2 * Copyright (C) 2006 Tilman Sauerbeck (tilman at code-monkey de)
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation, version 2.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 static ID id_casecmp, id_replace, id_compare;
30 comments_init (VALUE self, vcedit_state *state)
36 vc = vcedit_comments (state);
38 items = rb_iv_get (self, "items");
41 for (i = 0; i < vc->comments; i++) {
43 char *ptr, *content = vc->user_comments[i];
45 ptr = strchr (content, '=');
48 k = rb_str_new (content, ptr - content);
51 v = rb_str_new2 (ptr + 1);
53 pair = rb_ary_new3 (2, k, v);
56 rb_ary_store (items, i, pair);
61 comments_sync (VALUE self, vcedit_state *state)
67 vc = vcedit_comments (state);
69 vorbis_comment_clear (vc);
70 vorbis_comment_init (vc);
72 items = RARRAY (rb_iv_get (self, "items"));
74 for (i = 0; i < items->len; i++) {
75 struct RArray *pair = RARRAY (items->ptr[i]);
77 vorbis_comment_add_tag (vc,
78 StringValuePtr (pair->ptr[0]),
79 StringValuePtr (pair->ptr[1]));
84 * Ogg::Vorbis::Comments.new -> object
86 * Creates an Ogg::Vorbis::Comments object.
91 rb_iv_set (self, "items", rb_ary_new ());
98 * object.inspect -> string
100 * Returns the contents of *object* as a string.
103 c_inspect (VALUE self)
106 struct RArray *items;
109 items = RARRAY (rb_iv_get (self, "items"));
111 ret = rb_str_buf_new (128);
112 rb_str_buf_cat (ret, "{", 1);
114 for (i = 0; i < items->len; i++) {
115 struct RArray *pair = RARRAY (items->ptr[i]);
118 rb_str_buf_cat (ret, ", ", 2);
120 rb_str_buf_append (ret, rb_inspect (pair->ptr[0]));
121 rb_str_buf_cat (ret, "=>", 2);
122 rb_str_buf_append (ret, rb_inspect (pair->ptr[1]));
125 rb_str_buf_cat (ret, "}", 1);
132 * object.clear -> object
134 * Removes all elements from *object* and returns it.
139 rb_ary_clear (rb_iv_get (self, "items"));
146 * object.delete(key) -> string or nil
148 * If a tag with the specified key exists, that tag is deleted and
149 * the tag's value is returned. Otherwise, +nil+ is returned.
152 c_delete (VALUE self, VALUE key)
155 struct RArray *items;
158 items = RARRAY (rb_iv_get (self, "items"));
160 for (i = 0; i < items->len; i++) {
161 struct RArray *pair = RARRAY (items->ptr[i]);
164 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
165 if (tmp == INT2FIX (0)) {
173 rb_ary_delete_at (rb_iv_get (self, "items"), pos);
180 * object.keys -> array
182 * Returns an array that contains the keys of the tags in *object*.
188 struct RArray *items;
191 items = RARRAY (rb_iv_get (self, "items"));
192 ret = rb_ary_new2 (items->len);
194 for (i = 0; i < items->len; i++) {
195 struct RArray *pair = RARRAY (items->ptr[i]);
197 rb_ary_store (ret, i, pair->ptr[0]);
205 * object.values -> array
207 * Returns an array that contains the values of the tags in *object*.
210 c_values (VALUE self)
213 struct RArray *items;
216 items = RARRAY (rb_iv_get (self, "items"));
217 ret = rb_ary_new2 (items->len);
219 for (i = 0; i < items->len; i++) {
220 struct RArray *pair = RARRAY (items->ptr[i]);
222 rb_ary_store (ret, i, pair->ptr[1]);
230 * object.length -> integer
232 * Returns the number of tags in *object*.
235 c_length (VALUE self)
237 struct RArray *items;
239 items = RARRAY (rb_iv_get (self, "items"));
241 return LONG2NUM (items->len);
246 * object.empty? -> true or false
248 * Returns true if *object* is empty or false otherwise.
251 c_get_empty (VALUE self)
253 struct RArray *items;
255 items = RARRAY (rb_iv_get (self, "items"));
257 return items->len ? Qfalse : Qtrue;
262 * object[key] -> string
264 * Returns the value of the tag with the key *key* or +nil+ if the
265 * tag cannot be found.
268 c_aref (VALUE self, VALUE key)
270 struct RArray *items;
273 items = RARRAY (rb_iv_get (self, "items"));
275 for (i = 0; i < items->len; i++) {
276 struct RArray *pair = RARRAY (items->ptr[i]);
279 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
280 if (tmp == INT2FIX (0))
289 * object[key] = string
291 * Sets the value of the tag with the key *key* to *string*.
294 c_aset (VALUE self, VALUE key, VALUE value)
297 struct RArray *items;
300 items = RARRAY (rb_iv_get (self, "items"));
302 for (i = 0; i < items->len; i++) {
303 struct RArray *pair = RARRAY (items->ptr[i]);
306 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
307 if (tmp == INT2FIX (0)) {
308 rb_funcall (pair->ptr[1], id_replace, 1, value);
313 tmp = rb_ary_new3 (2, rb_str_dup_frozen (key), value);
316 rb_ary_push (rb_iv_get (self, "items"), tmp);
323 * object.has_key?(key) -> true or false
325 * Returns true if a tag exists with the specified key or false
329 c_has_key (VALUE self, VALUE key)
331 struct RArray *items;
334 items = RARRAY (rb_iv_get (self, "items"));
336 for (i = 0; i < items->len; i++) {
337 struct RArray *pair = RARRAY (items->ptr[i]);
340 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
341 if (tmp == INT2FIX (0))
349 merge_cb (VALUE key, VALUE value, VALUE self)
351 c_aset (self, key, value);
358 * object.merge!(hash) -> object
360 * Adds the key-value pairs from *hash* to *object*, overwriting existing
361 * values if a key already existed in *object*.
364 c_merge (VALUE self, VALUE hash)
366 Check_Type (hash, T_HASH);
368 rb_hash_foreach (hash, merge_cb, self);
375 * object.shift(hash) -> array or nil
377 * Removes the first key-value pair from *object* and returns it
378 * as the two-item array [key, value].
379 * If *object* is empty, +nil+ is returned.
384 return rb_ary_shift (rb_iv_get (self, "items"));
389 * object <=> other -> -1, 0 or 1
391 * Compares *object* to *other* and returns -1, 0 or 1 if
392 * *object* is less than, equal or greater than *other*.
395 c_compare (VALUE self, VALUE other)
397 struct RArray *a, *b;
400 if (rb_obj_is_kind_of (other, CLASS_OF (self)) != Qtrue)
401 rb_raise (rb_eArgError, "invalid argument");
403 a = RARRAY (rb_iv_get (self, "items"));
404 b = RARRAY (rb_iv_get (other, "items"));
412 for (i = 0; i < a->len; i++) {
413 struct RArray *aa = RARRAY (a->ptr[i]);
414 struct RArray *bb = RARRAY (b->ptr[i]);
416 for (j = 0; j < 2; j++) {
419 tmp = rb_funcall (aa->ptr[j], id_compare, 1, bb->ptr[j]);
420 if (FIX2INT (tmp) != 0)
430 * object.each { |key, value| block } -> object
432 * Calls _block_ once for each tag in *object*, passing the key and
439 struct RArray *items;
442 items = RARRAY (rb_iv_get (self, "items"));
444 for (i = 0; i < items->len; i++) {
445 struct RArray *pair = RARRAY (items->ptr[i]);
447 rb_yield_values (2, pair->ptr[0], pair->ptr[1]);
455 * object.each_key { |key| block } -> object
457 * Calls _block_ once for each tag in *object*, passing the key
462 c_each_key (VALUE self)
464 struct RArray *items;
467 items = RARRAY (rb_iv_get (self, "items"));
469 for (i = 0; i < items->len; i++) {
470 struct RArray *pair = RARRAY (items->ptr[i]);
472 rb_yield (pair->ptr[0]);
480 * object.each_value { |value| block } -> object
482 * Calls _block_ once for each tag in *object*, passing the value
483 * of the tag. Returns *object*.
486 c_each_value (VALUE self)
488 struct RArray *items;
491 items = RARRAY (rb_iv_get (self, "items"));
493 for (i = 0; i < items->len; i++) {
494 struct RArray *pair = RARRAY (items->ptr[i]);
496 rb_yield (pair->ptr[1]);
503 Init_Comments (VALUE mVorbis)
507 c = rb_define_class_under (mVorbis, "Comments", rb_cObject);
509 rb_define_method (c, "initialize", c_init, 0);
510 rb_define_method (c, "inspect", c_inspect, 0);
511 rb_define_method (c, "clear", c_clear, 0);
512 rb_define_method (c, "delete", c_delete, 1);
513 rb_define_method (c, "length", c_length, 0);
514 rb_define_method (c, "has_key?", c_has_key, 1);
515 rb_define_method (c, "[]", c_aref, 1);
516 rb_define_method (c, "[]=", c_aset, 2);
517 rb_define_method (c, "empty?", c_get_empty, 0);
518 rb_define_method (c, "keys", c_keys, 0);
519 rb_define_method (c, "values", c_values, 0);
520 rb_define_method (c, "merge!", c_merge, 1);
521 rb_define_method (c, "shift", c_shift, 0);
523 rb_include_module (c, rb_mComparable);
524 rb_define_method (c, "<=>", c_compare, 1);
526 rb_include_module (c, rb_mEnumerable);
527 rb_define_method (c, "each", c_each, 0);
528 rb_define_method (c, "each_key", c_each_key, 0);
529 rb_define_method (c, "each_value", c_each_value, 0);
531 rb_define_alias (c, "size", "length");
532 rb_define_alias (c, "each_pair", "each");
533 rb_define_alias (c, "key?", "has_key?");
534 rb_define_alias (c, "include?", "has_key?");
535 rb_define_alias (c, "member?", "has_key?");
537 id_casecmp = rb_intern ("casecmp");
538 id_replace = rb_intern ("replace");
539 id_compare = rb_intern ("<=>");