ox 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ox might be problematic. Click here for more details.
- data/LICENSE +27 -0
- data/README +153 -0
- data/ext/ox/base64.c +123 -0
- data/ext/ox/base64.h +44 -0
- data/ext/ox/cache.c +148 -0
- data/ext/ox/cache.h +43 -0
- data/ext/ox/cache8.c +80 -0
- data/ext/ox/cache8.h +43 -0
- data/ext/ox/cache8_test.c +69 -0
- data/ext/ox/cache_test.c +69 -0
- data/ext/ox/dump.c +901 -0
- data/ext/ox/extconf.rb +7 -0
- data/ext/ox/gen_load.c +196 -0
- data/ext/ox/obj_load.c +802 -0
- data/ext/ox/ox.c +456 -0
- data/ext/ox/ox.h +190 -0
- data/ext/ox/parse.c +629 -0
- data/lib/ox.rb +97 -0
- data/lib/ox/cdata.rb +12 -0
- data/lib/ox/comment.rb +13 -0
- data/lib/ox/doctype.rb +13 -0
- data/lib/ox/document.rb +20 -0
- data/lib/ox/element.rb +67 -0
- data/lib/ox/node.rb +24 -0
- data/test/Sample.graffle +2318 -0
- data/test/cache16_test.rb +17 -0
- data/test/cache8_test.rb +17 -0
- data/test/cache_test.rb +17 -0
- data/test/files.rb +34 -0
- data/test/func.rb +228 -0
- data/test/gen_sample.rb +22 -0
- data/test/obj_sample.rb +19 -0
- data/test/ox/change.rb +16 -0
- data/test/ox/dir.rb +21 -0
- data/test/ox/doc.rb +39 -0
- data/test/ox/file.rb +33 -0
- data/test/ox/group.rb +18 -0
- data/test/ox/hasprops.rb +18 -0
- data/test/ox/layer.rb +14 -0
- data/test/ox/line.rb +22 -0
- data/test/ox/oval.rb +12 -0
- data/test/ox/rect.rb +12 -0
- data/test/ox/shape.rb +37 -0
- data/test/ox/text.rb +23 -0
- data/test/perf_gen.rb +193 -0
- data/test/perf_mars.rb +97 -0
- data/test/perf_obj.rb +201 -0
- data/test/perf_pod.rb +88 -0
- data/test/perf_write.rb +80 -0
- data/test/sample.rb +62 -0
- data/test/test.rb +70 -0
- metadata +106 -0
data/ext/ox/ox.c
ADDED
@@ -0,0 +1,456 @@
|
|
1
|
+
/* ox.c
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
+
* list of conditions and the following disclaimer.
|
10
|
+
*
|
11
|
+
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
+
* used to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
#include <stdlib.h>
|
32
|
+
#include <errno.h>
|
33
|
+
#include <stdio.h>
|
34
|
+
#include <string.h>
|
35
|
+
|
36
|
+
#include "ruby.h"
|
37
|
+
#include "ox.h"
|
38
|
+
|
39
|
+
void Init_ox();
|
40
|
+
|
41
|
+
VALUE Ox = Qnil;
|
42
|
+
|
43
|
+
ID at_id;
|
44
|
+
ID attributes_id;
|
45
|
+
ID beg_id;
|
46
|
+
ID den_id;
|
47
|
+
ID end_id;
|
48
|
+
ID excl_id;
|
49
|
+
ID inspect_id;
|
50
|
+
ID keys_id;
|
51
|
+
ID local_id;
|
52
|
+
ID nodes_id;
|
53
|
+
ID num_id;
|
54
|
+
ID parse_id;
|
55
|
+
ID to_c_id;
|
56
|
+
ID to_s_id;
|
57
|
+
ID tv_sec_id;
|
58
|
+
ID tv_usec_id;
|
59
|
+
ID value_id;
|
60
|
+
|
61
|
+
VALUE version_sym;
|
62
|
+
VALUE standalone_sym;
|
63
|
+
VALUE encoding_sym;
|
64
|
+
VALUE indent_sym;
|
65
|
+
VALUE xsd_date_sym;
|
66
|
+
VALUE opt_format_sym;
|
67
|
+
VALUE circular_sym;
|
68
|
+
VALUE mode_sym;
|
69
|
+
VALUE auto_sym;
|
70
|
+
VALUE optimized_sym;
|
71
|
+
VALUE object_sym;
|
72
|
+
VALUE generic_sym;
|
73
|
+
VALUE limited_sym;
|
74
|
+
VALUE best_effort_sym;
|
75
|
+
VALUE trace_sym;
|
76
|
+
VALUE empty_string;
|
77
|
+
VALUE zero_fixnum;
|
78
|
+
|
79
|
+
VALUE ox_cdata_clas;
|
80
|
+
VALUE ox_comment_clas;
|
81
|
+
VALUE ox_doctype_clas;
|
82
|
+
VALUE ox_document_clas;
|
83
|
+
VALUE ox_element_clas;
|
84
|
+
VALUE ox_text_clas;
|
85
|
+
VALUE struct_class;
|
86
|
+
VALUE time_class;
|
87
|
+
|
88
|
+
Cache symbol_cache = 0;
|
89
|
+
Cache class_cache = 0;
|
90
|
+
Cache attr_cache = 0;
|
91
|
+
|
92
|
+
extern ParseCallbacks ox_obj_callbacks;
|
93
|
+
extern ParseCallbacks ox_gen_callbacks;
|
94
|
+
extern ParseCallbacks ox_limited_callbacks;
|
95
|
+
|
96
|
+
static void parse_dump_options(VALUE options, int *indent, int *xsd_date, int *circular);
|
97
|
+
|
98
|
+
/* call-seq: parse_obj(xml) => Object
|
99
|
+
*
|
100
|
+
* Parses an XML document String that is in the object format and returns an
|
101
|
+
* Object of the type represented by the XML. This function expects an
|
102
|
+
* optimized XML formated String. For other formats use the more generic
|
103
|
+
* Ox.load() method. Raises an exception if the XML is malformed or the
|
104
|
+
* classes specified in the file are not valid.
|
105
|
+
* [xml] XML String in optimized Object format.
|
106
|
+
*/
|
107
|
+
static VALUE
|
108
|
+
to_obj(VALUE self, VALUE ruby_xml) {
|
109
|
+
VALUE obj;
|
110
|
+
char *xml;
|
111
|
+
|
112
|
+
Check_Type(ruby_xml, T_STRING);
|
113
|
+
// the xml string gets modified so make a copy of it
|
114
|
+
xml = strdup(StringValuePtr(ruby_xml));
|
115
|
+
obj = parse(xml, ox_obj_callbacks, 0, 0, 0);
|
116
|
+
free(xml);
|
117
|
+
return obj;
|
118
|
+
}
|
119
|
+
|
120
|
+
/* call-seq: parse(xml) => Ox::Document or Ox::Element
|
121
|
+
*
|
122
|
+
* Parses and XML document String into an Ox::Document or Ox::Element.
|
123
|
+
* Raises an exception if the XML is malformed.
|
124
|
+
* [xml] XML String
|
125
|
+
*/
|
126
|
+
static VALUE
|
127
|
+
to_gen(VALUE self, VALUE ruby_xml) {
|
128
|
+
VALUE obj;
|
129
|
+
char *xml;
|
130
|
+
|
131
|
+
Check_Type(ruby_xml, T_STRING);
|
132
|
+
// the xml string gets modified so make a copy of it
|
133
|
+
xml = strdup(StringValuePtr(ruby_xml));
|
134
|
+
obj = parse(xml, ox_gen_callbacks, 0, 0, 0);
|
135
|
+
free(xml);
|
136
|
+
return obj;
|
137
|
+
}
|
138
|
+
|
139
|
+
typedef enum {
|
140
|
+
AutoMode = 0, // not supported
|
141
|
+
ObjMode = 1,
|
142
|
+
GenMode = 2,
|
143
|
+
LimMode = 3,
|
144
|
+
} LoadMode;
|
145
|
+
|
146
|
+
static VALUE
|
147
|
+
load(char *xml, int argc, VALUE *argv, VALUE self) {
|
148
|
+
VALUE obj;
|
149
|
+
int mode = AutoMode;
|
150
|
+
int trace = 0;
|
151
|
+
int best_effort = 0;
|
152
|
+
|
153
|
+
if (1 == argc && rb_cHash == rb_obj_class(*argv)) {
|
154
|
+
VALUE h = *argv;
|
155
|
+
VALUE v;
|
156
|
+
|
157
|
+
if (Qnil != (v = rb_hash_lookup(h, mode_sym))) {
|
158
|
+
if (auto_sym == v) {
|
159
|
+
mode = AutoMode;
|
160
|
+
} else if (object_sym == v) {
|
161
|
+
mode = ObjMode;
|
162
|
+
} else if (optimized_sym == v) {
|
163
|
+
mode = ObjMode;
|
164
|
+
} else if (generic_sym == v) {
|
165
|
+
mode = GenMode;
|
166
|
+
} else if (limited_sym == v) {
|
167
|
+
mode = LimMode;
|
168
|
+
} else {
|
169
|
+
rb_raise(rb_eArgError, ":mode must be :generic, :object, or :limited.\n");
|
170
|
+
}
|
171
|
+
}
|
172
|
+
if (Qnil != (v = rb_hash_lookup(h, trace_sym))) {
|
173
|
+
Check_Type(v, T_FIXNUM);
|
174
|
+
trace = FIX2INT(v);
|
175
|
+
}
|
176
|
+
if (Qnil != (v = rb_hash_lookup(h, best_effort_sym))) {
|
177
|
+
best_effort = (Qfalse != v);
|
178
|
+
}
|
179
|
+
}
|
180
|
+
switch (mode) {
|
181
|
+
case ObjMode:
|
182
|
+
obj = parse(xml, ox_obj_callbacks, 0, trace, best_effort);
|
183
|
+
break;
|
184
|
+
case GenMode:
|
185
|
+
obj = parse(xml, ox_gen_callbacks, 0, trace, 0);
|
186
|
+
break;
|
187
|
+
case LimMode:
|
188
|
+
obj = parse(xml, ox_limited_callbacks, 0, trace, best_effort);
|
189
|
+
break;
|
190
|
+
case AutoMode:
|
191
|
+
default:
|
192
|
+
obj = parse(xml, ox_gen_callbacks, 0, trace, 0);
|
193
|
+
break;
|
194
|
+
}
|
195
|
+
free(xml);
|
196
|
+
|
197
|
+
return obj;
|
198
|
+
}
|
199
|
+
|
200
|
+
/* call-seq: load(xml, options) => Ox::Document or Ox::Element or Object
|
201
|
+
*
|
202
|
+
* Parses and XML document String into an Ox::Document, or Ox::Element, or
|
203
|
+
* Object depending on the options. Raises an exception if the XML is
|
204
|
+
* malformed or the classes specified are not valid.
|
205
|
+
* [xml] XML String
|
206
|
+
* [options] load options
|
207
|
+
* [:mode] format expected
|
208
|
+
* [:object] object format
|
209
|
+
* [:generic] read as a generic XML file
|
210
|
+
* [:limited] read as a generic XML file but with callbacks on text and elements events only
|
211
|
+
* [:trace] trace level as a Fixnum, default: 0 (silent)
|
212
|
+
* [:best_effort] use best effort to create Objects using nil if undefined Class, default: 0
|
213
|
+
*/
|
214
|
+
static VALUE
|
215
|
+
load_str(int argc, VALUE *argv, VALUE self) {
|
216
|
+
char *xml;
|
217
|
+
|
218
|
+
Check_Type(*argv, T_STRING);
|
219
|
+
// the xml string gets modified so make a copy of it
|
220
|
+
xml = strdup(StringValuePtr(*argv));
|
221
|
+
|
222
|
+
return load(xml, argc - 1, argv + 1, self);
|
223
|
+
}
|
224
|
+
|
225
|
+
/* call-seq: load_file(file_path, xml, options) => Ox::Document or Ox::Element or Object
|
226
|
+
*
|
227
|
+
* Parses and XML document from a file into an Ox::Document, or Ox::Element,
|
228
|
+
* or Object depending on the options. Raises an exception if the XML is
|
229
|
+
* malformed or the classes specified are not valid.
|
230
|
+
* [file_path] file path to read the XML document from
|
231
|
+
* [xml] XML String
|
232
|
+
* [options] load options
|
233
|
+
* [:mode] format expected
|
234
|
+
* [:object] object format
|
235
|
+
* [:generic] read as a generic XML file
|
236
|
+
* [:limited] read as a generic XML file but with callbacks on text and elements events only
|
237
|
+
* [:trace] trace level as a Fixnum, default: 0 (silent)
|
238
|
+
* [:best_effort] use best effort to create Objects using nil if undefined Class, default: 0
|
239
|
+
*/
|
240
|
+
static VALUE
|
241
|
+
load_file(int argc, VALUE *argv, VALUE self) {
|
242
|
+
char *path;
|
243
|
+
char *xml;
|
244
|
+
FILE *f;
|
245
|
+
unsigned long len;
|
246
|
+
|
247
|
+
Check_Type(*argv, T_STRING);
|
248
|
+
path = StringValuePtr(*argv);
|
249
|
+
if (0 == (f = fopen(path, "r"))) {
|
250
|
+
rb_raise(rb_eIOError, "%s\n", strerror(errno));
|
251
|
+
}
|
252
|
+
fseek(f, 0, SEEK_END);
|
253
|
+
len = ftell(f);
|
254
|
+
if (0 == (xml = malloc(len + 1))) {
|
255
|
+
fclose(f);
|
256
|
+
rb_raise(rb_eNoMemError, "Could not allocate memory for %ld byte file.\n", len);
|
257
|
+
}
|
258
|
+
fseek(f, 0, SEEK_SET);
|
259
|
+
if (len != fread(xml, 1, len, f)) {
|
260
|
+
fclose(f);
|
261
|
+
rb_raise(rb_eLoadError, "Failed to read %ld bytes from %s.\n", len, path);
|
262
|
+
}
|
263
|
+
fclose(f);
|
264
|
+
xml[len] = '\0';
|
265
|
+
|
266
|
+
return load(xml, argc - 1, argv + 1, self);
|
267
|
+
}
|
268
|
+
|
269
|
+
static void
|
270
|
+
parse_dump_options(VALUE options, int *indent, int *xsd_date, int *circular) {
|
271
|
+
if (rb_cHash == rb_obj_class(options)) {
|
272
|
+
VALUE v;
|
273
|
+
|
274
|
+
if (Qnil != (v = rb_hash_lookup(options, indent_sym))) {
|
275
|
+
if (rb_cFixnum != rb_obj_class(v)) {
|
276
|
+
rb_raise(rb_eArgError, ":indent must be a Fixnum.\n");
|
277
|
+
}
|
278
|
+
*indent = NUM2INT(v);
|
279
|
+
}
|
280
|
+
if (Qnil != (v = rb_hash_lookup(options, xsd_date_sym))) {
|
281
|
+
VALUE c = rb_obj_class(v);
|
282
|
+
|
283
|
+
if (rb_cTrueClass == c) {
|
284
|
+
*xsd_date = 1;
|
285
|
+
} else if (rb_cFalseClass == c) {
|
286
|
+
*xsd_date = 0;
|
287
|
+
} else {
|
288
|
+
rb_raise(rb_eArgError, ":xsd_date must be true or false.\n");
|
289
|
+
}
|
290
|
+
}
|
291
|
+
if (Qnil != (v = rb_hash_lookup(options, circular_sym))) {
|
292
|
+
VALUE c = rb_obj_class(v);
|
293
|
+
|
294
|
+
if (rb_cTrueClass == c) {
|
295
|
+
*circular = 1;
|
296
|
+
} else if (rb_cFalseClass == c) {
|
297
|
+
*circular = 0;
|
298
|
+
} else {
|
299
|
+
rb_raise(rb_eArgError, ":circular must be true or false.\n");
|
300
|
+
}
|
301
|
+
}
|
302
|
+
}
|
303
|
+
}
|
304
|
+
|
305
|
+
/* call-seq: dump(obj, options) => xml-string
|
306
|
+
*
|
307
|
+
* Dumps an Object (obj) to a string.
|
308
|
+
* [obj] Object to serialize as an XML document String
|
309
|
+
* [options] formating options
|
310
|
+
* [:indent] number of spaces to use as the standard indention, default: 2
|
311
|
+
* [:xsd_date] use XSD date format if true, default: false
|
312
|
+
* [:circular] allow circular references, default: false
|
313
|
+
*/
|
314
|
+
static VALUE
|
315
|
+
dump(int argc, VALUE *argv, VALUE self) {
|
316
|
+
char *xml;
|
317
|
+
int indent = 2;
|
318
|
+
int xsd_date = 0;
|
319
|
+
int circular = 0;
|
320
|
+
VALUE rstr;
|
321
|
+
|
322
|
+
if (2 == argc) {
|
323
|
+
parse_dump_options(argv[1], &indent, &xsd_date, &circular);
|
324
|
+
}
|
325
|
+
if (0 == (xml = write_obj_to_str(*argv, indent, xsd_date, circular))) {
|
326
|
+
rb_raise(rb_eNoMemError, "Not enough memory.\n");
|
327
|
+
}
|
328
|
+
rstr = rb_str_new2(xml);
|
329
|
+
free(xml);
|
330
|
+
|
331
|
+
return rstr;
|
332
|
+
}
|
333
|
+
|
334
|
+
/* call-seq: to_file(file_path, obj, options)
|
335
|
+
*
|
336
|
+
* Dumps and Object to the specified file.
|
337
|
+
* [file_path] file path to write the XML document to
|
338
|
+
* [obj] Object to serialize as an XML document String
|
339
|
+
* [options] formating options
|
340
|
+
* [:indent] number of spaces to use as the standard indention, default: 2
|
341
|
+
* [:xsd_date] use XSD date format if true, default: false
|
342
|
+
* [:circular] allow circular references, default: false
|
343
|
+
*/
|
344
|
+
static VALUE
|
345
|
+
to_file(int argc, VALUE *argv, VALUE self) {
|
346
|
+
int indent = 2;
|
347
|
+
int xsd_date = 0;
|
348
|
+
int circular = 0;
|
349
|
+
|
350
|
+
if (3 == argc) {
|
351
|
+
parse_dump_options(argv[2], &indent, &xsd_date, &circular);
|
352
|
+
}
|
353
|
+
Check_Type(*argv, T_STRING);
|
354
|
+
write_obj_to_file(argv[1], StringValuePtr(*argv), indent, xsd_date, circular);
|
355
|
+
|
356
|
+
return Qnil;
|
357
|
+
}
|
358
|
+
|
359
|
+
extern void ox_cache_test(void);
|
360
|
+
|
361
|
+
static VALUE
|
362
|
+
cache_test(VALUE self) {
|
363
|
+
ox_cache_test();
|
364
|
+
return Qnil;
|
365
|
+
}
|
366
|
+
|
367
|
+
extern void ox_cache8_test(void);
|
368
|
+
|
369
|
+
static VALUE
|
370
|
+
cache8_test(VALUE self) {
|
371
|
+
ox_cache8_test();
|
372
|
+
return Qnil;
|
373
|
+
}
|
374
|
+
|
375
|
+
void Init_ox() {
|
376
|
+
Ox = rb_define_module("Ox");
|
377
|
+
rb_define_module_function(Ox, "parse_obj", to_obj, 1);
|
378
|
+
rb_define_module_function(Ox, "parse", to_gen, 1);
|
379
|
+
rb_define_module_function(Ox, "load", load_str, -1);
|
380
|
+
|
381
|
+
rb_define_module_function(Ox, "to_xml", dump, -1);
|
382
|
+
rb_define_module_function(Ox, "dump", dump, -1);
|
383
|
+
|
384
|
+
rb_define_module_function(Ox, "load_file", load_file, -1);
|
385
|
+
rb_define_module_function(Ox, "to_file", to_file, -1);
|
386
|
+
|
387
|
+
rb_require("time");
|
388
|
+
parse_id = rb_intern("parse");
|
389
|
+
local_id = rb_intern("local");
|
390
|
+
at_id = rb_intern("at");
|
391
|
+
inspect_id = rb_intern("inspect");
|
392
|
+
beg_id = rb_intern("@beg");
|
393
|
+
end_id = rb_intern("@end");
|
394
|
+
den_id = rb_intern("@den");
|
395
|
+
excl_id = rb_intern("@excl");
|
396
|
+
value_id = rb_intern("@value");
|
397
|
+
nodes_id = rb_intern("@nodes");
|
398
|
+
num_id = rb_intern("@num");
|
399
|
+
attributes_id = rb_intern("@attributes");
|
400
|
+
keys_id = rb_intern("keys");
|
401
|
+
tv_sec_id = rb_intern("tv_sec");
|
402
|
+
tv_usec_id = rb_intern("tv_usec");
|
403
|
+
to_c_id = rb_intern("to_c");
|
404
|
+
to_s_id = rb_intern("to_s");
|
405
|
+
|
406
|
+
time_class = rb_const_get(rb_cObject, rb_intern("Time"));
|
407
|
+
struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
408
|
+
|
409
|
+
version_sym = ID2SYM(rb_intern("version"));
|
410
|
+
standalone_sym = ID2SYM(rb_intern("standalone"));
|
411
|
+
encoding_sym = ID2SYM(rb_intern("encoding"));
|
412
|
+
indent_sym = ID2SYM(rb_intern("indent"));
|
413
|
+
xsd_date_sym = ID2SYM(rb_intern("xsd_date"));
|
414
|
+
opt_format_sym = ID2SYM(rb_intern("opt_format"));
|
415
|
+
mode_sym = ID2SYM(rb_intern("mode"));
|
416
|
+
auto_sym = ID2SYM(rb_intern("auto"));
|
417
|
+
optimized_sym = ID2SYM(rb_intern("optimized"));
|
418
|
+
object_sym = ID2SYM(rb_intern("object"));
|
419
|
+
circular_sym = ID2SYM(rb_intern("circular"));
|
420
|
+
generic_sym = ID2SYM(rb_intern("generic"));
|
421
|
+
limited_sym = ID2SYM(rb_intern("limited"));
|
422
|
+
trace_sym = ID2SYM(rb_intern("trace"));
|
423
|
+
best_effort_sym = ID2SYM(rb_intern("best_effort"));
|
424
|
+
empty_string = rb_str_new2("");
|
425
|
+
zero_fixnum = INT2NUM(0);
|
426
|
+
|
427
|
+
//rb_require("node"); // generic xml node classes
|
428
|
+
ox_document_clas = rb_const_get(Ox, rb_intern("Document"));
|
429
|
+
ox_element_clas = rb_const_get(Ox, rb_intern("Element"));
|
430
|
+
ox_comment_clas = rb_const_get(Ox, rb_intern("Comment"));
|
431
|
+
ox_doctype_clas = rb_const_get(Ox, rb_intern("DocType"));
|
432
|
+
ox_cdata_clas = rb_const_get(Ox, rb_intern("CData"));
|
433
|
+
|
434
|
+
ox_cache_new(&symbol_cache);
|
435
|
+
ox_cache_new(&class_cache);
|
436
|
+
ox_cache_new(&attr_cache);
|
437
|
+
|
438
|
+
rb_define_module_function(Ox, "cache_test", cache_test, 0);
|
439
|
+
rb_define_module_function(Ox, "cache8_test", cache8_test, 0);
|
440
|
+
}
|
441
|
+
|
442
|
+
void
|
443
|
+
_raise_error(const char *msg, const char *xml, const char *current, const char* file, int line) {
|
444
|
+
int xline = 1;
|
445
|
+
int col = 1;
|
446
|
+
|
447
|
+
for (; xml < current && '\n' != *current; current--) {
|
448
|
+
col++;
|
449
|
+
}
|
450
|
+
for (; xml < current; current--) {
|
451
|
+
if ('\n' == *current) {
|
452
|
+
xline++;
|
453
|
+
}
|
454
|
+
}
|
455
|
+
rb_raise(rb_eEncodingError, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line);
|
456
|
+
}
|