nokolexbor 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,15 +5,15 @@ extern VALUE cNokolexborNode;
5
5
  VALUE cNokolexborNodeSet;
6
6
  extern rb_data_type_t nl_document_type;
7
7
 
8
- VALUE nl_node_at_css(VALUE self, VALUE selector);
9
- VALUE nl_node_css(VALUE self, VALUE selector);
10
-
11
- typedef VALUE (*nl_node_find_f)(VALUE self, VALUE selector);
8
+ lxb_status_t nl_node_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx);
9
+ void sort_nodes_if_necessary(VALUE selector, lxb_dom_document_t *doc, lexbor_array_t *array);
10
+ lxb_status_t nl_node_at_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx);
11
+ lxb_status_t nl_node_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx);
12
12
 
13
13
  lxb_status_t
14
14
  lexbor_array_push_unique(lexbor_array_t *array, void *value)
15
15
  {
16
- for (int i = 0; i < array->length; i++)
16
+ for (size_t i = 0; i < array->length; i++)
17
17
  if (array->list[i] == value)
18
18
  return LXB_STATUS_STOPPED;
19
19
 
@@ -91,7 +91,7 @@ nl_node_set_delete(VALUE self, VALUE rb_node)
91
91
  lexbor_array_t *array = nl_rb_node_set_unwrap(self);
92
92
  lxb_dom_node_t *node = nl_rb_node_unwrap(rb_node);
93
93
 
94
- int i;
94
+ size_t i;
95
95
  for (i = 0; i < array->length; i++)
96
96
  if (array->list[i] == node)
97
97
  {
@@ -113,7 +113,7 @@ nl_node_set_is_include(VALUE self, VALUE rb_node)
113
113
  lexbor_array_t *array = nl_rb_node_set_unwrap(self);
114
114
  lxb_dom_node_t *node = nl_rb_node_unwrap(rb_node);
115
115
 
116
- for (int i = 0; i < array->length; i++)
116
+ for (size_t i = 0; i < array->length; i++)
117
117
  if (array->list[i] == node)
118
118
  {
119
119
  return Qtrue;
@@ -169,7 +169,7 @@ nl_node_set_subseq(VALUE self, long beg, long len)
169
169
  }
170
170
  }
171
171
 
172
- for (int j = beg; j < beg + len; ++j)
172
+ for (long j = beg; j < beg + len; ++j)
173
173
  {
174
174
  lxb_status_t status = lexbor_array_push(new_array, old_array->list[j]);
175
175
  if (status != LXB_STATUS_OK)
@@ -177,7 +177,7 @@ nl_node_set_subseq(VALUE self, long beg, long len)
177
177
  nl_raise_lexbor_error(status);
178
178
  }
179
179
  }
180
- return TypedData_Wrap_Struct(cNokolexborNodeSet, &nl_node_set_type, new_array);
180
+ return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
181
181
  }
182
182
 
183
183
  static VALUE
@@ -231,7 +231,7 @@ nl_node_set_to_array(VALUE self)
231
231
 
232
232
  VALUE list = rb_ary_new2(array->length);
233
233
  VALUE doc = nl_rb_document_get(self);
234
- for (int i = 0; i < array->length; i++)
234
+ for (size_t i = 0; i < array->length; i++)
235
235
  {
236
236
  lxb_dom_node_t *node = (lxb_dom_node_t *)array->list[i];
237
237
  VALUE rb_node = nl_rb_node_create(node, doc);
@@ -267,7 +267,7 @@ nl_node_set_union(VALUE self, VALUE other)
267
267
  memcpy(new_array->list, self_array->list, sizeof(lxb_dom_node_t *) * self_array->length);
268
268
  new_array->length = self_array->length;
269
269
 
270
- for (int i = 0; i < other_array->length; i++)
270
+ for (size_t i = 0; i < other_array->length; i++)
271
271
  {
272
272
  lexbor_array_push_unique(new_array, other_array->list[i]);
273
273
  }
@@ -275,16 +275,15 @@ nl_node_set_union(VALUE self, VALUE other)
275
275
  return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
276
276
  }
277
277
 
