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.
- checksums.yaml +4 -4
- data/ext/nokolexbor/extconf.rb +12 -6
- data/ext/nokolexbor/memory.c +7 -0
- data/ext/nokolexbor/nl_document.c +23 -5
- data/ext/nokolexbor/nl_node.c +95 -64
- data/ext/nokolexbor/nl_node_set.c +57 -22
- data/ext/nokolexbor/nl_xpath_context.c +82 -17
- data/ext/nokolexbor/nokolexbor.h +2 -0
- data/ext/nokolexbor/xml_error.c +225 -27
- data/lib/nokolexbor/node.rb +2 -2
- data/lib/nokolexbor/node_set.rb +5 -1
- data/lib/nokolexbor/version.rb +1 -1
- data/lib/nokolexbor/xpath.rb +69 -0
- data/lib/nokolexbor.rb +1 -0
- data/patches/0003-lexbor-attach-template-content-to-self.patch +13 -0
- metadata +21 -6
@@ -5,15 +5,15 @@ extern VALUE cNokolexborNode;
|
|
5
5
|
VALUE cNokolexborNodeSet;
|
6
6
|
extern rb_data_type_t nl_document_type;
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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 (
|
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
|
-
|
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 (
|
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 (
|
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
|
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 (
|
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 (
|
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
|
279
|
-
nl_node_set_find(VALUE self, VALUE selector,
|
278
|
+
static lxb_status_t
|
279
|
+
nl_node_set_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx)
|
280
280
|
{
|
281
|
-
|
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 (
|
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
|
-
|
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 (
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
141
|
-
|
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
|
-
|
146
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
258
|
+
rb_undef_alloc_func(cNokolexborXpathContext);
|
194
259
|
|
195
|
-
rb_define_singleton_method(
|
260
|
+
rb_define_singleton_method(cNokolexborXpathContext, "new", nl_xpath_context_new, 1);
|
196
261
|
|
197
|
-
rb_define_method(
|
198
|
-
rb_define_method(
|
199
|
-
rb_define_method(
|
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
|
}
|
data/ext/nokolexbor/nokolexbor.h
CHANGED
@@ -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
|
|
data/ext/nokolexbor/xml_error.c
CHANGED
@@ -3,12 +3,38 @@
|
|
3
3
|
#include <stdarg.h>
|
4
4
|
#include "libxml/xmlerror.h"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
49
|
+
}
|
24
50
|
|
25
|
-
|
26
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
}
|
data/lib/nokolexbor/node.rb
CHANGED
data/lib/nokolexbor/node_set.rb
CHANGED
data/lib/nokolexbor/version.rb
CHANGED