libxml-ruby 4.1.2 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY +17 -0
  3. data/README.rdoc +7 -16
  4. data/ext/libxml/ruby_libxml.h +43 -44
  5. data/ext/libxml/ruby_xml.c +0 -343
  6. data/ext/libxml/ruby_xml.h +9 -10
  7. data/ext/libxml/ruby_xml_attributes.h +2 -0
  8. data/ext/libxml/ruby_xml_document.c +6 -6
  9. data/ext/libxml/ruby_xml_document.h +11 -11
  10. data/ext/libxml/ruby_xml_dtd.c +85 -79
  11. data/ext/libxml/ruby_xml_encoding.h +20 -18
  12. data/ext/libxml/ruby_xml_error.c +9 -6
  13. data/ext/libxml/ruby_xml_error.h +2 -2
  14. data/ext/libxml/ruby_xml_html_parser_context.c +35 -21
  15. data/ext/libxml/ruby_xml_namespace.c +0 -3
  16. data/ext/libxml/ruby_xml_node.c +1394 -1398
  17. data/ext/libxml/ruby_xml_parser.h +1 -1
  18. data/ext/libxml/ruby_xml_parser_context.c +47 -39
  19. data/ext/libxml/ruby_xml_parser_options.c +9 -1
  20. data/ext/libxml/ruby_xml_parser_options.h +1 -1
  21. data/ext/libxml/ruby_xml_reader.c +15 -16
  22. data/ext/libxml/ruby_xml_sax2_handler.c +1 -1
  23. data/ext/libxml/ruby_xml_sax_parser.c +1 -9
  24. data/ext/libxml/ruby_xml_schema.c +4 -4
  25. data/ext/libxml/ruby_xml_version.h +5 -5
  26. data/ext/libxml/ruby_xml_writer.c +8 -8
  27. data/ext/libxml/ruby_xml_xpath.c +1 -1
  28. data/ext/libxml/ruby_xml_xpath_context.c +2 -2
  29. data/ext/libxml/ruby_xml_xpath_expression.c +1 -1
  30. data/lib/libxml/document.rb +15 -15
  31. data/lib/libxml/html_parser.rb +23 -23
  32. data/lib/libxml/parser.rb +26 -24
  33. data/test/test.rb +5 -0
  34. data/test/test_document.rb +8 -0
  35. data/test/test_document_write.rb +1 -4
  36. data/test/test_dtd.rb +5 -8
  37. data/test/test_encoding.rb +1 -4
  38. data/test/test_helper.rb +9 -2
  39. data/test/test_html_parser.rb +162 -162
  40. data/test/test_namespace.rb +1 -3
  41. data/test/test_node.rb +1 -3
  42. data/test/test_node_write.rb +1 -4
  43. data/test/test_parser.rb +26 -17
  44. data/test/test_reader.rb +4 -4
  45. data/test/test_sax_parser.rb +1 -1
  46. data/test/test_xml.rb +0 -99
  47. metadata +3 -2
@@ -124,112 +124,118 @@ static VALUE rxml_dtd_type(VALUE self)
124
124
 
125
125
  /*
126
126
  * call-seq:
127
- * XML::Dtd.new("DTD string") -> dtd
128
- * XML::Dtd.new("public", "system") -> dtd
129
- * XML::Dtd.new("name", "public", "system", document) -> external subset dtd
130
- * XML::Dtd.new("name", "public", "system", document, false) -> internal subset dtd
131
- * XML::Dtd.new("name", "public", "system", document, true) -> internal subset dtd
127
+ * XML::Dtd.new(dtd_string) -> dtd
128
+ * XML::Dtd.new(external_id, system_id) -> dtd
129
+ * XML::Dtd.new(external_id, system_id, name, document, internal) -> dtd
132
130
  *
133
- * Create a new Dtd from the specified public and system
134
- * identifiers.
131
+ * Create a new Dtd from the specified public and system identifiers:
132
+ *
133
+ * * The first usage creates a DTD from a string and requires 1 parameter.
134
+ * * The second usage loads and parses an external DTD and requires 2 parameters.
135
+ * * The third usage creates a new internal or external DTD and requires 3 parameters and 2 optional parameters.
136
+ * It then attaches the DTD to the specified document if it is not nil
137
+ *
138
+ * Parameters:
139
+ *
140
+ * dtd_string - A string that contains a complete DTD
141
+ * external_id - A string that specifies the DTD's external name. For example, "-//W3C//DTD XHTML 1.0 Transitional//EN"
142
+ * system_id - A string that specififies the DTD's system name. For example, "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
143
+ * name - A string that specifies the DTD's name. For example "xhtml1".
144
+ * document - A xml document.
145
+ * internal - Boolean value indicating whether this is an internal or external DTD. Optional. If not specified
146
+ * then external is assumed.
135
147
  */
