    /*
     * call-seq:
     *   from_memory(string, url = nil, encoding = nil, options = 0)
     *
     * Create a new reader that parses +string+
     */
    static VALUE from_memory(int argc, VALUE *argv, VALUE klass)
    {
      VALUE rb_buffer, rb_url, encoding, rb_options;
      xmlTextReaderPtr reader;
      const char * c_url      = NULL;
      const char * c_encoding = NULL;
      int c_options           = 0;
      VALUE rb_reader, args[3];

      rb_scan_args(argc, argv, "13", &rb_buffer, &rb_url, &encoding, &rb_options);

      if (!RTEST(rb_buffer)) rb_raise(rb_eArgError, "string cannot be nil");
      if (RTEST(rb_url)) c_url = StringValuePtr(rb_url);
      if (RTEST(encoding)) c_encoding = StringValuePtr(encoding);
      if (RTEST(rb_options)) c_options = (int)NUM2INT(rb_options);

      reader = xmlReaderForMemory(
          StringValuePtr(rb_buffer),
          (int)RSTRING_LEN(rb_buffer),
          c_url,
          c_encoding,
          c_options
      );

      if(reader == NULL) {
        xmlFreeTextReader(reader);
        rb_raise(rb_eRuntimeError, "couldn't create a parser");
      }

      rb_reader = Data_Wrap_Struct(klass, NULL, dealloc, reader);
      args[0] = rb_buffer;
      args[1] = rb_url;
      args[2] = encoding;
      rb_obj_call_init(rb_reader, 3, args);

      return rb_reader;
    }