X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=ext%2Fcomments.c;h=6e6efd58460b787f541c82a1cbda9ccda9b5a7b9;hb=HEAD;hp=a2569866a62766062a292d9719f0233fd75a1185;hpb=0ebbf4f00aa8b375b4a781b0a0397d0fce5466e1;p=ruby-vorbistagger.git diff --git a/ext/comments.c b/ext/comments.c index a256986..6e6efd5 100644 --- a/ext/comments.c +++ b/ext/comments.c @@ -17,13 +17,14 @@ */ #include +#include #include #include #include #include "vcedit.h" -static ID id_casecmp, id_replace, id_compare; +static ID id_casecmp, id_replace, id_each, id_compare; void comments_init (VALUE self, vcedit_state *state) @@ -34,20 +35,23 @@ comments_init (VALUE self, vcedit_state *state) vc = vcedit_comments (state); - items = rb_ary_new2 (vc->comments); - rb_iv_set (self, "items", items); + items = rb_iv_get (self, "items"); + rb_ary_clear (items); for (i = 0; i < vc->comments; i++) { VALUE k, v, pair; char *ptr, *content = vc->user_comments[i]; + int k_len, v_len; ptr = strchr (content, '='); assert (ptr); - k = rb_str_new (content, ptr - content); + k_len = ptr - content; + k = rb_str_new (content, k_len); OBJ_FREEZE (k); - v = rb_str_new2 (ptr + 1); + v_len = vc->comment_lengths[i] - k_len - 1; + v = rb_str_new (ptr + 1, v_len); pair = rb_ary_new3 (2, k, v); OBJ_FREEZE (pair); @@ -78,6 +82,19 @@ comments_sync (VALUE self, vcedit_state *state) StringValuePtr (pair->ptr[1])); } } +/* + * call-seq: + * Ogg::Vorbis::Comments.new -> object + * + * Creates an Ogg::Vorbis::Comments object. + */ +static VALUE +c_init (VALUE self) +{ + rb_iv_set (self, "items", rb_ary_new ()); + + return self; +} /* * call-seq: @@ -147,7 +164,7 @@ c_delete (VALUE self, VALUE key) struct RArray *pair = RARRAY (items->ptr[i]); VALUE tmp; - tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key); + tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key); if (tmp == INT2FIX (0)) { ret = pair->ptr[1]; pos = i; @@ -262,7 +279,7 @@ c_aref (VALUE self, VALUE key) struct RArray *pair = RARRAY (items->ptr[i]); VALUE tmp; - tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key); + tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key); if (tmp == INT2FIX (0)) return pair->ptr[1]; } @@ -289,9 +306,9 @@ c_aset (VALUE self, VALUE key, VALUE value) struct RArray *pair = RARRAY (items->ptr[i]); VALUE tmp; - tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key); + tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key); if (tmp == INT2FIX (0)) { - rb_funcall (pair->ptr[1], id_replace, 1, value); + rb_funcall2 (pair->ptr[1], id_replace, 1, &value); return pair->ptr[1]; } } @@ -323,7 +340,7 @@ c_has_key (VALUE self, VALUE key) struct RArray *pair = RARRAY (items->ptr[i]); VALUE tmp; - tmp = rb_funcall (pair->ptr[0], id_casecmp, 1, key); + tmp = rb_funcall2 (pair->ptr[0], id_casecmp, 1, &key); if (tmp == INT2FIX (0)) return Qtrue; } @@ -331,6 +348,52 @@ c_has_key (VALUE self, VALUE key) return Qfalse; } +static VALUE +merge_cb (VALUE ar, VALUE self) +{ + struct RArray *pair = RARRAY (ar); + + c_aset (self, pair->ptr[0], pair->ptr[1]); + + return Qnil; +} + +/* + * call-seq: + * object.merge!(arg) -> object + * + * Adds the key-value pairs from *arg* to *object*, overwriting existing + * values if a key already existed in *object*. + * + * Note that *arg*'s each method needs to yield key-value pairs for this + * to work. This means that e.g. hashes and Ogg::Vorbis::Comments objects + * are supported as arguments. + */ +static VALUE +c_merge (VALUE self, VALUE arg) +{ + if (!rb_respond_to (arg, id_each)) + rb_raise (rb_eArgError, "invalid argument"); + + rb_iterate (rb_each, arg, merge_cb, self); + + return self; +} + +/* + * call-seq: + * object.shift(hash) -> array or nil + * + * Removes the first key-value pair from *object* and returns it + * as the two-item array [key, value]. + * If *object* is empty, +nil+ is returned. + */ +static VALUE +c_shift (VALUE self) +{ + return rb_ary_shift (rb_iv_get (self, "items")); +} + /* * call-seq: * object <=> other -> -1, 0 or 1 @@ -363,7 +426,7 @@ c_compare (VALUE self, VALUE other) for (j = 0; j < 2; j++) { VALUE tmp; - tmp = rb_funcall (aa->ptr[j], id_compare, 1, bb->ptr[j]); + tmp = rb_funcall2 (aa->ptr[j], id_compare, 1, &bb->ptr[j]); if (FIX2INT (tmp) != 0) return tmp; } @@ -453,6 +516,7 @@ Init_Comments (VALUE mVorbis) c = rb_define_class_under (mVorbis, "Comments", rb_cObject); + rb_define_method (c, "initialize", c_init, 0); rb_define_method (c, "inspect", c_inspect, 0); rb_define_method (c, "clear", c_clear, 0); rb_define_method (c, "delete", c_delete, 1); @@ -463,6 +527,8 @@ Init_Comments (VALUE mVorbis) rb_define_method (c, "empty?", c_get_empty, 0); rb_define_method (c, "keys", c_keys, 0); rb_define_method (c, "values", c_values, 0); + rb_define_method (c, "merge!", c_merge, 1); + rb_define_method (c, "shift", c_shift, 0); rb_include_module (c, rb_mComparable); rb_define_method (c, "<=>", c_compare, 1); @@ -480,6 +546,7 @@ Init_Comments (VALUE mVorbis) id_casecmp = rb_intern ("casecmp"); id_replace = rb_intern ("replace"); + id_each = rb_intern ("each"); id_compare = rb_intern ("<=>"); return c;