278
- static VALUE
279
- nl_node_set_find(VALUE self, VALUE selector, nl_node_find_f finder)
278
+ static lxb_status_t
279
+ nl_node_set_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx)
280
280
  {
281
- VALUE rb_doc = nl_rb_document_get(self);
282
- lxb_dom_document_t *doc;
283
- TypedData_Get_Struct(rb_doc, lxb_dom_document_t, &nl_document_type, doc);
281
+ lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
284
282
  if (doc == NULL)
285
283
  {
286
284
  rb_raise(rb_eRuntimeError, "Error getting document");
287
285
  }
286
+ // Wrap direct children with a temporary fragment so that they can be searched
288
287
  lxb_dom_document_fragment_t *frag = lxb_dom_document_fragment_interface_create(doc);
289
288
  if (frag == NULL)
290
289
  {
@@ -302,7 +301,7 @@ nl_node_set_find(VALUE self, VALUE selector, nl_node_find_f finder)
302
301
  }
303
302
  }
304
303
  // Backup original node data and re-group them into a fragment
305
- for (int i = 0; i < array->length; i++)
304
+ for (size_t i = 0; i < array->length; i++)
306
305
  {
307
306
  lxb_dom_node_t *node = (lxb_dom_node_t *)array->list[i];
308
307
  lxb_dom_node_t *backup_node = malloc(sizeof(lxb_dom_node_t));
@@ -320,29 +319,65 @@ nl_node_set_find(VALUE self, VALUE selector, nl_node_find_f finder)
320
319
  }
321
320
  VALUE rb_frag = nl_rb_node_create(&frag->node, nl_rb_document_get(self));
322
321
 
323
- VALUE ret = finder(rb_frag, selector);
322
+ lxb_status_t status = nl_node_find(rb_frag, selector, cb, ctx);
324
323
 
325
324
  lxb_dom_document_fragment_interface_destroy(frag);
326
325
  // Restore original node data
327
- for (int i = 0; i < array->length; i++)
326
+ for (size_t i = 0; i < array->length; i++)
328
327
  {
329
328
  memcpy(array->list[i], backup_array->list[i], sizeof(lxb_dom_node_t));
330
329
  free(backup_array->list[i]);
331
330
  }
332
331
  lexbor_array_destroy(backup_array, true);
333
- return ret;
332
+
333
+ return status;
334
334
  }
335
335
 
336
336
  static VALUE
337
337
  nl_node_set_at_css(VALUE self, VALUE selector)
338
338
  {
339
- return nl_node_set_find(self, selector, nl_node_at_css);
339
+ lexbor_array_t *array = lexbor_array_create();
340
+ lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
341
+
342
+ lxb_status_t status = nl_node_set_find(self, selector, nl_node_at_css_callback, array);
343
+
344
+ if (status != LXB_STATUS_OK)
345
+ {
346
+ lexbor_array_destroy(array, true);
347
+ nl_raise_lexbor_error(status);
348
+ }
349
+
350
+ if (array->length == 0)
351
+ {
352
+ lexbor_array_destroy(array, true);
353
+ return Qnil;
354
+ }
355
+
356
+ sort_nodes_if_necessary(selector, doc, array);
357
+
358
+ VALUE ret = nl_rb_node_create(array->list[0], nl_rb_document_get(self));
359
+
360
+ lexbor_array_destroy(array, true);
361
+
362
+ return ret;
340
363
  }
341
364
 
342
365
  static VALUE
343
366
  nl_node_set_css(VALUE self, VALUE selector)
344
367
  {
345
- return nl_node_set_find(self, selector, nl_node_css);
368
+ lexbor_array_t *array = lexbor_array_create();
369
+ lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
370
+
371
+ lxb_status_t status = nl_node_set_find(self, selector, nl_node_css_callback, array);
372
+ if (status != LXB_STATUS_OK)
373
+ {
374
+ lexbor_array_destroy(array, true);
375
+ nl_raise_lexbor_error(status);
376
+ }
377
+
378
+ sort_nodes_if_necessary(selector, doc, array);
379
+
380
+ return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
346
381
  }
347
382
 
348
383
  void Init_nl_node_set(void)
@@ -7,9 +7,13 @@
7
7
  #include "libxml/xpathInternals.h"
8
8
  #include "libxml/parserInternals.h"