136
148
  static VALUE rxml_dtd_initialize(int argc, VALUE *argv, VALUE self)
137
149
  {
138
- VALUE external, system, dtd_string;
139
- xmlParserInputBufferPtr buffer;
140
- xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
141
- xmlChar *new_string;
142
150
  xmlDtdPtr xdtd;
151
+ VALUE external, system;
143
152
 
144
- // 1 argument -- string --> parsujeme jako dtd
145
- // 2 arguments -- public, system --> bude se hledat
146
- // 3 arguments -- public, system, name --> creates an external subset (any parameter may be nil)
147
- // 4 arguments -- public, system, name, doc --> creates an external subset (any parameter may be nil)
148
- // 5 arguments -- public, system, name, doc, true --> creates an internal subset (all but last parameter may be nil)
149
153
  switch (argc)
150
154
  {
151
- case 3:
152
- case 4:
153
- case 5: {
154
- VALUE name, doc, internal;
155
- const xmlChar *xname = NULL, *xpublic = NULL, *xsystem = NULL;
156
- xmlDocPtr xdoc = NULL;
155
+ case 3:
156
+ case 4:
157
+ case 5:
158
+ {
159
+ const xmlChar *xname = NULL, *xpublic = NULL, *xsystem = NULL;
160
+ xmlDocPtr xdoc = NULL;
157
161
 
158
- rb_scan_args(argc, argv, "32", &external, &system, &name, &doc, &internal);
162
+ VALUE name, doc, internal;
163
+ rb_scan_args(argc, argv, "32", &external, &system, &name, &doc, &internal);
159
164
 
160
- if (external != Qnil) {
161
- Check_Type(external, T_STRING);
162
- xpublic = (const xmlChar*) StringValuePtr(external);
163
- }
164
- if (system != Qnil) {
165
- Check_Type(system, T_STRING);
166
- xsystem = (const xmlChar*) StringValuePtr(system);
167
- }
168
- if (name != Qnil) {
169
- Check_Type(name, T_STRING);
170
- xname = (const xmlChar*) StringValuePtr(name);
171
- }
172
- if (doc != Qnil) {
173
- if (rb_obj_is_kind_of(doc, cXMLDocument) == Qfalse)
174
- rb_raise(rb_eTypeError, "Must pass an LibXML::XML::Document object");
175
- Data_Get_Struct(doc, xmlDoc, xdoc);
176
- }
165
+ Check_Type(external, T_STRING);
166
+ xpublic = (const xmlChar*) StringValuePtr(external);
177
167
 
178
- if (internal == Qnil || internal == Qfalse)
179
- xdtd = xmlNewDtd(xdoc, xname, xpublic, xsystem);
180
- else
181
- xdtd = xmlCreateIntSubset(xdoc, xname, xpublic, xsystem);
168
+ Check_Type(system, T_STRING);
169
+ xsystem = (const xmlChar*) StringValuePtr(system);
182
170
 
183
- if (xdtd == NULL)
184
- rxml_raise(&xmlLastError);
171
+ Check_Type(name, T_STRING);
172
+ xname = (const xmlChar*) StringValuePtr(name);
185
173
 
186
- /* Document will free this dtd now. */
187
- RDATA(self)->dfree = NULL;
188
- DATA_PTR(self) = xdtd;
174
+ if (doc != Qnil)
175
+ {
176
+ if (rb_obj_is_kind_of(doc, cXMLDocument) == Qfalse)
177
+ rb_raise(rb_eTypeError, "Must pass an LibXML::XML::Document object");
178
+ Data_Get_Struct(doc, xmlDoc, xdoc);
179
+ }
189
180
 
190
- xmlSetTreeDoc((xmlNodePtr) xdtd, xdoc);
191
- }
192
- break;
181
+ if (internal == Qnil || internal == Qfalse)
182
+ xdtd = xmlNewDtd(xdoc, xname, xpublic, xsystem);
183
+ else
184
+ xdtd = xmlCreateIntSubset(xdoc, xname, xpublic, xsystem);
193
185
 
194
- case 2:
195
- rb_scan_args(argc, argv, "20", &external, &system);
186
+ if (xdtd == NULL)
187
+ rxml_raise(xmlGetLastError());
196
188
 
197
- Check_Type(external, T_STRING);
198
- Check_Type(system, T_STRING);
189
+ /* The document will free the dtd so Ruby should not */
190
+ RDATA(self)->dfree = NULL;
191
+ DATA_PTR(self) = xdtd;
199
192
 
200
- xdtd = xmlParseDTD((xmlChar*) StringValuePtr(external),
201
- (xmlChar*) StringValuePtr(system));
193
+ xmlSetTreeDoc((xmlNodePtr) xdtd, xdoc);
194
+ }
195
+ break;
202
196
 
203
- if (xdtd == NULL)
204
- rxml_raise(&xmlLastError);
197
+ case 2:
198
+ {
199
+ rb_scan_args(argc, argv, "20", &external, &system);
205
200
 
206
- DATA_PTR(self) = xdtd;
201
+ Check_Type(external, T_STRING);
202
+ Check_Type(system, T_STRING);
207
203
 
208
- xmlSetTreeDoc((xmlNodePtr) xdtd, NULL);
209
- break;
204
+ xdtd = xmlParseDTD((xmlChar*) StringValuePtr(external), (xmlChar*) StringValuePtr(system));
210
205
 
211
- case 1:
212
- rb_scan_args(argc, argv, "10", &dtd_string);
213
- Check_Type(dtd_string, T_STRING);
206
+ if (xdtd == NULL)
207
+ rxml_raise(xmlGetLastError());
214
208
 
215
- /* Note that buffer is freed by xmlParserInputBufferPush*/
216
- buffer = xmlAllocParserInputBuffer(enc);
217
- new_string = xmlStrdup((xmlChar*) StringValuePtr(dtd_string));
218
- xmlParserInputBufferPush(buffer, xmlStrlen(new_string),
219
- (const char*) new_string);
209
+ DATA_PTR(self) = xdtd;
220
210
 
221
- xdtd = xmlIOParseDTD(NULL, buffer, enc);
211
+ xmlSetTreeDoc((xmlNodePtr) xdtd, NULL);
212
+ break;
213
+ }
214
+ case 1:
215
+ {
216
+ VALUE dtd_string;
217
+ rb_scan_args(argc, argv, "10", &dtd_string);
218
+ Check_Type(dtd_string, T_STRING);
222
219
 
223
- if (xdtd == NULL)
224
- rxml_raise(&xmlLastError);
220
+ /* Note that buffer is freed by xmlParserInputBufferPush*/
221
+ xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
222
+ xmlParserInputBufferPtr buffer = xmlAllocParserInputBuffer(enc);
223
+ xmlChar *new_string = xmlStrdup((xmlChar*) StringValuePtr(dtd_string));
224
+ xmlParserInputBufferPush(buffer, xmlStrlen(new_string),
225
+ (const char*) new_string);
225
226
 
226
- xmlFree(new_string);
227
+ xdtd = xmlIOParseDTD(NULL, buffer, enc);
227
228
 
228
- DATA_PTR(self) = xdtd;
229
- break;
229
+ if (xdtd == NULL)
230
+ rxml_raise(xmlGetLastError());
230
231
 
231
- default:
232
- rb_raise(rb_eArgError, "wrong number of arguments");
232
+ xmlFree(new_string);
233
+
234
+ DATA_PTR(self) = xdtd;
235
+ break;
236
+ }
237
+ default:
238
+ rb_raise(rb_eArgError, "wrong number of arguments");
233
239
  }
234
240
 
235
241
  return self;
@@ -1,18 +1,20 @@
1
- /* Please see the LICENSE file for copyright and distribution information */
2
-
3
- #ifndef __RXML_ENCODING__
4
- #define __RXML_ENCODING__
5
-
6
- #include <ruby/encoding.h>
7
-
8
- extern VALUE mXMLEncoding;
9
-
10
- void rxml_init_encoding();
11
-
12
- VALUE rxml_new_cstr(const xmlChar* xstr, const xmlChar* xencoding);
13
- VALUE rxml_new_cstr_len(const xmlChar* xstr, const long length, const xmlChar* xencoding);
14
-
15
- rb_encoding* rxml_xml_encoding_to_rb_encoding(VALUE klass, xmlCharEncoding xmlEncoding);
16
- rb_encoding* rxml_figure_encoding(const xmlChar* xencoding);
17
-
18
- #endif
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RXML_ENCODING__
4
+ #define __RXML_ENCODING__
5
+
6
+ #include <ruby/encoding.h>
7
+ #include <libxml/encoding.h>
8
+ #include <libxml/xmlstring.h>
9
+
10
+ extern VALUE mXMLEncoding;
11
+
12
+ void rxml_init_encoding(void);
13
+
14
+ VALUE rxml_new_cstr(const xmlChar* xstr, const xmlChar* xencoding);
15
+ VALUE rxml_new_cstr_len(const xmlChar* xstr, const long length, const xmlChar* xencoding);
16
+
17
+ rb_encoding* rxml_xml_encoding_to_rb_encoding(VALUE klass, xmlCharEncoding xmlEncoding);
18
+ rb_encoding* rxml_figure_encoding(const xmlChar* xencoding);
19
+
20
+ #endif
@@ -50,7 +50,7 @@ static VALUE rxml_error_get_handler(VALUE self)
50
50
  return block;
51
51
  }
