    /*
     * call-seq:
     *  read_memory(string, url, encoding, options)
     *
     * Create a new document from a String
     */
    static VALUE read_memory( VALUE klass,
                              VALUE string,
                              VALUE url,
                              VALUE encoding,
                              VALUE options )
    {
      const char * c_buffer = StringValuePtr(string);
      const char * c_url    = NIL_P(url)      ? NULL : StringValuePtr(url);
      const char * c_enc    = NIL_P(encoding) ? NULL : StringValuePtr(encoding);
      int len               = (int)RSTRING_LEN(string);
      VALUE error_list      = rb_ary_new();
      VALUE document;
      xmlDocPtr doc;

      xmlResetLastError();
      xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
      doc = xmlReadMemory(c_buffer, len, c_url, c_enc, (int)NUM2INT(options));
      xmlSetStructuredErrorFunc(NULL, NULL);

      if(doc == NULL) {
        xmlErrorPtr error;

        xmlFreeDoc(doc);

        error = xmlGetLastError();
        if(error)
          rb_exc_raise(Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error));
        else
          rb_raise(rb_eRuntimeError, "Could not parse document");

        return Qnil;
      }

      document = Nokogiri_wrap_xml_document(klass, doc);
      rb_iv_set(document, "@errors", error_list);
      return document;
    }