9
9
 
10
+ #define RBSTR_OR_QNIL(_str) (_str ? rb_utf8_str_new_cstr(_str) : Qnil)
11
+
10
12
  extern VALUE mNokolexbor;
11
13
  extern VALUE cNokolexborNodeSet;
12
- VALUE cNokoLexborXpathContext;
14
+ VALUE cNokolexborXpathContext;
15
+ VALUE mNokolexborXpath;
16
+ VALUE cNokolexborXpathSyntaxError;
13
17
 
14
18
  static void
15
19
  free_xml_xpath_context(xmlXPathContextPtr ctx)
@@ -24,7 +28,7 @@ free_xml_xpath_context(xmlXPathContextPtr ctx)
24
28
  * Register the namespace with +prefix+ and +uri+.
25
29
  */
26
30
  static VALUE
27
- rb_xml_xpath_context_register_ns(VALUE self, VALUE prefix, VALUE uri)
31
+ nl_xpath_context_register_ns(VALUE self, VALUE prefix, VALUE uri)
28
32
  {
29
33
  xmlXPathContextPtr ctx;
30
34
  Data_Get_Struct(self, xmlXPathContext, ctx);
@@ -42,7 +46,7 @@ rb_xml_xpath_context_register_ns(VALUE self, VALUE prefix, VALUE uri)
42
46
  * Register the variable +name+ with +value+.
43
47
  */
44
48
  static VALUE
45
- rb_xml_xpath_context_register_variable(VALUE self, VALUE name, VALUE value)
49
+ nl_xpath_context_register_variable(VALUE self, VALUE name, VALUE value)
46
50
  {
47
51
  xmlXPathContextPtr ctx;
48
52
  xmlXPathObjectPtr xmlValue;
@@ -69,7 +73,7 @@ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr ctx, VALUE rb_do
69
73
  switch (c_xpath_object->type)
70
74
  {
71
75
  case XPATH_STRING:
72
- rb_retval = rb_utf8_str_new_cstr(c_xpath_object->stringval);
76
+ rb_retval = rb_utf8_str_new_cstr((const char *)c_xpath_object->stringval);
73
77
  xmlFree(c_xpath_object->stringval);
74
78
  return rb_retval;
75
79
 
@@ -106,6 +110,60 @@ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr ctx, VALUE rb_do
106
110
  }
107
111
  }
108
112
 
113
+ static VALUE
114
+ nl_xpath_wrap_syntax_error(xmlErrorPtr error)
115
+ {
116
+ VALUE msg, e;
117
+
118
+ msg = (error && error->message) ? rb_utf8_str_new_cstr(error->message) : Qnil;
119
+
120
+ e = rb_class_new_instance(
121
+ 1,
122
+ &msg,
123
+ cNokolexborXpathSyntaxError);
124
+
125
+ if (error)
126
+ {
127
+ rb_iv_set(e, "@domain", INT2NUM(error->domain));
128
+ rb_iv_set(e, "@code", INT2NUM(error->code));
129
+ rb_iv_set(e, "@level", INT2NUM((short)error->level));
130
+ rb_iv_set(e, "@file", RBSTR_OR_QNIL(error->file));
131
+ rb_iv_set(e, "@line", INT2NUM(error->line));
132
+ rb_iv_set(e, "@str1", RBSTR_OR_QNIL(error->str1));
133
+ rb_iv_set(e, "@str2", RBSTR_OR_QNIL(error->str2));
134
+ rb_iv_set(e, "@str3", RBSTR_OR_QNIL(error->str3));
135
+ rb_iv_set(e, "@int1", INT2NUM(error->int1));
136
+ rb_iv_set(e, "@column", INT2NUM(error->int2));
137
+ }
138
+
139
+ return e;
140
+ }
141
+
142
+ static void nl_xpath_error_array_pusher(void *ctx, xmlErrorPtr error)
143
+ {
144
+ VALUE list = (VALUE)ctx;
145
+ Check_Type(list, T_ARRAY);
146
+ rb_ary_push(list, nl_xpath_wrap_syntax_error(error));
147
+ }
148
+
149
+ static void
150
+ nl_xpath_generic_exception_pusher(void *ctx, const char *msg, ...)
151
+ {
152
+ VALUE rb_errors = (VALUE)ctx;
153
+ VALUE rb_message;
154
+ VALUE rb_exception;
155
+
156
+ Check_Type(rb_errors, T_ARRAY);
157
+
158
+ va_list args;
159
+ va_start(args, msg);
160
+ rb_message = rb_vsprintf(msg, args);
161
+ va_end(args);
162
+
163
+ rb_exception = rb_exc_new_str(cNokolexborXpathSyntaxError, rb_message);
164
+ rb_ary_push(rb_errors, rb_exception);
165
+ }
166
+
109
167
  /*
110
168
  * call-seq:
111
169
  * evaluate(search_path, handler = nil)
@@ -113,7 +171,7 @@ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr ctx, VALUE rb_do
113
171
  * Evaluate the +search_path+ returning an XML::XPath object.
114
172
  */
115
173
  static VALUE
116
- rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
174
+ nl_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
117
175
  {
118
176
  VALUE search_path, xpath_handler;
119
177
  VALUE retval = Qnil;
@@ -137,16 +195,17 @@ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
137
195
  // xmlXPathRegisterFuncLookup(ctx, handler_lookup, (void *)xpath_handler);
138
196
  // }
139
197
 
140
- // xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
141
- // xmlSetGenericErrorFunc((void *)errors, generic_exception_pusher);
198
+ xmlSetStructuredErrorFunc((void *)errors, nl_xpath_error_array_pusher);
199
+ xmlSetGenericErrorFunc((void *)errors, nl_xpath_generic_exception_pusher);
142
200
 
143
201
  xpath = xmlXPathEvalExpression(query, ctx);
144
202
 
145
- // xmlSetStructuredErrorFunc(NULL, NULL);
146
- // xmlSetGenericErrorFunc(NULL, NULL);
203
+ xmlSetStructuredErrorFunc(NULL, NULL);
204
+ xmlSetGenericErrorFunc(NULL, NULL);
147
205
 
148
206
  if (xpath == NULL)
149
207
  {
208
+ xmlXPathFreeObject(xpath);
150
209
  rb_exc_raise(rb_ary_entry(errors, 0));
151
210
  }
152
211
 
@@ -156,7 +215,7 @@ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
156
215
  retval = rb_funcall(cNokolexborNodeSet, rb_intern("new"), 1, rb_ary_new());
157
216
  }
158
217
 
159
- // xmlXPathFreeNodeSetList(xpath);
218
+ xmlXPathFreeObject(xpath);
160
219
 
161
220
  return retval;
162
221
  }