52
52
 
53
- VALUE rxml_error_wrap(xmlErrorPtr xerror)
53
+ VALUE rxml_error_wrap(const xmlError *xerror)
54
54
  {
55
55
  VALUE result = Qnil;
56
56
 
@@ -97,7 +97,7 @@ VALUE rxml_error_wrap(xmlErrorPtr xerror)
97
97
  }
98
98
 
99
99
  /* Hook that receives xml error message */
100
- static void structuredErrorFunc(void *userData, xmlErrorPtr xerror)
100
+ static void structuredErrorFunc(void *userData, const xmlError *xerror)
101
101
  {
102
102
  VALUE error = rxml_error_wrap(xerror);
103
103
 
@@ -158,11 +158,14 @@ static VALUE rxml_error_reset_handler(VALUE self)
158
158
  return self;
159
159
  }
160
160
 
161
- NORETURN(void rxml_raise(xmlErrorPtr xerror))
161
+ void rxml_raise(const xmlError *xerror)
162
162
  {
163
- /* Wrap error up as Ruby object and send it off to ruby */
164
- VALUE error = rxml_error_wrap(xerror);
165
- rb_exc_raise(error);
163
+ if (xerror)
164
+ {
165
+ /* Wrap error up as Ruby object and send it off to ruby */
166
+ VALUE error = rxml_error_wrap(xerror);
167
+ rb_exc_raise(error);
168
+ }
166
169
  }
