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_ary_new2 (vc->comments);
39 rb_iv_set (self, "items", 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]));
85 * object.inspect -> string
87 * Returns the contents of *object* as a string.
90 c_inspect (VALUE self)
96 items = RARRAY (rb_iv_get (self, "items"));
98 ret = rb_str_buf_new (128);
99 rb_str_buf_cat (ret, "{", 1);
101 for (i = 0; i < items->len; i++) {
102 struct RArray *pair = RARRAY (items->ptr[i]);
105 rb_str_buf_cat (ret, ", ", 2);
107 rb_str_buf_append (ret, rb_inspect (pair->ptr[0]));
108 rb_str_buf_cat (ret, "=>", 2);
109 rb_str_buf_append (ret, rb_inspect (pair->ptr[1]));
112 rb_str_buf_cat (ret, "}", 1);
119 * object.clear -> object
121 * Removes all elements from *object* and returns it.
126 rb_ary_clear (rb_iv_get (self, "items"));
133 * object.delete(key) -> string or nil
135 * If a tag with the specified key exists, that tag is deleted and
136 * the tag's value is returned. Otherwise, +nil+ is returned.
139 c_delete (VALUE self, VALUE key)
142 struct RArray *items;
145 items = RARRAY (rb_iv_get (self, "items"));
147 for (i = 0; i < items->len; i++) {
148 struct RArray *pair = RARRAY (items->ptr[i]);
151 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
152 if (tmp == INT2FIX (0)) {
160 rb_ary_delete_at (rb_iv_get (self, "items"), pos);
167 * object.keys -> array
169 * Returns an array that contains the keys of the tags in *object*.
175 struct RArray *items;
178 items = RARRAY (rb_iv_get (self, "items"));
179 ret = rb_ary_new2 (items->len);
181 for (i = 0; i < items->len; i++) {
182 struct RArray *pair = RARRAY (items->ptr[i]);
184 rb_ary_store (ret, i, pair->ptr[0]);
192 * object.values -> array
194 * Returns an array that contains the values of the tags in *object*.
197 c_values (VALUE self)
200 struct RArray *items;
203 items = RARRAY (rb_iv_get (self, "items"));
204 ret = rb_ary_new2 (items->len);
206 for (i = 0; i < items->len; i++) {
207 struct RArray *pair = RARRAY (items->ptr[i]);
209 rb_ary_store (ret, i, pair->ptr[1]);
217 * object.length -> integer
219 * Returns the number of tags in *object*.
222 c_length (VALUE self)
224 struct RArray *items;
226 items = RARRAY (rb_iv_get (self, "items"));
228 return LONG2NUM (items->len);
233 * object.empty? -> true or false
235 * Returns true if *object* is empty or false otherwise.
238 c_get_empty (VALUE self)
240 struct RArray *items;
242 items = RARRAY (rb_iv_get (self, "items"));
244 return items->len ? Qfalse : Qtrue;
249 * object[key] -> string
251 * Returns the value of the tag with the key *key* or +nil+ if the
252 * tag cannot be found.
255 c_aref (VALUE self, VALUE key)
257 struct RArray *items;
260 items = RARRAY (rb_iv_get (self, "items"));
262 for (i = 0; i < items->len; i++) {
263 struct RArray *pair = RARRAY (items->ptr[i]);
266 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
267 if (tmp == INT2FIX (0))
276 * object[key] = string
278 * Sets the value of the tag with the key *key* to *string*.
281 c_aset (VALUE self, VALUE key, VALUE value)
284 struct RArray *items;
287 items = RARRAY (rb_iv_get (self, "items"));
289 for (i = 0; i < items->len; i++) {
290 struct RArray *pair = RARRAY (items->ptr[i]);
293 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
294 if (tmp == INT2FIX (0)) {
295 rb_funcall (pair->ptr[1], id_replace, 1, value);
300 tmp = rb_ary_new3 (2, rb_str_dup_frozen (key), value);
303 rb_ary_push (rb_iv_get (self, "items"), tmp);
310 * object.has_key?(key) -> true or false
312 * Returns true if a tag exists with the specified key or false
316 c_has_key (VALUE self, VALUE key)
318 struct RArray *items;
321 items = RARRAY (rb_iv_get (self, "items"));
323 for (i = 0; i < items->len; i++) {
324 struct RArray *pair = RARRAY (items->ptr[i]);
327 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
328 if (tmp == INT2FIX (0))
336 merge_cb (VALUE key, VALUE value, VALUE self)
338 c_aset (self, key, value);
345 * object.merge!(hash) -> object
347 * Adds the key-value pairs from *hash* to *object*, overwriting existing
348 * values if a key already existed in *object*.
351 c_merge (VALUE self, VALUE hash)
353 Check_Type (hash, T_HASH);
355 rb_hash_foreach (hash, merge_cb, self);
362 * object.shift(hash) -> array or nil
364 * Removes the first key-value pair from *object* and returns it
365 * as the two-item array [key, value].
366 * If *object* is empty, +nil+ is returned.
371 return rb_ary_shift (rb_iv_get (self, "items"));
376 * object <=> other -> -1, 0 or 1
378 * Compares *object* to *other* and returns -1, 0 or 1 if
379 * *object* is less than, equal or greater than *other*.
382 c_compare (VALUE self, VALUE other)
384 struct RArray *a, *b;
387 if (rb_obj_is_kind_of (other, CLASS_OF (self)) != Qtrue)
388 rb_raise (rb_eArgError, "invalid argument");
390 a = RARRAY (rb_iv_get (self, "items"));
391 b = RARRAY (rb_iv_get (other, "items"));
399 for (i = 0; i < a->len; i++) {
400 struct RArray *aa = RARRAY (a->ptr[i]);
401 struct RArray *bb = RARRAY (b->ptr[i]);
403 for (j = 0; j < 2; j++) {
406 tmp = rb_funcall (aa->ptr[j], id_compare, 1, bb->ptr[j]);
407 if (FIX2INT (tmp) != 0)
417 * object.each { |key, value| block } -> object
419 * Calls _block_ once for each tag in *object*, passing the key and
426 struct RArray *items;
429 items = RARRAY (rb_iv_get (self, "items"));
431 for (i = 0; i < items->len; i++) {
432 struct RArray *pair = RARRAY (items->ptr[i]);
434 rb_yield_values (2, pair->ptr[0], pair->ptr[1]);
442 * object.each_key { |key| block } -> object
444 * Calls _block_ once for each tag in *object*, passing the key
449 c_each_key (VALUE self)
451 struct RArray *items;
454 items = RARRAY (rb_iv_get (self, "items"));
456 for (i = 0; i < items->len; i++) {
457 struct RArray *pair = RARRAY (items->ptr[i]);
459 rb_yield (pair->ptr[0]);
467 * object.each_value { |value| block } -> object
469 * Calls _block_ once for each tag in *object*, passing the value
470 * of the tag. Returns *object*.
473 c_each_value (VALUE self)
475 struct RArray *items;
478 items = RARRAY (rb_iv_get (self, "items"));
480 for (i = 0; i < items->len; i++) {
481 struct RArray *pair = RARRAY (items->ptr[i]);
483 rb_yield (pair->ptr[1]);
490 Init_Comments (VALUE mVorbis)
494 c = rb_define_class_under (mVorbis, "Comments", rb_cObject);
496 rb_define_method (c, "inspect", c_inspect, 0);
497 rb_define_method (c, "clear", c_clear, 0);
498 rb_define_method (c, "delete", c_delete, 1);
499 rb_define_method (c, "length", c_length, 0);
500 rb_define_method (c, "has_key?", c_has_key, 1);
501 rb_define_method (c, "[]", c_aref, 1);
502 rb_define_method (c, "[]=", c_aset, 2);
503 rb_define_method (c, "empty?", c_get_empty, 0);
504 rb_define_method (c, "keys", c_keys, 0);
505 rb_define_method (c, "values", c_values, 0);
506 rb_define_method (c, "merge!", c_merge, 1);
507 rb_define_method (c, "shift", c_shift, 0);
509 rb_include_module (c, rb_mComparable);
510 rb_define_method (c, "<=>", c_compare, 1);
512 rb_include_module (c, rb_mEnumerable);
513 rb_define_method (c, "each", c_each, 0);
514 rb_define_method (c, "each_key", c_each_key, 0);
515 rb_define_method (c, "each_value", c_each_value, 0);
517 rb_define_alias (c, "size", "length");
518 rb_define_alias (c, "each_pair", "each");
519 rb_define_alias (c, "key?", "has_key?");
520 rb_define_alias (c, "include?", "has_key?");
521 rb_define_alias (c, "member?", "has_key?");
523 id_casecmp = rb_intern ("casecmp");
524 id_replace = rb_intern ("replace");
525 id_compare = rb_intern ("<=>");