@@ -168,7 +227,7 @@ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
168
227
  * Create a new XPathContext with +node+ as the reference point.
169
228
  */
170
229
  static VALUE
171
- rb_xml_xpath_context_new(VALUE klass, VALUE rb_node)
230
+ nl_xpath_context_new(VALUE klass, VALUE rb_node)
172
231
  {
173
232
  xmlXPathContextPtr ctx;
174
233
  VALUE self;
@@ -186,15 +245,21 @@ rb_xml_xpath_context_new(VALUE klass, VALUE rb_node)
186
245
 
187
246
  void Init_nl_xpath_context(void)
188
247
  {
248
+ #ifndef NOKOLEXBOR_ASAN
189
249
  xmlMemSetup((xmlFreeFunc)ruby_xfree, (xmlMallocFunc)ruby_xmalloc, (xmlReallocFunc)ruby_xrealloc, ruby_strdup);
250
+ #else
251
+ xmlMemSetup((xmlFreeFunc)free, (xmlMallocFunc)malloc, (xmlReallocFunc)realloc, strdup);
252
+ #endif
190
253
 
191
- cNokoLexborXpathContext = rb_define_class_under(mNokolexbor, "XPathContext", rb_cObject);
254
+ cNokolexborXpathContext = rb_define_class_under(mNokolexbor, "XPathContext", rb_cObject);
255
+ mNokolexborXpath = rb_define_module_under(mNokolexbor, "XPath");
256
+ cNokolexborXpathSyntaxError = rb_define_class_under(mNokolexborXpath, "SyntaxError", rb_eStandardError);
192
257
 
193
- rb_undef_alloc_func(cNokoLexborXpathContext);
258
+ rb_undef_alloc_func(cNokolexborXpathContext);
194
259
 
195
- rb_define_singleton_method(cNokoLexborXpathContext, "new", rb_xml_xpath_context_new, 1);
260
+ rb_define_singleton_method(cNokolexborXpathContext, "new", nl_xpath_context_new, 1);
196
261
 
197
- rb_define_method(cNokoLexborXpathContext, "evaluate", rb_xml_xpath_context_evaluate, -1);
198
- rb_define_method(cNokoLexborXpathContext, "register_variable", rb_xml_xpath_context_register_variable, 2);
199
- rb_define_method(cNokoLexborXpathContext, "register_ns", rb_xml_xpath_context_register_ns, 2);
262
+ rb_define_method(cNokolexborXpathContext, "evaluate", nl_xpath_context_evaluate, -1);
263
+ rb_define_method(cNokolexborXpathContext, "register_variable", nl_xpath_context_register_variable, 2);
264
+ rb_define_method(cNokolexborXpathContext, "register_ns", nl_xpath_context_register_ns, 2);
200
265
  }
@@ -28,6 +28,8 @@ lxb_inline VALUE nl_rb_document_get(VALUE rb_node_or_doc)
28
28
  return rb_iv_get(rb_node_or_doc, "@document");
29
29
  }