167
170
 
168
171
  void rxml_init_error(void)
@@ -8,7 +8,7 @@
8
8
  extern VALUE eXMLError;
9
9
 
10
10
  void rxml_init_error(void);
11
- VALUE rxml_error_wrap(xmlErrorPtr xerror);
12
- NORETURN(void rxml_raise(xmlErrorPtr xerror));
11
+ VALUE rxml_error_wrap(const xmlError *xerror);
12
+ void rxml_raise(const xmlError *xerror);
13
13
 
14
14
  #endif
@@ -146,19 +146,23 @@ static VALUE rxml_html_parser_context_wrap(htmlParserCtxtPtr ctxt)
146
146
  *
147
147
  * Parameters:
148
148
  *
149
- * file - A filename or uri.
149
+ * file - A filename or uri
150
+ * options - A or'ed together list of LibXML::XML::HTMLParser::Options values
150
151
  */
151
- static VALUE rxml_html_parser_context_file(VALUE klass, VALUE file)
152
+ static VALUE rxml_html_parser_context_file(int argc, VALUE* argv, VALUE klass)
152
153
  {
154
+ VALUE file, options;
155
+ rb_scan_args(argc, argv, "11", &file, &options);
156
+
153
157
  htmlParserCtxtPtr ctxt = htmlCreateFileParserCtxt(StringValuePtr(file), NULL);
154
158
  if (!ctxt)
155
- rxml_raise(&xmlLastError);
159
+ rxml_raise(xmlGetLastError());
156
160
 
157
161
  /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
158
162
  xmlCtxtUseOptionsInternal (called below) initialize slightly different
159
163
  context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
160
164
  sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
161
- htmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
165
+ htmlCtxtUseOptions(ctxt, options == Qnil ? 0 : NUM2INT(options));
162
166
 
163
167
  return rxml_html_parser_context_wrap(ctxt);
164
168
  }
