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 <=> other -> -1, 0 or 1
364 * Compares *object* to *other* and returns -1, 0 or 1 if
365 * *object* is less than, equal or greater than *other*.
368 c_compare (VALUE self, VALUE other)
370 struct RArray *a, *b;
373 if (rb_obj_is_kind_of (other, CLASS_OF (self)) != Qtrue)
374 rb_raise (rb_eArgError, "invalid argument");
376 a = RARRAY (rb_iv_get (self, "items"));
377 b = RARRAY (rb_iv_get (other, "items"));
385 for (i = 0; i < a->len; i++) {
386 struct RArray *aa = RARRAY (a->ptr[i]);
387 struct RArray *bb = RARRAY (b->ptr[i]);
389 for (j = 0; j < 2; j++) {
392 tmp = rb_funcall (aa->ptr[j], id_compare, 1, bb->ptr[j]);
393 if (FIX2INT (tmp) != 0)
403 * object.each { |key, value| block } -> object
405 * Calls _block_ once for each tag in *object*, passing the key and
412 struct RArray *items;
415 items = RARRAY (rb_iv_get (self, "items"));
417 for (i = 0; i < items->len; i++) {
418 struct RArray *pair = RARRAY (items->ptr[i]);
420 rb_yield_values (2, pair->ptr[0], pair->ptr[1]);
428 * object.each_key { |key| block } -> object
430 * Calls _block_ once for each tag in *object*, passing the key
435 c_each_key (VALUE self)
437 struct RArray *items;
440 items = RARRAY (rb_iv_get (self, "items"));
442 for (i = 0; i < items->len; i++) {
443 struct RArray *pair = RARRAY (items->ptr[i]);
445 rb_yield (pair->ptr[0]);
453 * object.each_value { |value| block } -> object
455 * Calls _block_ once for each tag in *object*, passing the value
456 * of the tag. Returns *object*.
459 c_each_value (VALUE self)
461 struct RArray *items;
464 items = RARRAY (rb_iv_get (self, "items"));
466 for (i = 0; i < items->len; i++) {
467 struct RArray *pair = RARRAY (items->ptr[i]);
469 rb_yield (pair->ptr[1]);
476 Init_Comments (VALUE mVorbis)
480 c = rb_define_class_under (mVorbis, "Comments", rb_cObject);
482 rb_define_method (c, "inspect", c_inspect, 0);
483 rb_define_method (c, "clear", c_clear, 0);
484 rb_define_method (c, "delete", c_delete, 1);
485 rb_define_method (c, "length", c_length, 0);
486 rb_define_method (c, "has_key?", c_has_key, 1);
487 rb_define_method (c, "[]", c_aref, 1);
488 rb_define_method (c, "[]=", c_aset, 2);
489 rb_define_method (c, "empty?", c_get_empty, 0);
490 rb_define_method (c, "keys", c_keys, 0);
491 rb_define_method (c, "values", c_values, 0);
492 rb_define_method (c, "merge!", c_merge, 1);
494 rb_include_module (c, rb_mComparable);
495 rb_define_method (c, "<=>", c_compare, 1);
497 rb_include_module (c, rb_mEnumerable);
498 rb_define_method (c, "each", c_each, 0);
499 rb_define_method (c, "each_key", c_each_key, 0);
500 rb_define_method (c, "each_value", c_each_value, 0);
502 rb_define_alias (c, "size", "length");
503 rb_define_alias (c, "each_pair", "each");
504 rb_define_alias (c, "key?", "has_key?");
505 rb_define_alias (c, "include?", "has_key?");
506 rb_define_alias (c, "member?", "has_key?");
508 id_casecmp = rb_intern ("casecmp");
509 id_replace = rb_intern ("replace");
510 id_compare = rb_intern ("<=>");