30
30
 
31
+ lxb_dom_document_t * nl_rb_document_unwrap(VALUE rb_doc);
32
+
31
33
  const lxb_char_t *
32
34
  lxb_dom_node_name_qualified(lxb_dom_node_t *node, size_t *len);
33
35
 
@@ -3,12 +3,38 @@
3
3
  #include <stdarg.h>
4
4
  #include "libxml/xmlerror.h"
5
5
 
6
- void *_xmlGenericErrorContext = NULL;
7
-
8
- // void * *
9
- // __xmlGenericErrorContext(void) {
10
- // return (&_xmlGenericErrorContext);
11
- // }
6
+ #define XML_GET_VAR_STR(msg, str) { \
7
+ int size, prev_size = -1; \
8
+ int chars; \
9
+ char *larger; \
10
+ va_list ap; \
11
+ \
12
+ str = (char *) xmlMalloc(150); \
13
+ if (str != NULL) { \
14
+ \
15
+ size = 150; \
16
+ \
17
+ while (size < 64000) { \
18
+ va_start(ap, msg); \
19
+ chars = vsnprintf(str, size, msg, ap); \
20
+ va_end(ap); \
21
+ if ((chars > -1) && (chars < size)) { \
22
+ if (prev_size == chars) { \
23
+ break; \
24
+ } else { \
25
+ prev_size = chars; \
26
+ } \
27
+ } \
28
+ if (chars > -1) \
29
+ size += chars + 1; \
30
+ else \
31
+ size += 100; \
32
+ if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
33
+ break; \
34
+ } \
35
+ str = larger; \
36
+ }} \
37
+ }
12
38
 
13
39
  /**
14
40
  * xmlGenericErrorDefaultFunc:
@@ -20,22 +46,57 @@ void *_xmlGenericErrorContext = NULL;
20
46
  */
21
47
  void XMLCDECL
22
48
  xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
23
- va_list args;
49
+ }
24
50
 
25
- if (_xmlGenericErrorContext == NULL)
26
- _xmlGenericErrorContext = (void *) stderr;
51
+ /**
52
+ * xmlCopyError:
53
+ * @from: a source error
54
+ * @to: a target error
55
+ *
56
+ * Save the original error to the new place.
57
+ *
58
+ * Returns 0 in case of success and -1 in case of error.
59
+ */
60
+ int
61
+ xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
62
+ char *message, *file, *str1, *str2, *str3;
27
63
 
28
- va_start(args, msg);
29
- vfprintf((FILE *)_xmlGenericErrorContext, msg, args);
30
- va_end(args);
31
- }
64
+ if ((from == NULL) || (to == NULL))
65
+ return(-1);
66
+
67
+ message = (char *) xmlStrdup((xmlChar *) from->message);
68
+ file = (char *) xmlStrdup ((xmlChar *) from->file);
69
+ str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
70
+ str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
71
+ str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
32
72
 