@@ -170,10 +174,14 @@ static VALUE rxml_html_parser_context_file(VALUE klass, VALUE file)
170
174
  *
171
175
  * Parameters:
172
176
  *
173
- * io - A ruby IO object.
177
+ * io - A ruby IO object
178
+ * options - A or'ed together list of LibXML::XML::HTMLParser::Options values
174
179
  */
175
- static VALUE rxml_html_parser_context_io(VALUE klass, VALUE io)
180
+ static VALUE rxml_html_parser_context_io(int argc, VALUE* argv, VALUE klass)
176
181
  {
182
+ VALUE io, options;
183
+ rb_scan_args(argc, argv, "11", &io, &options);
184
+
177
185
  VALUE result;
178
186
  htmlParserCtxtPtr ctxt;
179
187
  xmlParserInputBufferPtr input;
@@ -189,14 +197,14 @@ static VALUE rxml_html_parser_context_io(VALUE klass, VALUE io)
189
197
  if (!ctxt)
190
198
  {
191
199
  xmlFreeParserInputBuffer(input);
192
- rxml_raise(&xmlLastError);
200
+ rxml_raise(xmlGetLastError());
193
201
  }
194
202
 
195
203
  /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
196
204
  xmlCtxtUseOptionsInternal (called below) initialize slightly different
197
205
  context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
198
206
  sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
199
- htmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
207
+ htmlCtxtUseOptions(ctxt, options == Qnil ? 0 : NUM2INT(options));
200
208
 
201
209
  stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
202
210
 
@@ -204,7 +212,7 @@ static VALUE rxml_html_parser_context_io(VALUE klass, VALUE io)
204
212
  {
205
213
  xmlFreeParserInputBuffer(input);
206
214
  xmlFreeParserCtxt(ctxt);
207
- rxml_raise(&xmlLastError);
215
+ rxml_raise(xmlGetLastError());
208
216
  }
209
217
  inputPush(ctxt, stream);
210
218
  result = rxml_html_parser_context_wrap(ctxt);
@@ -222,29 +230,35 @@ static VALUE rxml_html_parser_context_io(VALUE klass, VALUE io)
222
230
  *
223
231
  * Parameters:
224
232
  *
225
- * string - A string that contains the data to parse.
233
+ * string - A string that contains the data to parse
234
+ * options - A or'ed together list of LibXML::XML::HTMLParser::Options values
226
235
  */
227
- static VALUE rxml_html_parser_context_string(VALUE klass, VALUE string)
236
+ static VALUE rxml_html_parser_context_string(int argc, VALUE* argv, VALUE klass)
228
237
  {
229
- htmlParserCtxtPtr ctxt;
238
+ VALUE string, options;
239
+ rb_scan_args(argc, argv, "11", &string, &options);
240
+
230
241
  Check_Type(string, T_STRING);
231
242
 
232
243
  if (RSTRING_LEN(string) == 0)
233
244
  rb_raise(rb_eArgError, "Must specify a string with one or more characters");
234
245
 
235
- ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(string),
246
+ htmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(string),
236
247
  (int)RSTRING_LEN(string));
237
248
  if (!ctxt)
238
- rxml_raise(&xmlLastError);
249
+ rxml_raise(xmlGetLastError());
239
250
 
240
251
  /* This is annoying, but xmlInitParserCtxt (called indirectly above) and
241
252
  xmlCtxtUseOptionsInternal (called below) initialize slightly different
242
253
  context options, in particular XML_PARSE_NODICT which xmlInitParserCtxt
243
254
  sets to 0 and xmlCtxtUseOptionsInternal sets to 1. So we have to call both. */
244
- htmlCtxtUseOptions(ctxt, rxml_libxml_default_options());
255
+ htmlCtxtUseOptions(ctxt, options == Qnil ? 0 : NUM2INT(options));
245
256
 
246
- if (ctxt->sax != NULL)
247
- memcpy(ctxt->sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandlerV1));
257
+ // Setup sax handler
258
+ // TODO - there must be a better way? The sax handler is initialized for XML, but we want
259
+ // to use HTML
260
+ memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
261
+ xmlSAX2InitHtmlDefaultSAXHandler(ctxt->sax);
248
262
 
