nokolexbor 0.2.3 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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