Relaxed rules for Ogg::Vorbis::Comments#merge!.
[ruby-vorbistagger.git] / ext / comments.c
index f7919dbdac1e20219a8a45dd70d79a1361aa5f95..03a237b104f87d0fbfd77f78e165dae2a828fb34 100644 (file)
@@ -24,7 +24,7 @@
 
 #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)
@@ -35,8 +35,8 @@ 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;
@@ -79,6 +79,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:
@@ -332,27 +345,34 @@ c_has_key (VALUE self, VALUE key)
        return Qfalse;
 }
 
-static int
-merge_cb (VALUE key, VALUE value, VALUE self)
+static VALUE
+merge_cb (VALUE ar, VALUE self)
 {
-       c_aset (self, key, value);
+       struct RArray *pair = RARRAY (ar);
+
+       c_aset (self, pair->ptr[0], pair->ptr[1]);
 
-       return ST_CONTINUE;
+       return Qnil;
 }
 
 /*
  * call-seq:
- *  object.merge!(hash) -> object
+ *  object.merge!(arg) -> object
  *
- * Adds the key-value pairs from *hash* to *object*, overwriting existing
+ * 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 hash)
+c_merge (VALUE self, VALUE arg)
 {
-       Check_Type (hash, T_HASH);
+       if (!rb_respond_to (arg, id_each))
+               rb_raise (rb_eArgError, "invalid argument");
 
-       rb_hash_foreach (hash, merge_cb, self);
+       rb_iterate (rb_each, arg, merge_cb, self);
 
        return self;
 }
@@ -493,6 +513,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);
@@ -522,6 +543,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;