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,
32 static ID id_casecmp, id_replace, id_compare;
35 comments_init (VALUE self, vcedit_state *state)
41 Data_Get_Struct (self, RbVorbisComments, o);
44 vcedit_state_ref (state);
46 vc = vcedit_comments (o->state);
48 o->items = rb_ary_new2 (vc->comments);
50 for (i = 0; i < vc->comments; i++) {
52 char *ptr, *content = vc->user_comments[i];
54 ptr = strchr (content, '=');
57 k = rb_str_new (content, ptr - content);
60 v = rb_str_new2 (ptr + 1);
62 pair = rb_ary_new3 (2, k, v);
65 rb_ary_store (o->items, i, pair);
70 comments_sync (VALUE self)
77 Data_Get_Struct (self, RbVorbisComments, o);
79 vc = vcedit_comments (o->state);
81 vorbis_comment_clear (vc);
82 vorbis_comment_init (vc);
84 items = RARRAY (o->items);
86 for (i = 0; i < items->len; i++) {
87 struct RArray *pair = RARRAY (items->ptr[i]);
89 vorbis_comment_add_tag (vc,
90 StringValuePtr (pair->ptr[0]),
91 StringValuePtr (pair->ptr[1]));
96 c_mark (RbVorbisComments *o)
98 rb_gc_mark (o->items);
102 c_free (RbVorbisComments *o)
104 vcedit_state_unref (o->state);
110 c_alloc (VALUE klass)
114 return Data_Make_Struct (klass, RbVorbisComments, c_mark, c_free, o);
119 * object.inspect -> string
121 * Returns the contents of *object* as a string.
124 c_inspect (VALUE self)
128 struct RArray *items;
131 Data_Get_Struct (self, RbVorbisComments, o);
133 items = RARRAY (o->items);
135 ret = rb_str_buf_new (128);
136 rb_str_buf_cat (ret, "{", 1);
138 for (i = 0; i < items->len; i++) {
139 struct RArray *pair = RARRAY (items->ptr[i]);
142 rb_str_buf_cat (ret, ", ", 2);
144 rb_str_buf_append (ret, rb_inspect (pair->ptr[0]));
145 rb_str_buf_cat (ret, "=>", 2);
146 rb_str_buf_append (ret, rb_inspect (pair->ptr[1]));
149 rb_str_buf_cat (ret, "}", 1);
156 * object.clear -> object
158 * Removes all elements from *object* and returns it.
165 Data_Get_Struct (self, RbVorbisComments, o);
167 rb_ary_clear (o->items);
174 * object.delete(key) -> string or nil
176 * If a tag with the specified key exists, that tag is deleted and
177 * the tag's value is returned. Otherwise, +nil+ is returned.
180 c_delete (VALUE self, VALUE key)
184 struct RArray *items;
187 Data_Get_Struct (self, RbVorbisComments, o);
189 items = RARRAY (o->items);
191 for (i = 0; i < items->len; i++) {
192 struct RArray *pair = RARRAY (items->ptr[i]);
195 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
196 if (tmp == INT2FIX (0)) {
204 rb_ary_delete_at (o->items, pos);
211 * object.keys -> array
213 * Returns an array that contains the keys of the tags in *object*.
220 struct RArray *items;
223 Data_Get_Struct (self, RbVorbisComments, o);
225 items = RARRAY (o->items);
226 ret = rb_ary_new2 (items->len);
228 for (i = 0; i < items->len; i++) {
229 struct RArray *pair = RARRAY (items->ptr[i]);
231 rb_ary_store (ret, i, pair->ptr[0]);
239 * object.values -> array
241 * Returns an array that contains the values of the tags in *object*.
244 c_values (VALUE self)
248 struct RArray *items;
251 Data_Get_Struct (self, RbVorbisComments, o);
253 items = RARRAY (o->items);
254 ret = rb_ary_new2 (items->len);
256 for (i = 0; i < items->len; i++) {
257 struct RArray *pair = RARRAY (items->ptr[i]);
259 rb_ary_store (ret, i, pair->ptr[1]);
267 * object.length -> integer
269 * Returns the number of tags in *object*.
272 c_length (VALUE self)
276 Data_Get_Struct (self, RbVorbisComments, o);
278 return LONG2NUM (RARRAY (o->items)->len);
283 * object.empty? -> true or false
285 * Returns true if *object* is empty or false otherwise.
288 c_get_empty (VALUE self)
292 Data_Get_Struct (self, RbVorbisComments, o);
294 return RARRAY(o->items)->len ? Qfalse : Qtrue;
299 * object[key] -> string
301 * Returns the value of the tag with the key *key* or +nil+ if the
302 * tag cannot be found.
305 c_aref (VALUE self, VALUE key)
308 struct RArray *items;
311 Data_Get_Struct (self, RbVorbisComments, o);
313 items = RARRAY (o->items);
315 for (i = 0; i < items->len; i++) {
316 struct RArray *pair = RARRAY (items->ptr[i]);
319 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
320 if (tmp == INT2FIX (0))
329 * object[key] = string
331 * Sets the value of the tag with the key *key* to *string*.
334 c_aset (VALUE self, VALUE key, VALUE value)
338 struct RArray *items;
341 Data_Get_Struct (self, RbVorbisComments, o);
343 items = RARRAY (o->items);
345 for (i = 0; i < items->len; i++) {
346 struct RArray *pair = RARRAY (items->ptr[i]);
349 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
350 if (tmp == INT2FIX (0)) {
351 rb_funcall (pair->ptr[1], id_replace, 1, value);
356 tmp = rb_ary_new3 (2, rb_str_dup_frozen (key), value);
359 rb_ary_push (o->items, tmp);
366 * object.has_key?(key) -> true or false
368 * Returns true if a tag exists with the specified key or false
372 c_has_key (VALUE self, VALUE key)
375 struct RArray *items;
378 Data_Get_Struct (self, RbVorbisComments, o);
380 items = RARRAY (o->items);
382 for (i = 0; i < items->len; i++) {
383 struct RArray *pair = RARRAY (items->ptr[i]);
386 tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key);
387 if (tmp == INT2FIX (0))
396 * object <=> other -> -1, 0 or 1
398 * Compares *object* to *other* and returns -1, 0 or 1 if
399 * *object* is less than, equal or greater than *other*.
402 c_compare (VALUE self, VALUE other)
404 RbVorbisComments *o, *o2;
405 struct RArray *a, *b;
408 if (rb_obj_is_kind_of (other, CLASS_OF (self)) != Qtrue)
409 rb_raise (rb_eArgError, "invalid argument");
411 Data_Get_Struct (self, RbVorbisComments, o);
412 Data_Get_Struct (other, RbVorbisComments, o2);
414 a = RARRAY (o->items);
415 b = RARRAY (o2->items);
423 for (i = 0; i < a->len; i++) {
424 struct RArray *aa = RARRAY (a->ptr[i]);
425 struct RArray *bb = RARRAY (b->ptr[i]);
427 for (j = 0; j < 2; j++) {
430 tmp = rb_funcall (aa->ptr[j], id_compare, 1, bb->ptr[j]);
431 if (FIX2INT (tmp) != 0)
441 * object.each { |key, value| block } -> object
443 * Calls _block_ once for each tag in *object*, passing the key and
451 struct RArray *items;
454 Data_Get_Struct (self, RbVorbisComments, o);
456 items = RARRAY (o->items);
458 for (i = 0; i < items->len; i++) {
459 struct RArray *pair = RARRAY (items->ptr[i]);
461 rb_yield_values (2, pair->ptr[0], pair->ptr[1]);
469 * object.each_key { |key| block } -> object
471 * Calls _block_ once for each tag in *object*, passing the key
476 c_each_key (VALUE self)
479 struct RArray *items;
482 Data_Get_Struct (self, RbVorbisComments, o);
484 items = RARRAY (o->items);
486 for (i = 0; i < items->len; i++) {
487 struct RArray *pair = RARRAY (items->ptr[i]);
489 rb_yield (pair->ptr[0]);
497 * object.each_value { |value| block } -> object
499 * Calls _block_ once for each tag in *object*, passing the value
500 * of the tag. Returns *object*.
503 c_each_value (VALUE self)
506 struct RArray *items;
509 Data_Get_Struct (self, RbVorbisComments, o);
511 items = RARRAY (o->items);
513 for (i = 0; i < items->len; i++) {
514 struct RArray *pair = RARRAY (items->ptr[i]);
516 rb_yield (pair->ptr[1]);
523 Init_Comments (VALUE mVorbis)
527 c = rb_define_class_under (mVorbis, "Comments", rb_cObject);
529 rb_define_alloc_func (c, c_alloc);
531 rb_define_method (c, "inspect", c_inspect, 0);
532 rb_define_method (c, "clear", c_clear, 0);
533 rb_define_method (c, "delete", c_delete, 1);
534 rb_define_method (c, "length", c_length, 0);
535 rb_define_method (c, "has_key?", c_has_key, 1);
536 rb_define_method (c, "[]", c_aref, 1);
537 rb_define_method (c, "[]=", c_aset, 2);
538 rb_define_method (c, "empty?", c_get_empty, 0);
539 rb_define_method (c, "keys", c_keys, 0);
540 rb_define_method (c, "values", c_values, 0);
542 rb_include_module (c, rb_mComparable);
543 rb_define_method (c, "<=>", c_compare, 1);
545 rb_include_module (c, rb_mEnumerable);
546 rb_define_method (c, "each", c_each, 0);
547 rb_define_method (c, "each_key", c_each_key, 0);
548 rb_define_method (c, "each_value", c_each_value, 0);
550 rb_define_alias (c, "size", "length");
551 rb_define_alias (c, "each_pair", "each");
552 rb_define_alias (c, "key?", "has_key?");
553 rb_define_alias (c, "include?", "has_key?");
554 rb_define_alias (c, "member?", "has_key?");
556 id_casecmp = rb_intern ("casecmp");
557 id_replace = rb_intern ("replace");
558 id_compare = rb_intern ("<=>");