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_each, 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];
46 ptr = strchr (content, '=');
49 k_len = ptr - content;
50 k = rb_str_new (content, k_len);
53 v_len = vc->comment_lengths[i] - k_len - 1;
54 v = rb_str_new (ptr + 1, v_len);
56 pair = rb_ary_new3 (2, k, v);
59 rb_ary_store (items, i, pair);
64 comments_sync (VALUE self, vcedit_state *state)
70 vc = vcedit_comments (state);
72 vorbis_comment_clear (vc);
73 vorbis_comment_init (vc);
75 items = RARRAY (rb_iv_get (self, "items"));
77 for (i = 0; i < items->len; i++) {
78 struct RArray *pair = RARRAY (items->ptr[i]);
80 vorbis_comment_add_tag (vc,
81 StringValuePtr (pair->ptr[0]),
82 StringValuePtr (pair->ptr[1]));
87 * Ogg::Vorbis::Comments.new -> object
89 * Creates an Ogg::Vorbis::Comments object.
94 rb_iv_set (self, "items", rb_ary_new ());
101 * object.inspect -> string
103 * Returns the contents of *object* as a string.
106 c_inspect (VALUE self)
109 struct RArray *items;
112 items = RARRAY (rb_iv_get (self, "items"));
114 ret = rb_str_buf_new (128);
115 rb_str_buf_cat (ret, "{", 1);
117 for (i = 0; i < items->len; i++) {
118 struct RArray *pair = RARRAY (items->ptr[i]);
121 rb_str_buf_cat (ret, ", ", 2);
123 rb_str_buf_append (ret, rb_inspect (pair->ptr[0]));
124 rb_str_buf_cat (ret, "=>", 2);
125 rb_str_buf_append (ret, rb_inspect (pair->ptr[1]));
128 rb_str_buf_cat (ret, "}", 1);
135 * object.clear -> object
137 * Removes all elements from *object* and returns it.
142 rb_ary_clear (rb_iv_get (self, "items"));
149 * object.delete(key) -> string or nil
151 * If a tag with the specified key exists, that tag is deleted and
152 * the tag's value is returned. Otherwise, +nil+ is returned.
155 c_delete (VALUE self, VALUE key)
158 struct RArray *items;
161 items = RARRAY (rb_iv_get (self, "items"));
163 for (i = 0; i < items->len; i++) {
164 struct RArray *pair = RARRAY (items->ptr[i]);
167 tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key);
168 if (tmp == INT2FIX (0)) {
176 rb_ary_delete_at (rb_iv_get (self, "items"), pos);
183 * object.keys -> array
185 * Returns an array that contains the keys of the tags in *object*.
191 struct RArray *items;
194 items = RARRAY (rb_iv_get (self, "items"));
195 ret = rb_ary_new2 (items->len);
197 for (i = 0; i < items->len; i++) {
198 struct RArray *pair = RARRAY (items->ptr[i]);
200 rb_ary_store (ret, i, pair->ptr[0]);
208 * object.values -> array
210 * Returns an array that contains the values of the tags in *object*.
213 c_values (VALUE self)
216 struct RArray *items;
219 items = RARRAY (rb_iv_get (self, "items"));
220 ret = rb_ary_new2 (items->len);
222 for (i = 0; i < items->len; i++) {
223 struct RArray *pair = RARRAY (items->ptr[i]);
225 rb_ary_store (ret, i, pair->ptr[1]);
233 * object.length -> integer
235 * Returns the number of tags in *object*.
238 c_length (VALUE self)
240 struct RArray *items;
242 items = RARRAY (rb_iv_get (self, "items"));
244 return LONG2NUM (items->len);
249 * object.empty? -> true or false
251 * Returns true if *object* is empty or false otherwise.
254 c_get_empty (VALUE self)
256 struct RArray *items;
258 items = RARRAY (rb_iv_get (self, "items"));
260 return items->len ? Qfalse : Qtrue;
265 * object[key] -> string
267 * Returns the value of the tag with the key *key* or +nil+ if the
268 * tag cannot be found.
271 c_aref (VALUE self, VALUE key)
273 struct RArray *items;
276 items = RARRAY (rb_iv_get (self, "items"));
278 for (i = 0; i < items->len; i++) {
279 struct RArray *pair = RARRAY (items->ptr[i]);
282 tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key);
283 if (tmp == INT2FIX (0))
292 * object[key] = string
294 * Sets the value of the tag with the key *key* to *string*.
297 c_aset (VALUE self, VALUE key, VALUE value)
300 struct RArray *items;
303 items = RARRAY (rb_iv_get (self, "items"));
305 for (i = 0; i < items->len; i++) {
306 struct RArray *pair = RARRAY (items->ptr[i]);
309 tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key);
310 if (tmp == INT2FIX (0)) {
311 rb_funcall2 (pair->ptr[1], id_replace, 1, &value);
316 tmp = rb_ary_new3 (2, rb_str_dup_frozen (key), value);
319 rb_ary_push (rb_iv_get (self, "items"), tmp);
326 * object.has_key?(key) -> true or false
328 * Returns true if a tag exists with the specified key or false
332 c_has_key (VALUE self, VALUE key)
334 struct RArray *items;
337 items = RARRAY (rb_iv_get (self, "items"));
339 for (i = 0; i < items->len; i++) {
340 struct RArray *pair = RARRAY (items->ptr[i]);
343 tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key);
344 if (tmp == INT2FIX (0))
352 merge_cb (VALUE ar, VALUE self)
354 struct RArray *pair = RARRAY (ar);
356 c_aset (self, pair->ptr[0], pair->ptr[1]);
363 * object.merge!(arg) -> object
365 * Adds the key-value pairs from *arg* to *object*, overwriting existing
366 * values if a key already existed in *object*.
368 * Note that *arg*'s each method needs to yield key-value pairs for this
369 * to work. This means that e.g. hashes and Ogg::Vorbis::Comments objects
370 * are supported as arguments.
373 c_merge (VALUE self, VALUE arg)
375 if (!rb_respond_to (arg, id_each))
376 rb_raise (rb_eArgError, "invalid argument");
378 rb_iterate (rb_each, arg, merge_cb, self);
385 * object.shift(hash) -> array or nil
387 * Removes the first key-value pair from *object* and returns it
388 * as the two-item array [key, value].
389 * If *object* is empty, +nil+ is returned.
394 return rb_ary_shift (rb_iv_get (self, "items"));
399 * object <=> other -> -1, 0 or 1
401 * Compares *object* to *other* and returns -1, 0 or 1 if
402 * *object* is less than, equal or greater than *other*.
405 c_compare (VALUE self, VALUE other)
407 struct RArray *a, *b;
410 if (rb_obj_is_kind_of (other, CLASS_OF (self)) != Qtrue)
411 rb_raise (rb_eArgError, "invalid argument");
413 a = RARRAY (rb_iv_get (self, "items"));
414 b = RARRAY (rb_iv_get (other, "items"));
422 for (i = 0; i < a->len; i++) {
423 struct RArray *aa = RARRAY (a->ptr[i]);
424 struct RArray *bb = RARRAY (b->ptr[i]);
426 for (j = 0; j < 2; j++) {
429 tmp = rb_funcall2 (aa->ptr[j], id_compare, 1, &bb->ptr[j]);
430 if (FIX2INT (tmp) != 0)
440 * object.each { |key, value| block } -> object
442 * Calls _block_ once for each tag in *object*, passing the key and
449 struct RArray *items;
452 items = RARRAY (rb_iv_get (self, "items"));
454 for (i = 0; i < items->len; i++) {
455 struct RArray *pair = RARRAY (items->ptr[i]);
457 rb_yield_values (2, pair->ptr[0], pair->ptr[1]);
465 * object.each_key { |key| block } -> object
467 * Calls _block_ once for each tag in *object*, passing the key
472 c_each_key (VALUE self)
474 struct RArray *items;
477 items = RARRAY (rb_iv_get (self, "items"));
479 for (i = 0; i < items->len; i++) {
480 struct RArray *pair = RARRAY (items->ptr[i]);
482 rb_yield (pair->ptr[0]);
490 * object.each_value { |value| block } -> object
492 * Calls _block_ once for each tag in *object*, passing the value
493 * of the tag. Returns *object*.
496 c_each_value (VALUE self)
498 struct RArray *items;
501 items = RARRAY (rb_iv_get (self, "items"));
503 for (i = 0; i < items->len; i++) {
504 struct RArray *pair = RARRAY (items->ptr[i]);
506 rb_yield (pair->ptr[1]);
513 Init_Comments (VALUE mVorbis)
517 c = rb_define_class_under (mVorbis, "Comments", rb_cObject);
519 rb_define_method (c, "initialize", c_init, 0);
520 rb_define_method (c, "inspect", c_inspect, 0);
521 rb_define_method (c, "clear", c_clear, 0);
522 rb_define_method (c, "delete", c_delete, 1);
523 rb_define_method (c, "length", c_length, 0);
524 rb_define_method (c, "has_key?", c_has_key, 1);
525 rb_define_method (c, "[]", c_aref, 1);
526 rb_define_method (c, "[]=", c_aset, 2);
527 rb_define_method (c, "empty?", c_get_empty, 0);
528 rb_define_method (c, "keys", c_keys, 0);
529 rb_define_method (c, "values", c_values, 0);
530 rb_define_method (c, "merge!", c_merge, 1);
531 rb_define_method (c, "shift", c_shift, 0);
533 rb_include_module (c, rb_mComparable);
534 rb_define_method (c, "<=>", c_compare, 1);
536 rb_include_module (c, rb_mEnumerable);
537 rb_define_method (c, "each", c_each, 0);
538 rb_define_method (c, "each_key", c_each_key, 0);
539 rb_define_method (c, "each_value", c_each_value, 0);
541 rb_define_alias (c, "size", "length");
542 rb_define_alias (c, "each_pair", "each");
543 rb_define_alias (c, "key?", "has_key?");
544 rb_define_alias (c, "include?", "has_key?");
545 rb_define_alias (c, "member?", "has_key?");
547 id_casecmp = rb_intern ("casecmp");
548 id_replace = rb_intern ("replace");
549 id_each = rb_intern ("each");
550 id_compare = rb_intern ("<=>");