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,
26 static ID id_casecmp, id_replace, id_compare;
29 comments_init (VALUE self, vcedit_state *state)
35 vc = vcedit_comments (state);
37 items = rb_ary_new2 (vc->comments);
38 rb_iv_set (self, "items", items);
40 for (i = 0; i < vc->comments; i++) {
42 char *ptr, *content = vc->user_comments[i];
44 ptr = strchr (content, '=');
47 k = rb_str_new (content, ptr - content);
50 v = rb_str_new2 (ptr + 1);
52 pair = rb_ary_new3 (2, k, v);
55 rb_ary_store (items, i, pair);
60 comments_sync (VALUE self, vcedit_state *state)
66 vc = vcedit_comments (state);
68 vorbis_comment_clear (vc);
69 vorbis_comment_init (vc);
71 items = RARRAY (rb_iv_get (self, "items"));
73 for (i = 0; i < items->len; i++) {
74 struct RArray *pair = RARRAY (items->ptr[i]);
76 vorbis_comment_add_tag (vc,
77 StringValuePtr (pair->ptr[0]),
78 StringValuePtr (pair->ptr[1]));
84 * object.inspect -> string
86 * Returns the contents of *object* as a string.
89 c_inspect (VALUE self)
95 items = RARRAY (rb_iv_get (self, "items"));
97 ret = rb_str_buf_new (128);
98 rb_str_buf_cat (ret, "{", 1);
100 for (i = 0; i < items->len; i++) {
101 struct RArray *pair = RARRAY (items->ptr[i]);
104 rb_str_buf_cat (ret, ", ", 2);
106 rb_str_buf_append (ret, rb_inspect (pair->ptr[0]));
107 rb_str_buf_cat (ret, "=>", 2);
108 rb_str_buf_append (ret, rb_inspect (pair->ptr[1]));
111 rb_str_buf_cat (ret, "}", 1);
118 * object.clear -> object
120 * Removes all elements from *object* and returns it.
125 rb_ary_clear (rb_iv_get (self, "items"));
132 * object.delete(key) -> string or nil
134 * If a tag with the specified key exists, that tag is deleted and
135 * the tag's value is returned. Otherwise, +nil+ is returned.
138 c_delete (VALUE self, VALUE key)
141 struct RArray *items;
144 items = RARRAY (rb_iv_get (self, "items"));
146 for (i = 0; i < items->len; i++) {
147 struct RArray *pair = RARRAY (items->ptr[i]);
150 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
151 if (tmp == INT2FIX (0)) {
159 rb_ary_delete_at (rb_iv_get (self, "items"), pos);
166 * object.keys -> array
168 * Returns an array that contains the keys of the tags in *object*.
174 struct RArray *items;
177 items = RARRAY (rb_iv_get (self, "items"));
178 ret = rb_ary_new2 (items->len);
180 for (i = 0; i < items->len; i++) {
181 struct RArray *pair = RARRAY (items->ptr[i]);
183 rb_ary_store (ret, i, pair->ptr[0]);
191 * object.values -> array
193 * Returns an array that contains the values of the tags in *object*.
196 c_values (VALUE self)
199 struct RArray *items;
202 items = RARRAY (rb_iv_get (self, "items"));
203 ret = rb_ary_new2 (items->len);
205 for (i = 0; i < items->len; i++) {
206 struct RArray *pair = RARRAY (items->ptr[i]);
208 rb_ary_store (ret, i, pair->ptr[1]);
216 * object.length -> integer
218 * Returns the number of tags in *object*.
221 c_length (VALUE self)
223 struct RArray *items;
225 items = RARRAY (rb_iv_get (self, "items"));
227 return LONG2NUM (items->len);
232 * object.empty? -> true or false
234 * Returns true if *object* is empty or false otherwise.
237 c_get_empty (VALUE self)
239 struct RArray *items;
241 items = RARRAY (rb_iv_get (self, "items"));
243 return items->len ? Qfalse : Qtrue;
248 * object[key] -> string
250 * Returns the value of the tag with the key *key* or +nil+ if the
251 * tag cannot be found.
254 c_aref (VALUE self, VALUE key)
256 struct RArray *items;
259 items = RARRAY (rb_iv_get (self, "items"));
261 for (i = 0; i < items->len; i++) {
262 struct RArray *pair = RARRAY (items->ptr[i]);
265 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
266 if (tmp == INT2FIX (0))
275 * object[key] = string
277 * Sets the value of the tag with the key *key* to *string*.
280 c_aset (VALUE self, VALUE key, VALUE value)
283 struct RArray *items;
286 items = RARRAY (rb_iv_get (self, "items"));
288 for (i = 0; i < items->len; i++) {
289 struct RArray *pair = RARRAY (items->ptr[i]);
292 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
293 if (tmp == INT2FIX (0)) {
294 rb_funcall (pair->ptr[1], id_replace, 1, value);
299 tmp = rb_ary_new3 (2, rb_str_dup_frozen (key), value);
302 rb_ary_push (rb_iv_get (self, "items"), tmp);
309 * object.has_key?(key) -> true or false
311 * Returns true if a tag exists with the specified key or false
315 c_has_key (VALUE self, VALUE key)
317 struct RArray *items;
320 items = RARRAY (rb_iv_get (self, "items"));
322 for (i = 0; i < items->len; i++) {
323 struct RArray *pair = RARRAY (items->ptr[i]);
326 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
327 if (tmp == INT2FIX (0))
336 * object <=> other -> -1, 0 or 1
338 * Compares *object* to *other* and returns -1, 0 or 1 if
339 * *object* is less than, equal or greater than *other*.
342 c_compare (VALUE self, VALUE other)
344 struct RArray *a, *b;
347 if (rb_obj_is_kind_of (other, CLASS_OF (self)) != Qtrue)
348 rb_raise (rb_eArgError, "invalid argument");
350 a = RARRAY (rb_iv_get (self, "items"));
351 b = RARRAY (rb_iv_get (other, "items"));
359 for (i = 0; i < a->len; i++) {
360 struct RArray *aa = RARRAY (a->ptr[i]);
361 struct RArray *bb = RARRAY (b->ptr[i]);
363 for (j = 0; j < 2; j++) {
366 tmp = rb_funcall (aa->ptr[j], id_compare, 1, bb->ptr[j]);
367 if (FIX2INT (tmp) != 0)
377 * object.each { |key, value| block } -> object
379 * Calls _block_ once for each tag in *object*, passing the key and
386 struct RArray *items;
389 items = RARRAY (rb_iv_get (self, "items"));
391 for (i = 0; i < items->len; i++) {
392 struct RArray *pair = RARRAY (items->ptr[i]);
394 rb_yield_values (2, pair->ptr[0], pair->ptr[1]);
402 * object.each_key { |key| block } -> object
404 * Calls _block_ once for each tag in *object*, passing the key
409 c_each_key (VALUE self)
411 struct RArray *items;
414 items = RARRAY (rb_iv_get (self, "items"));
416 for (i = 0; i < items->len; i++) {
417 struct RArray *pair = RARRAY (items->ptr[i]);
419 rb_yield (pair->ptr[0]);
427 * object.each_value { |value| block } -> object
429 * Calls _block_ once for each tag in *object*, passing the value
430 * of the tag. Returns *object*.
433 c_each_value (VALUE self)
435 struct RArray *items;
438 items = RARRAY (rb_iv_get (self, "items"));
440 for (i = 0; i < items->len; i++) {
441 struct RArray *pair = RARRAY (items->ptr[i]);
443 rb_yield (pair->ptr[1]);
450 Init_Comments (VALUE mVorbis)
454 c = rb_define_class_under (mVorbis, "Comments", rb_cObject);
456 rb_define_method (c, "inspect", c_inspect, 0);
457 rb_define_method (c, "clear", c_clear, 0);
458 rb_define_method (c, "delete", c_delete, 1);
459 rb_define_method (c, "length", c_length, 0);
460 rb_define_method (c, "has_key?", c_has_key, 1);
461 rb_define_method (c, "[]", c_aref, 1);
462 rb_define_method (c, "[]=", c_aset, 2);
463 rb_define_method (c, "empty?", c_get_empty, 0);
464 rb_define_method (c, "keys", c_keys, 0);
465 rb_define_method (c, "values", c_values, 0);
467 rb_include_module (c, rb_mComparable);
468 rb_define_method (c, "<=>", c_compare, 1);
470 rb_include_module (c, rb_mEnumerable);
471 rb_define_method (c, "each", c_each, 0);
472 rb_define_method (c, "each_key", c_each_key, 0);
473 rb_define_method (c, "each_value", c_each_value, 0);
475 rb_define_alias (c, "size", "length");
476 rb_define_alias (c, "each_pair", "each");
477 rb_define_alias (c, "key?", "has_key?");
478 rb_define_alias (c, "include?", "has_key?");
479 rb_define_alias (c, "member?", "has_key?");
481 id_casecmp = rb_intern ("casecmp");
482 id_replace = rb_intern ("replace");
483 id_compare = rb_intern ("<=>");