249
263
  return rxml_html_parser_context_wrap(ctxt);
250
264
  }
@@ -288,7 +302,7 @@ static VALUE rxml_html_parser_context_disable_cdata_set(VALUE self, VALUE value)
288
302
  if (value)
289
303
  ctxt->sax->cdataBlock = NULL;
290
304
  else
291
- ctxt->sax->cdataBlock = htmlDefaultSAXHandler.cdataBlock;
305
+ ctxt->sax->cdataBlock = xmlSAX2CDataBlock;
292
306
 
293
307
  return value;
294
308
  }
@@ -328,9 +342,9 @@ void rxml_init_html_parser_context(void)
328
342
  IO_ATTR = ID2SYM(rb_intern("@io"));
329
343
  cXMLHtmlParserContext = rb_define_class_under(cXMLHtmlParser, "Context", cXMLParserContext);
330
344
 
331
- rb_define_singleton_method(cXMLHtmlParserContext, "file", rxml_html_parser_context_file, 1);
332
- rb_define_singleton_method(cXMLHtmlParserContext, "io", rxml_html_parser_context_io, 1);
333
- rb_define_singleton_method(cXMLHtmlParserContext, "string", rxml_html_parser_context_string, 1);
345
+ rb_define_singleton_method(cXMLHtmlParserContext, "file", rxml_html_parser_context_file, -1);
346
+ rb_define_singleton_method(cXMLHtmlParserContext, "io", rxml_html_parser_context_io, -1);
347
+ rb_define_singleton_method(cXMLHtmlParserContext, "string", rxml_html_parser_context_string, -1);
334
348
  rb_define_method(cXMLHtmlParserContext, "close", rxml_html_parser_context_close, 0);
335
349
  rb_define_method(cXMLHtmlParserContext, "disable_cdata=", rxml_html_parser_context_disable_cdata_set, 1);
336
350
  rb_define_method(cXMLHtmlParserContext, "options=", rxml_html_parser_context_options_set, 1);
@@ -58,9 +58,6 @@ static VALUE rxml_namespace_initialize(VALUE self, VALUE node, VALUE prefix,
58
58
  xmlPrefix = NIL_P(prefix) ? NULL : (xmlChar *)StringValuePtr(prefix);
59
59
  xns = xmlNewNs(xnode, (xmlChar*) StringValuePtr(href), xmlPrefix);
60
60
 
61
- if (!xns)
62
- rxml_raise(&xmlLastError);
63
-
64
61
  DATA_PTR(self) = xns;
65
62
  return self;
66
63
  }