33
- // xmlGenericErrorFunc _xmlGenericError = xmlGenericErrorDefaultFunc;
73
+ if (to->message != NULL)
74
+ xmlFree(to->message);
75
+ if (to->file != NULL)
76
+ xmlFree(to->file);
77
+ if (to->str1 != NULL)
78
+ xmlFree(to->str1);
79
+ if (to->str2 != NULL)
80
+ xmlFree(to->str2);
81
+ if (to->str3 != NULL)
82
+ xmlFree(to->str3);
83
+ to->domain = from->domain;
84
+ to->code = from->code;
85
+ to->level = from->level;
86
+ to->line = from->line;
87
+ to->node = from->node;
88
+ to->int1 = from->int1;
89
+ to->int2 = from->int2;
90
+ to->node = from->node;
91
+ to->ctxt = from->ctxt;
92
+ to->message = message;
93
+ to->file = file;
94
+ to->str1 = str1;
95
+ to->str2 = str2;
96
+ to->str3 = str3;
34
97
 
35
- // xmlGenericErrorFunc *
36
- // __xmlGenericError(void) {
37
- // return (&_xmlGenericError);
38
- // }
98
+ return 0;
99
+ }
39
100
 
40
101
  /**
41
102
  * __xmlRaiseError:
@@ -63,16 +124,112 @@ xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
63
124
  */
64
125
  void XMLCDECL
65
126
  __xmlRaiseError(xmlStructuredErrorFunc schannel,
66
- xmlGenericErrorFunc channel, void *data, void *ctx,
67
- void *nod, int domain, int code, xmlErrorLevel level,
68
- const char *file, int line, const char *str1,
69
- const char *str2, const char *str3, int int1, int col,
70
- const char *msg, ...)
127
+ xmlGenericErrorFunc channel, void *data, void *ctx,
128
+ void *nod, int domain, int code, xmlErrorLevel level,
129
+ const char *file, int line, const char *str1,
130
+ const char *str2, const char *str3, int int1, int col,
131
+ const char *msg, ...)
71
132
  {
72
- va_list args;
73
- va_start(args, msg);
74
- vfprintf(stderr, msg, args);
75
- va_end(args);
133
+ xmlParserCtxtPtr ctxt = NULL;
134
+ lxb_dom_node_t_ptr node = (lxb_dom_node_t_ptr)nod;
135
+ char *str = NULL;
136
+ xmlParserInputPtr input = NULL;
137
+ xmlErrorPtr to = &xmlLastError;
138
+ lxb_dom_node_t_ptr baseptr = NULL;
139
+
140
+ if (code == XML_ERR_OK)
141
+ return;
142
+ if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
143
+ return;
144
+ if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
145
+ (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
146
+ (domain == XML_FROM_IO) || (domain == XML_FROM_VALID))
147
+ {
148
+ ctxt = (xmlParserCtxtPtr)ctx;
149
+ if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
150
+ (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
151
+ (ctxt->sax->serror != NULL))
152
+ {
153
+ schannel = ctxt->sax->serror;
154
+ data = ctxt->userData;
155
+ }
156
+ }
157
+ /*
158
+ * Check if structured error handler set
159
+ */
160
+ if (schannel == NULL)
161
+ {
162
+ schannel = xmlStructuredError;
163
+ /*
164
+ * if user has defined handler, change data ptr to user's choice
165
+ */
166
+ if (schannel != NULL)
167
+ data = xmlStructuredErrorContext;
168
+ }
169
+ /*
170
+ * Formatting the message
171
+ */
172
+ if (msg == NULL)
173
+ {
174
+ str = (char *)xmlStrdup(BAD_CAST "No error message provided");
175
+ }
176
+ else
177
+ {
178
+ XML_GET_VAR_STR(msg, str);
179
+ }
180
+
181
+ /*
182
+ * specific processing if a parser context is provided
183
+ */
184
+ if (ctxt != NULL)
185
+ {
186
+ if (file == NULL)
187
+ {
188
+ input = ctxt->input;
189
+ if ((input != NULL) && (input->filename == NULL) &&
190
+ (ctxt->inputNr > 1))
191
+ {
192
+ input = ctxt->inputTab[ctxt->inputNr - 2];
193
+ }
194
+ if (input != NULL)
195
+ {
196
+ file = input->filename;
197
+ line = input->line;
198
+ col = input->col;
199
+ }
200
+ }
201
+ to = &ctxt->lastError;
202
+ }
203
+
204
+ /*
205
+ * Save the information about the error
206
+ */
207
+ xmlResetError(to);
208
+ to->domain = domain;
209
+ to->code = code;
210
+ to->message = str;
211
+ to->level = level;
212
+ if (file != NULL)
213
+ to->file = (char *)xmlStrdup((const xmlChar *)file);
214
+ to->line = line;
215
+ if (str1 != NULL)
216
+ to->str1 = (char *)xmlStrdup((const xmlChar *)str1);
217
+ if (str2 != NULL)
218
+ to->str2 = (char *)xmlStrdup((const xmlChar *)str2);
219
+ if (str3 != NULL)
220
+ to->str3 = (char *)xmlStrdup((const xmlChar *)str3);
221
+ to->int1 = int1;
222
+ to->int2 = col;
223
+ to->node = node;
224
+ to->ctxt = ctx;
225
+
226
+ if (to != &xmlLastError)
227
+ xmlCopyError(to, &xmlLastError);
228
+
229
+ if (schannel != NULL)
230
+ {
231
+ schannel(data, to);
232
+ }
76
233
  }
77
234
 
78
235
  /**
@@ -131,4 +288,45 @@ __xmlSimpleError(int domain, int code, lxb_dom_node_t_ptr node,
131
288
  code, XML_ERR_ERROR, NULL, 0, extra,
132
289
  NULL, NULL, 0, 0, msg, extra);
133
290
  }
291
+ }
292
+
293
+ /**
294
+ * xmlSetGenericErrorFunc:
295
+ * @ctx: the new error handling context
296
+ * @handler: the new handler function
297
+ *
298
+ * Function to reset the handler and the error context for out of
299
+ * context error messages.
300
+ * This simply means that @handler will be called for subsequent
301
+ * error messages while not parsing nor validating. And @ctx will
302
+ * be passed as first argument to @handler
303
+ * One can simply force messages to be emitted to another FILE * than
304
+ * stderr by setting @ctx to this file handle and @handler to NULL.
305
+ * For multi-threaded applications, this must be set separately for each thread.
306
+ */
307
+ void
308
+ xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
309
+ xmlGenericErrorContext = ctx;
310
+ if (handler != NULL)
311
+ xmlGenericError = handler;
312
+ else
313
+ xmlGenericError = xmlGenericErrorDefaultFunc;
314
+ }
315
+
316
+ /**
317
+ * xmlSetStructuredErrorFunc:
318
+ * @ctx: the new error handling context
319
+ * @handler: the new handler function
320
+ *
321
+ * Function to reset the handler and the error context for out of
322
+ * context structured error messages.
323
+ * This simply means that @handler will be called for subsequent
324
+ * error messages while not parsing nor validating. And @ctx will
325
+ * be passed as first argument to @handler
326
+ * For multi-threaded applications, this must be set separately for each thread.
327
+ */
328
+ void
329
+ xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
330
+ xmlStructuredErrorContext = ctx;
331
+ xmlStructuredError = handler;
134
332
  }
@@ -119,8 +119,8 @@ module Nokolexbor
119
119
  end
120
120
 
121
121
  def each
122
- attributes.each do |node|
123
- yield [node.name, node.value]
122
+ attributes.each do |name, node|
123
+ yield [name, node.value]
124
124
  end
125
125
  end
126
126
 
@@ -69,9 +69,13 @@ module Nokolexbor
69
69
  self.each(&:remove)
70
70
  end
71
71
 
72
- alias_method :destroy, :remove
72
+ alias_method :unlink, :remove
73
73
  alias_method :to_ary, :to_a
74
74
 
75
+ def destroy
76
+ self.each(&:destroy)
77
+ end
78
+
75
79
  def pop
76
80
  return nil if length == 0
77
81
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nokolexbor
4
- VERSION = '0.2.3'
4
+ VERSION = '0.2.5'
5
5
  end