ox 1.5.1 → 1.5.2
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/README.md +4 -2
- data/ext/ox/cache.c +2 -4
- data/ext/ox/cache8.c +2 -4
- data/ext/ox/dump.c +60 -54
- data/ext/ox/obj_load.c +56 -59
- data/ext/ox/ox.c +22 -18
- data/ext/ox/ox.h +4 -0
- data/ext/ox/parse.c +6 -14
- data/ext/ox/sax.c +3 -7
- data/lib/ox/version.rb +1 -1
- data/test/bug3.rb +21 -0
- data/test/bug4.rb +60 -0
- data/test/func.rb +26 -1
- data/test/perf.rb +1 -1
- data/test/sax_example.rb +37 -0
- metadata +5 -3
data/README.md
CHANGED
@@ -30,9 +30,11 @@ A fast XML parser and Object marshaller as a Ruby gem.
|
|
30
30
|
|
31
31
|
## <a name="release">Release Notes</a>
|
32
32
|
|
33
|
-
### Release 1.5.
|
33
|
+
### Release 1.5.2
|
34
34
|
|
35
|
-
-
|
35
|
+
- Added support for Date.
|
36
|
+
|
37
|
+
- Exception encoding and decoding support improved.
|
36
38
|
|
37
39
|
## <a name="description">Description</a>
|
38
40
|
|
data/ext/ox/cache.c
CHANGED
@@ -46,9 +46,7 @@ static void slot_print(Cache cache, unsigned int depth);
|
|
46
46
|
|
47
47
|
void
|
48
48
|
ox_cache_new(Cache *cache) {
|
49
|
-
|
50
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
51
|
-
}
|
49
|
+
*cache = ALLOC(struct _Cache);
|
52
50
|
(*cache)->key = 0;
|
53
51
|
(*cache)->value = Qundef;
|
54
52
|
bzero((*cache)->slots, sizeof((*cache)->slots));
|
@@ -87,7 +85,7 @@ ox_cache_get(Cache cache, const char *key, VALUE **slot) {
|
|
87
85
|
cp2 = (*cp2)->slots + (*ck & 0x0F);
|
88
86
|
ox_cache_new(cp2);
|
89
87
|
if ('\0' == *(ck + 1)) {
|
90
|
-
|
88
|
+
xfree(cache->key);
|
91
89
|
} else {
|
92
90
|
(*cp2)->key = cache->key;
|
93
91
|
}
|
data/ext/ox/cache8.c
CHANGED
@@ -28,9 +28,7 @@ ox_cache8_new(Cache8 *cache) {
|
|
28
28
|
Cache8 *cp;
|
29
29
|
int i;
|
30
30
|
|
31
|
-
|
32
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
33
|
-
}
|
31
|
+
*cache = ALLOC(struct _Cache8);
|
34
32
|
for (i = SLOT_CNT, cp = (*cache)->slots; 0 < i; i--, cp++) {
|
35
33
|
*cp = 0;
|
36
34
|
}
|
@@ -53,7 +51,7 @@ cache8_delete(Cache8 cache, int depth) {
|
|
53
51
|
}
|
54
52
|
}
|
55
53
|
}
|
56
|
-
|
54
|
+
xfree(cache);
|
57
55
|
}
|
58
56
|
|
59
57
|
slot_t
|
data/ext/ox/dump.c
CHANGED
@@ -98,6 +98,7 @@ static void dump_value(Out out, const char *value, size_t size);
|
|
98
98
|
static void dump_str_value(Out out, const char *value, size_t size);
|
99
99
|
static int dump_var(ID key, VALUE value, Out out);
|
100
100
|
static void dump_num(Out out, VALUE obj);
|
101
|
+
static void dump_date(Out out, VALUE obj);
|
101
102
|
static void dump_time_thin(Out out, VALUE obj);
|
102
103
|
static void dump_time_xsd(Out out, VALUE obj);
|
103
104
|
static int dump_hash(VALUE key, VALUE value, Out out);
|
@@ -145,8 +146,10 @@ dump_hex(u_char c, Out out) {
|
|
145
146
|
*out->cur++ = hex_chars[d];
|
146
147
|
}
|
147
148
|
|
148
|
-
|
149
|
+
static Type
|
149
150
|
obj_class_code(VALUE obj) {
|
151
|
+
VALUE clas = rb_obj_class(obj);
|
152
|
+
|
150
153
|
switch (rb_type(obj)) {
|
151
154
|
case T_NIL: return NilClassCode;
|
152
155
|
case T_ARRAY: return ArrayCode;
|
@@ -162,9 +165,9 @@ obj_class_code(VALUE obj) {
|
|
162
165
|
|
163
166
|
return (is_xml_friendly((u_char*)sym, (int)strlen(sym))) ? SymbolCode : Symbol64Code;
|
164
167
|
}
|
165
|
-
case T_DATA: return (rb_cTime ==
|
166
|
-
case T_STRUCT: return (rb_cRange ==
|
167
|
-
case T_OBJECT: return (ox_document_clas ==
|
168
|
+
case T_DATA: return (rb_cTime == clas) ? TimeCode : ((ox_date_class == clas) ? DateCode : 0);
|
169
|
+
case T_STRUCT: return (rb_cRange == clas) ? RangeCode : StructCode;
|
170
|
+
case T_OBJECT: return (ox_document_clas == clas || ox_element_clas == clas) ? RawCode : ObjectCode;
|
168
171
|
case T_REGEXP: return RegexpCode;
|
169
172
|
case T_BIGNUM: return BignumCode;
|
170
173
|
#ifdef T_COMPLEX
|
@@ -256,17 +259,13 @@ static void
|
|
256
259
|
grow(Out out, size_t len) {
|
257
260
|
size_t size = out->end - out->buf;
|
258
261
|
long pos = out->cur - out->buf;
|
259
|
-
char *buf;
|
260
262
|
|
261
263
|
size *= 2;
|
262
264
|
if (size <= len * 2 + pos) {
|
263
265
|
size += len;
|
264
266
|
}
|
265
|
-
|
266
|
-
|
267
|
-
}
|
268
|
-
out->buf = buf;
|
269
|
-
out->end = buf + size;
|
267
|
+
REALLOC_N(out->buf, char, size + 10); // 10 extra for terminator character plus extra (paranoid)
|
268
|
+
out->end = out->buf + size;
|
270
269
|
out->cur = out->buf + pos;
|
271
270
|
}
|
272
271
|
|
@@ -294,7 +293,7 @@ dump_start(Out out, Element e) {
|
|
294
293
|
if (0 < e->attr.len) {
|
295
294
|
fill_attr(out, 'a', e->attr.str, e->attr.len);
|
296
295
|
}
|
297
|
-
if ((ObjectCode == e->type || StructCode == e->type || ClassCode == e->type) && 0 < e->clas.len) {
|
296
|
+
if ((ObjectCode == e->type || ExceptionCode == e->type || StructCode == e->type || ClassCode == e->type) && 0 < e->clas.len) {
|
298
297
|
fill_attr(out, 'c', e->clas.str, e->clas.len);
|
299
298
|
}
|
300
299
|
if (0 < e->id) {
|
@@ -454,6 +453,30 @@ dump_time_thin(Out out, VALUE obj) {
|
|
454
453
|
out->cur += size;
|
455
454
|
}
|
456
455
|
|
456
|
+
static void
|
457
|
+
dump_date(Out out, VALUE obj) {
|
458
|
+
char buf[64];
|
459
|
+
char *b = buf + sizeof(buf) - 1;
|
460
|
+
long jd = NUM2LONG(rb_funcall2(obj, ox_jd_id, 0, 0));
|
461
|
+
long size;
|
462
|
+
|
463
|
+
*b-- = '\0';
|
464
|
+
for (; 0 < jd; b--, jd /= 10) {
|
465
|
+
*b = '0' + (jd % 10);
|
466
|
+
}
|
467
|
+
b++;
|
468
|
+
if ('\0' == *b) {
|
469
|
+
b--;
|
470
|
+
*b = '0';
|
471
|
+
}
|
472
|
+
size = sizeof(buf) - (b - buf) - 1;
|
473
|
+
if (out->end - out->cur <= size) {
|
474
|
+
grow(out, size);
|
475
|
+
}
|
476
|
+
memcpy(out->cur, b, size);
|
477
|
+
out->cur += size;
|
478
|
+
}
|
479
|
+
|
457
480
|
static void
|
458
481
|
dump_time_xsd(Out out, VALUE obj) {
|
459
482
|
struct tm *tm;
|
@@ -621,24 +644,15 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
|
|
621
644
|
e.indent = -1;
|
622
645
|
out->w_end(out, &e);
|
623
646
|
} else {
|
624
|
-
char buf64[4096];
|
625
|
-
char *b64 = buf64;
|
626
647
|
ulong size = b64_size(cnt);
|
648
|
+
char *b64 = ALLOCA_N(char, size + 1);
|
627
649
|
|
628
650
|
e.type = String64Code;
|
629
|
-
if (sizeof(buf64) < size) {
|
630
|
-
if (0 == (b64 = (char*)malloc(size + 1))) {
|
631
|
-
rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
|
632
|
-
}
|
633
|
-
}
|
634
651
|
to_base64((u_char*)str, cnt, b64);
|
635
652
|
out->w_start(out, &e);
|
636
653
|
dump_value(out, b64, size);
|
637
654
|
e.indent = -1;
|
638
655
|
out->w_end(out, &e);
|
639
|
-
if (buf64 != b64) {
|
640
|
-
free(b64);
|
641
|
-
}
|
642
656
|
}
|
643
657
|
#else
|
644
658
|
e.type = StringCode;
|
@@ -662,24 +676,15 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
|
|
662
676
|
e.indent = -1;
|
663
677
|
out->w_end(out, &e);
|
664
678
|
} else {
|
665
|
-
char buf64[4096];
|
666
|
-
char *b64 = buf64;
|
667
679
|
ulong size = b64_size(cnt);
|
680
|
+
char *b64 = ALLOCA_N(char, size + 1);
|
668
681
|
|
669
682
|
e.type = Symbol64Code;
|
670
|
-
if (sizeof(buf64) < size) {
|
671
|
-
if (0 == (b64 = (char*)malloc(size + 1))) {
|
672
|
-
rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
|
673
|
-
}
|
674
|
-
}
|
675
683
|
to_base64((u_char*)sym, cnt, b64);
|
676
684
|
out->w_start(out, &e);
|
677
685
|
dump_value(out, b64, size);
|
678
686
|
e.indent = -1;
|
679
687
|
out->w_end(out, &e);
|
680
|
-
if (buf64 != b64) {
|
681
|
-
free(b64);
|
682
|
-
}
|
683
688
|
}
|
684
689
|
#else
|
685
690
|
e.type = SymbolCode;
|
@@ -701,14 +706,24 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
|
|
701
706
|
out->w_time(out, obj);
|
702
707
|
e.indent = -1;
|
703
708
|
out->w_end(out, &e);
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
709
|
+
} else {
|
710
|
+
const char *classname = rb_class2name(clas);
|
711
|
+
|
712
|
+
if (0 == strcmp("Date", classname)) {
|
713
|
+
e.type = DateCode;
|
714
|
+
out->w_start(out, &e);
|
715
|
+
dump_date(out, obj);
|
716
|
+
e.indent = -1;
|
717
|
+
out->w_end(out, &e);
|
718
|
+
} else {
|
719
|
+
if (StrictEffort == out->opts->effort) {
|
720
|
+
rb_raise(rb_eNotImpError, "Failed to dump T_DATA %s\n", classname);
|
721
|
+
} else {
|
722
|
+
e.type = NilClassCode;
|
723
|
+
e.closed = 1;
|
724
|
+
out->w_start(out, &e);
|
725
|
+
}
|
726
|
+
}
|
712
727
|
}
|
713
728
|
break;
|
714
729
|
}
|
@@ -779,7 +794,7 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
|
|
779
794
|
} else { // Object
|
780
795
|
// use encoding as the indicator for Ruby 1.8.7 or 1.9.x
|
781
796
|
#ifdef HAVE_RUBY_ENCODING_H
|
782
|
-
e.type = ObjectCode;
|
797
|
+
e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
|
783
798
|
cnt = (int)rb_ivar_count(obj);
|
784
799
|
e.closed = (0 >= cnt);
|
785
800
|
out->w_start(out, &e);
|
@@ -797,7 +812,7 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
|
|
797
812
|
#else
|
798
813
|
VALUE vars = rb_obj_instance_variables(obj);
|
799
814
|
#endif
|
800
|
-
e.type = ObjectCode;
|
815
|
+
e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
|
801
816
|
cnt = (int)RARRAY_LEN(vars);
|
802
817
|
e.closed = (0 >= cnt);
|
803
818
|
out->w_start(out, &e);
|
@@ -839,20 +854,11 @@ dump_obj(ID aid, VALUE obj, unsigned int depth, Out out) {
|
|
839
854
|
//dump_value(out, "/", 1);
|
840
855
|
dump_str_value(out, s, cnt);
|
841
856
|
} else {
|
842
|
-
char buf64[4096];
|
843
|
-
char *b64 = buf64;
|
844
857
|
ulong size = b64_size(cnt);
|
858
|
+
char *b64 = ALLOCA_N(char, size + 1);
|
845
859
|
|
846
|
-
if (sizeof(buf64) < size) {
|
847
|
-
if (0 == (b64 = (char*)malloc(size + 1))) {
|
848
|
-
rb_raise(rb_eNoMemError, "Failed to create string. [%d:%s]\n", ENOSPC, strerror(ENOSPC));
|
849
|
-
}
|
850
|
-
}
|
851
860
|
to_base64((u_char*)s, cnt, b64);
|
852
861
|
dump_value(out, b64, size);
|
853
|
-
if (buf64 != b64) {
|
854
|
-
free(b64);
|
855
|
-
}
|
856
862
|
}
|
857
863
|
#else
|
858
864
|
dump_str_value(out, s, cnt);
|
@@ -1119,8 +1125,8 @@ dump_obj_to_xml(VALUE obj, Options copts, Out out) {
|
|
1119
1125
|
VALUE clas = rb_obj_class(obj);
|
1120
1126
|
|
1121
1127
|
out->w_time = (Yes == copts->xsd_date) ? dump_time_xsd : dump_time_thin;
|
1122
|
-
out->buf = (char
|
1123
|
-
out->end = out->buf + 65325; //
|
1128
|
+
out->buf = ALLOC_N(char, 65336);
|
1129
|
+
out->end = out->buf + 65325; // 10 less than end plus extra for possible errors
|
1124
1130
|
out->cur = out->buf;
|
1125
1131
|
out->circ_cache = 0;
|
1126
1132
|
out->circ_cnt = 0;
|
@@ -1168,6 +1174,6 @@ ox_write_obj_to_file(VALUE obj, const char *path, Options copts) {
|
|
1168
1174
|
int err = ferror(f);
|
1169
1175
|
rb_raise(rb_eIOError, "Write failed. [%d:%s]\n", err, strerror(err));
|
1170
1176
|
}
|
1171
|
-
|
1177
|
+
xfree(out.buf);
|
1172
1178
|
fclose(f);
|
1173
1179
|
}
|
data/ext/ox/obj_load.c
CHANGED
@@ -50,9 +50,9 @@ static VALUE parse_double_time(const char *text, VALUE clas);
|
|
50
50
|
static VALUE parse_regexp(const char *text);
|
51
51
|
|
52
52
|
static VALUE get_var_sym_from_attrs(Attr a, void *encoding);
|
53
|
-
static VALUE get_obj_from_attrs(Attr a, PInfo pi);
|
54
|
-
static VALUE get_class_from_attrs(Attr a, PInfo pi);
|
55
|
-
static VALUE classname2class(const char *name, PInfo pi);
|
53
|
+
static VALUE get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class);
|
54
|
+
static VALUE get_class_from_attrs(Attr a, PInfo pi, VALUE base_class);
|
55
|
+
static VALUE classname2class(const char *name, PInfo pi, VALUE base_class);
|
56
56
|
static unsigned long get_id_from_attrs(PInfo pi, Attr a);
|
57
57
|
static CircArray circ_array_new(void);
|
58
58
|
static void circ_array_free(CircArray ca);
|
@@ -125,7 +125,7 @@ name2var(const char *name, void *encoding) {
|
|
125
125
|
}
|
126
126
|
|
127
127
|
inline static VALUE
|
128
|
-
resolve_classname(VALUE mod, const char *class_name, Effort effort) {
|
128
|
+
resolve_classname(VALUE mod, const char *class_name, Effort effort, VALUE base_class) {
|
129
129
|
VALUE clas;
|
130
130
|
ID ci = rb_intern(class_name);
|
131
131
|
|
@@ -141,7 +141,7 @@ resolve_classname(VALUE mod, const char *class_name, Effort effort) {
|
|
141
141
|
if (rb_const_defined_at(mod, ci)) {
|
142
142
|
clas = rb_const_get_at(mod, ci);
|
143
143
|
} else {
|
144
|
-
clas = rb_define_class_under(mod, class_name,
|
144
|
+
clas = rb_define_class_under(mod, class_name, base_class);
|
145
145
|
}
|
146
146
|
break;
|
147
147
|
case StrictEffort:
|
@@ -154,8 +154,8 @@ resolve_classname(VALUE mod, const char *class_name, Effort effort) {
|
|
154
154
|
}
|
155
155
|
|
156
156
|
inline static VALUE
|
157
|
-
classname2obj(const char *name, PInfo pi) {
|
158
|
-
VALUE clas = classname2class(name, pi);
|
157
|
+
classname2obj(const char *name, PInfo pi, VALUE base_class) {
|
158
|
+
VALUE clas = classname2class(name, pi, base_class);
|
159
159
|
|
160
160
|
if (Qundef == clas) {
|
161
161
|
return Qnil;
|
@@ -189,6 +189,20 @@ structname2obj(const char *name) {
|
|
189
189
|
}
|
190
190
|
#endif
|
191
191
|
|
192
|
+
inline static VALUE
|
193
|
+
parse_ulong(const char *s, PInfo pi) {
|
194
|
+
unsigned long n = 0;
|
195
|
+
|
196
|
+
for (; '\0' != *s; s++) {
|
197
|
+
if ('0' <= *s && *s <= '9') {
|
198
|
+
n = n * 10 + (*s - '0');
|
199
|
+
} else {
|
200
|
+
raise_error("Invalid number for a julian day", pi->str, pi->s);
|
201
|
+
}
|
202
|
+
}
|
203
|
+
return ULONG2NUM(n);
|
204
|
+
}
|
205
|
+
|
192
206
|
// 2010-07-09T10:47:45.895826162+09:00
|
193
207
|
inline static VALUE
|
194
208
|
parse_time(const char *text, VALUE clas) {
|
@@ -206,7 +220,7 @@ parse_time(const char *text, VALUE clas) {
|
|
206
220
|
}
|
207
221
|
|
208
222
|
static VALUE
|
209
|
-
classname2class(const char *name, PInfo pi) {
|
223
|
+
classname2class(const char *name, PInfo pi, VALUE base_class) {
|
210
224
|
VALUE *slot;
|
211
225
|
VALUE clas;
|
212
226
|
|
@@ -223,7 +237,7 @@ classname2class(const char *name, PInfo pi) {
|
|
223
237
|
if (':' != *n) {
|
224
238
|
raise_error("Invalid classname, expected another ':'", pi->str, pi->s);
|
225
239
|
}
|
226
|
-
if (Qundef == (clas = resolve_classname(clas, class_name, pi->effort))) {
|
240
|
+
if (Qundef == (clas = resolve_classname(clas, class_name, pi->effort, base_class))) {
|
227
241
|
return Qundef;
|
228
242
|
}
|
229
243
|
s = class_name;
|
@@ -232,7 +246,7 @@ classname2class(const char *name, PInfo pi) {
|
|
232
246
|
}
|
233
247
|
}
|
234
248
|
*s = '\0';
|
235
|
-
if (Qundef != (clas = resolve_classname(clas, class_name, pi->effort))) {
|
249
|
+
if (Qundef != (clas = resolve_classname(clas, class_name, pi->effort, base_class))) {
|
236
250
|
*slot = clas;
|
237
251
|
}
|
238
252
|
}
|
@@ -250,10 +264,10 @@ get_var_sym_from_attrs(Attr a, void *encoding) {
|
|
250
264
|
}
|
251
265
|
|
252
266
|
static VALUE
|
253
|
-
get_obj_from_attrs(Attr a, PInfo pi) {
|
267
|
+
get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
254
268
|
for (; 0 != a->name; a++) {
|
255
269
|
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
256
|
-
return classname2obj(a->value, pi);
|
270
|
+
return classname2obj(a->value, pi, base_class);
|
257
271
|
}
|
258
272
|
}
|
259
273
|
return Qundef;
|
@@ -272,10 +286,10 @@ get_struct_from_attrs(Attr a) {
|
|
272
286
|
#endif
|
273
287
|
|
274
288
|
static VALUE
|
275
|
-
get_class_from_attrs(Attr a, PInfo pi) {
|
289
|
+
get_class_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
276
290
|
for (; 0 != a->name; a++) {
|
277
291
|
if ('c' == *a->name && '\0' == *(a->name + 1)) {
|
278
|
-
return classname2class(a->value, pi);
|
292
|
+
return classname2class(a->value, pi, base_class);
|
279
293
|
}
|
280
294
|
}
|
281
295
|
return Qundef;
|
@@ -307,9 +321,7 @@ static CircArray
|
|
307
321
|
circ_array_new() {
|
308
322
|
CircArray ca;
|
309
323
|
|
310
|
-
|
311
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
312
|
-
}
|
324
|
+
ca = ALLOC(struct _CircArray);
|
313
325
|
ca->objs = ca->obj_array;
|
314
326
|
ca->size = sizeof(ca->obj_array) / sizeof(VALUE);
|
315
327
|
ca->cnt = 0;
|
@@ -320,9 +332,9 @@ circ_array_new() {
|
|
320
332
|
static void
|
321
333
|
circ_array_free(CircArray ca) {
|
322
334
|
if (ca->objs != ca->obj_array) {
|
323
|
-
|
335
|
+
xfree(ca->objs);
|
324
336
|
}
|
325
|
-
|
337
|
+
xfree(ca);
|
326
338
|
}
|
327
339
|
|
328
340
|
static void
|
@@ -334,14 +346,10 @@ circ_array_set(CircArray ca, VALUE obj, unsigned long id) {
|
|
334
346
|
unsigned long cnt = id + 512;
|
335
347
|
|
336
348
|
if (ca->objs == ca->obj_array) {
|
337
|
-
|
338
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
339
|
-
}
|
349
|
+
ca->objs = ALLOC_N(VALUE, cnt);
|
340
350
|
memcpy(ca->objs, ca->obj_array, sizeof(VALUE) * ca->cnt);
|
341
|
-
} else {
|
342
|
-
|
343
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
344
|
-
}
|
351
|
+
} else {
|
352
|
+
REALLOC_N(ca->objs, VALUE, cnt);
|
345
353
|
}
|
346
354
|
ca->size = cnt;
|
347
355
|
}
|
@@ -461,21 +469,23 @@ add_text(PInfo pi, char *text, int closed) {
|
|
461
469
|
pi->h->obj = sym;
|
462
470
|
break;
|
463
471
|
}
|
472
|
+
case DateCode:
|
473
|
+
{
|
474
|
+
VALUE args[1];
|
475
|
+
|
476
|
+
*args = parse_ulong(text, pi);
|
477
|
+
pi->h->obj = rb_funcall2(ox_date_class, ox_jd_id, 1, args);
|
478
|
+
break;
|
479
|
+
}
|
464
480
|
case TimeCode:
|
465
481
|
pi->h->obj = parse_time(text, ox_time_class);
|
466
482
|
break;
|
467
483
|
case String64Code:
|
468
484
|
{
|
469
|
-
char buf[1024];
|
470
|
-
char *str = buf;
|
471
485
|
unsigned long str_size = b64_orig_size(text);
|
472
486
|
VALUE v;
|
487
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
473
488
|
|
474
|
-
if (sizeof(buf) <= str_size) {
|
475
|
-
if (0 == (str = (char*)malloc(str_size + 1))) {
|
476
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
477
|
-
}
|
478
|
-
}
|
479
489
|
from_base64(text, (u_char*)str);
|
480
490
|
v = rb_str_new(str, str_size);
|
481
491
|
#ifdef HAVE_RUBY_ENCODING_H
|
@@ -487,53 +497,32 @@ add_text(PInfo pi, char *text, int closed) {
|
|
487
497
|
circ_array_set(pi->circ_array, v, (unsigned long)pi->h->obj);
|
488
498
|
}
|
489
499
|
pi->h->obj = v;
|
490
|
-
if (buf != str) {
|
491
|
-
free(str);
|
492
|
-
}
|
493
500
|
break;
|
494
501
|
}
|
495
502
|
case Symbol64Code:
|
496
503
|
{
|
497
504
|
VALUE sym;
|
498
505
|
VALUE *slot;
|
499
|
-
char buf[1024];
|
500
|
-
char *str = buf;
|
501
506
|
unsigned long str_size = b64_orig_size(text);
|
507
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
502
508
|
|
503
|
-
if (sizeof(buf) <= str_size) {
|
504
|
-
if (0 == (str = (char*)malloc(str_size + 1))) {
|
505
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
506
|
-
}
|
507
|
-
}
|
508
509
|
from_base64(text, (u_char*)str);
|
509
510
|
if (Qundef == (sym = ox_cache_get(ox_symbol_cache, str, &slot))) {
|
510
511
|
sym = str2sym(str, pi->encoding);
|
511
512
|
*slot = sym;
|
512
513
|
}
|
513
514
|
pi->h->obj = sym;
|
514
|
-
if (buf != str) {
|
515
|
-
free(str);
|
516
|
-
}
|
517
515
|
break;
|
518
516
|
}
|
519
517
|
case RegexpCode:
|
520
518
|
if ('/' == *text) {
|
521
519
|
pi->h->obj = parse_regexp(text);
|
522
520
|
} else {
|
523
|
-
char buf[1024];
|
524
|
-
char *str = buf;
|
525
521
|
unsigned long str_size = b64_orig_size(text);
|
522
|
+
char *str = ALLOCA_N(char, str_size + 1);
|
526
523
|
|
527
|
-
if (sizeof(buf) <= str_size) {
|
528
|
-
if (0 == (str = (char*)malloc(str_size + 1))) {
|
529
|
-
rb_raise(rb_eNoMemError, "not enough memory\n");
|
530
|
-
}
|
531
|
-
}
|
532
524
|
from_base64(text, (u_char*)str);
|
533
525
|
pi->h->obj = parse_regexp(str);
|
534
|
-
if (sizeof(buf) <= str_size) {
|
535
|
-
free(str);
|
536
|
-
}
|
537
526
|
}
|
538
527
|
break;
|
539
528
|
case BignumCode:
|
@@ -609,6 +598,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
609
598
|
case RegexpCode:
|
610
599
|
case BignumCode:
|
611
600
|
case ComplexCode:
|
601
|
+
case DateCode:
|
612
602
|
case TimeCode:
|
613
603
|
case RationalCode: // sub elements read next
|
614
604
|
// value will be read in the following add_text
|
@@ -645,8 +635,14 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
645
635
|
h->obj = Qnil;
|
646
636
|
}
|
647
637
|
break;
|
638
|
+
case ExceptionCode:
|
639
|
+
h->obj = get_obj_from_attrs(attrs, pi, rb_eException);
|
640
|
+
if (0 != pi->circ_array && Qnil != h->obj) {
|
641
|
+
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
642
|
+
}
|
643
|
+
break;
|
648
644
|
case ObjectCode:
|
649
|
-
h->obj = get_obj_from_attrs(attrs, pi);
|
645
|
+
h->obj = get_obj_from_attrs(attrs, pi, ox_bag_clas);
|
650
646
|
if (0 != pi->circ_array && Qnil != h->obj) {
|
651
647
|
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
652
648
|
}
|
@@ -662,7 +658,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
662
658
|
#endif
|
663
659
|
break;
|
664
660
|
case ClassCode:
|
665
|
-
h->obj = get_class_from_attrs(attrs, pi);
|
661
|
+
h->obj = get_class_from_attrs(attrs, pi, ox_bag_clas);
|
666
662
|
break;
|
667
663
|
case RefCode:
|
668
664
|
h->obj = Qundef;
|
@@ -711,6 +707,7 @@ end_element(PInfo pi, const char *ename) {
|
|
711
707
|
case ArrayCode:
|
712
708
|
rb_ary_push(pi->h->obj, h->obj);
|
713
709
|
break;
|
710
|
+
case ExceptionCode:
|
714
711
|
case ObjectCode:
|
715
712
|
if (Qnil != pi->h->obj) {
|
716
713
|
rb_ivar_set(pi->h->obj, h->var, h->obj);
|
@@ -910,7 +907,7 @@ debug_stack(PInfo pi, const char *comment) {
|
|
910
907
|
|
911
908
|
v = rb_funcall2(h->var, rb_intern("to_s"), 0, 0);
|
912
909
|
key = StringValuePtr(v);
|
913
|
-
} else if (ObjectCode == (h - 1)->type || RangeCode == (h - 1)->type || StructCode == (h - 1)->type) {
|
910
|
+
} else if (ObjectCode == (h - 1)->type || ExceptionCode == (h - 1)->type || RangeCode == (h - 1)->type || StructCode == (h - 1)->type) {
|
914
911
|
key = rb_id2name(h->var);
|
915
912
|
} else {
|
916
913
|
printf("%s*** corrupt stack ***\n", indent);
|
data/ext/ox/ox.c
CHANGED
@@ -60,6 +60,7 @@ ID ox_excl_id;
|
|
60
60
|
ID ox_fileno_id;
|
61
61
|
ID ox_inspect_id;
|
62
62
|
ID ox_instruct_id;
|
63
|
+
ID ox_jd_id;
|
63
64
|
ID ox_keys_id;
|
64
65
|
ID ox_local_id;
|
65
66
|
ID ox_mesg_id;
|
@@ -91,6 +92,7 @@ VALUE ox_element_clas;
|
|
91
92
|
VALUE ox_bag_clas;
|
92
93
|
VALUE ox_struct_class;
|
93
94
|
VALUE ox_time_class;
|
95
|
+
VALUE ox_date_class;
|
94
96
|
|
95
97
|
Cache ox_symbol_cache = 0;
|
96
98
|
Cache ox_class_cache = 0;
|
@@ -285,15 +287,16 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
285
287
|
*/
|
286
288
|
static VALUE
|
287
289
|
to_obj(VALUE self, VALUE ruby_xml) {
|
288
|
-
VALUE obj;
|
289
290
|
char *xml;
|
291
|
+
size_t len;
|
290
292
|
|
291
293
|
Check_Type(ruby_xml, T_STRING);
|
292
294
|
// the xml string gets modified so make a copy of it
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
295
|
+
len = RSTRING_LEN(ruby_xml) + 1;
|
296
|
+
xml = ALLOCA_N(char, len);
|
297
|
+
strcpy(xml, StringValuePtr(ruby_xml));
|
298
|
+
|
299
|
+
return ox_parse(xml, ox_obj_callbacks, 0, 0, StrictEffort);
|
297
300
|
}
|
298
301
|
|
299
302
|
/* call-seq: parse(xml) => Ox::Document or Ox::Element
|
@@ -305,15 +308,16 @@ to_obj(VALUE self, VALUE ruby_xml) {
|
|
305
308
|
*/
|
306
309
|
static VALUE
|
307
310
|
to_gen(VALUE self, VALUE ruby_xml) {
|
308
|
-
VALUE obj;
|
309
311
|
char *xml;
|
312
|
+
size_t len;
|
310
313
|
|
311
314
|
Check_Type(ruby_xml, T_STRING);
|
312
315
|
// the xml string gets modified so make a copy of it
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
316
|
+
len = RSTRING_LEN(ruby_xml) + 1;
|
317
|
+
xml = ALLOCA_N(char, len);
|
318
|
+
strcpy(xml, StringValuePtr(ruby_xml));
|
319
|
+
|
320
|
+
return ox_parse(xml, ox_gen_callbacks, 0, 0, StrictEffort);
|
317
321
|
}
|
318
322
|
|
319
323
|
static VALUE
|
@@ -371,8 +375,6 @@ load(char *xml, int argc, VALUE *argv, VALUE self) {
|
|
371
375
|
obj = ox_parse(xml, ox_gen_callbacks, 0, options.trace, options.effort);
|
372
376
|
break;
|
373
377
|
}
|
374
|
-
free(xml);
|
375
|
-
|
376
378
|
return obj;
|
377
379
|
}
|
378
380
|
|
@@ -396,10 +398,13 @@ load(char *xml, int argc, VALUE *argv, VALUE self) {
|
|
396
398
|
static VALUE
|
397
399
|
load_str(int argc, VALUE *argv, VALUE self) {
|
398
400
|
char *xml;
|
401
|
+
size_t len;
|
399
402
|
|
400
403
|
Check_Type(*argv, T_STRING);
|
401
404
|
// the xml string gets modified so make a copy of it
|
402
|
-
|
405
|
+
len = RSTRING_LEN(*argv) + 1;
|
406
|
+
xml = ALLOCA_N(char, len);
|
407
|
+
strcpy(xml, StringValuePtr(*argv));
|
403
408
|
|
404
409
|
return load(xml, argc - 1, argv + 1, self);
|
405
410
|
}
|
@@ -435,10 +440,7 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
435
440
|
}
|
436
441
|
fseek(f, 0, SEEK_END);
|
437
442
|
len = ftell(f);
|
438
|
-
|
439
|
-
fclose(f);
|
440
|
-
rb_raise(rb_eNoMemError, "Could not allocate memory for %ld byte file.\n", len);
|
441
|
-
}
|
443
|
+
xml = ALLOCA_N(char, len + 1);
|
442
444
|
fseek(f, 0, SEEK_SET);
|
443
445
|
if (len != fread(xml, 1, len, f)) {
|
444
446
|
fclose(f);
|
@@ -569,7 +571,7 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
569
571
|
rb_enc_associate(rstr, rb_enc_find(copts.encoding));
|
570
572
|
}
|
571
573
|
#endif
|
572
|
-
|
574
|
+
xfree(xml);
|
573
575
|
|
574
576
|
return rstr;
|
575
577
|
}
|
@@ -653,6 +655,7 @@ void Init_ox() {
|
|
653
655
|
ox_fileno_id = rb_intern("fileno");
|
654
656
|
ox_inspect_id = rb_intern("inspect");
|
655
657
|
ox_instruct_id = rb_intern("instruct");
|
658
|
+
ox_jd_id = rb_intern("jd");
|
656
659
|
ox_keys_id = rb_intern("keys");
|
657
660
|
ox_local_id = rb_intern("local");
|
658
661
|
ox_mesg_id = rb_intern("mesg");
|
@@ -672,6 +675,7 @@ void Init_ox() {
|
|
672
675
|
ox_value_id = rb_intern("@value");
|
673
676
|
|
674
677
|
ox_time_class = rb_const_get(rb_cObject, rb_intern("Time"));
|
678
|
+
ox_date_class = rb_const_get(rb_cObject, rb_intern("Date"));
|
675
679
|
ox_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|
676
680
|
|
677
681
|
ox_encoding_sym = ID2SYM(rb_intern("encoding")); rb_ary_push(keep, ox_encoding_sym);
|
data/ext/ox/ox.h
CHANGED
@@ -121,6 +121,8 @@ typedef enum {
|
|
121
121
|
String64Code = 'b', // base64 encoded String
|
122
122
|
ClassCode = 'c',
|
123
123
|
Symbol64Code = 'd', // base64 encoded Symbol
|
124
|
+
DateCode = 'D',
|
125
|
+
ExceptionCode = 'e',
|
124
126
|
FloatCode = 'f',
|
125
127
|
RegexpCode = 'g',
|
126
128
|
HashCode = 'h',
|
@@ -231,6 +233,7 @@ extern ID ox_excl_id;
|
|
231
233
|
extern ID ox_fileno_id;
|
232
234
|
extern ID ox_inspect_id;
|
233
235
|
extern ID ox_instruct_id;
|
236
|
+
extern ID ox_jd_id;
|
234
237
|
extern ID ox_keys_id;
|
235
238
|
extern ID ox_local_id;
|
236
239
|
extern ID ox_mesg_id;
|
@@ -249,6 +252,7 @@ extern ID ox_tv_sec_id;
|
|
249
252
|
extern ID ox_tv_usec_id;
|
250
253
|
extern ID ox_value_id;
|
251
254
|
|
255
|
+
extern VALUE ox_date_class;
|
252
256
|
extern VALUE ox_empty_string;
|
253
257
|
extern VALUE ox_encoding_sym;
|
254
258
|
extern VALUE ox_struct_class;
|
data/ext/ox/parse.c
CHANGED
@@ -469,18 +469,14 @@ read_text(PInfo pi) {
|
|
469
469
|
|
470
470
|
if (0 == alloc_buf) {
|
471
471
|
size = sizeof(buf) * 2;
|
472
|
-
|
473
|
-
raise_error("text too long", pi->str, pi->s);
|
474
|
-
}
|
472
|
+
alloc_buf = ALLOC_N(char, size);
|
475
473
|
memcpy(alloc_buf, buf, b - buf);
|
476
474
|
b = alloc_buf + (b - buf);
|
477
475
|
} else {
|
478
476
|
unsigned long pos = b - alloc_buf;
|
479
477
|
|
480
478
|
size = (end - alloc_buf) * 2;
|
481
|
-
|
482
|
-
raise_error("text too long", pi->str, pi->s);
|
483
|
-
}
|
479
|
+
REALLOC_N(alloc_buf, char, size);
|
484
480
|
b = alloc_buf + pos;
|
485
481
|
}
|
486
482
|
end = alloc_buf + size - 2;
|
@@ -492,7 +488,7 @@ read_text(PInfo pi) {
|
|
492
488
|
*b = '\0';
|
493
489
|
if (0 != alloc_buf) {
|
494
490
|
pi->pcb->add_text(pi, alloc_buf, ('/' == *(pi->s + 1)));
|
495
|
-
|
491
|
+
xfree(alloc_buf);
|
496
492
|
} else {
|
497
493
|
pi->pcb->add_text(pi, buf, ('/' == *(pi->s + 1)));
|
498
494
|
}
|
@@ -534,18 +530,14 @@ read_reduced_text(PInfo pi) {
|
|
534
530
|
|
535
531
|
if (0 == alloc_buf) {
|
536
532
|
size = sizeof(buf) * 2;
|
537
|
-
|
538
|
-
raise_error("text too long", pi->str, pi->s);
|
539
|
-
}
|
533
|
+
alloc_buf = ALLOC_N(char, size);
|
540
534
|
memcpy(alloc_buf, buf, b - buf);
|
541
535
|
b = alloc_buf + (b - buf);
|
542
536
|
} else {
|
543
537
|
unsigned long pos = b - alloc_buf;
|
544
538
|
|
545
539
|
size = (end - alloc_buf) * 2;
|
546
|
-
|
547
|
-
raise_error("text too long", pi->str, pi->s);
|
548
|
-
}
|
540
|
+
REALLOC(alloc_buf, char, size);
|
549
541
|
b = alloc_buf + pos;
|
550
542
|
}
|
551
543
|
end = alloc_buf + size - 2;
|
@@ -561,7 +553,7 @@ read_reduced_text(PInfo pi) {
|
|
561
553
|
*b = '\0';
|
562
554
|
if (0 != alloc_buf) {
|
563
555
|
pi->pcb->add_text(pi, alloc_buf, ('/' == *(pi->s + 1)));
|
564
|
-
|
556
|
+
xfree(alloc_buf);
|
565
557
|
} else {
|
566
558
|
pi->pcb->add_text(pi, buf, ('/' == *(pi->s + 1)));
|
567
559
|
}
|
data/ext/ox/sax.c
CHANGED
@@ -270,7 +270,7 @@ sax_drive_init(SaxDrive dr, VALUE handler, VALUE io, int convert) {
|
|
270
270
|
static void
|
271
271
|
sax_drive_cleanup(SaxDrive dr) {
|
272
272
|
if (dr->base_buf != dr->buf) {
|
273
|
-
|
273
|
+
xfree(dr->buf);
|
274
274
|
}
|
275
275
|
}
|
276
276
|
|
@@ -291,14 +291,10 @@ sax_drive_read(SaxDrive dr) {
|
|
291
291
|
size_t size = dr->buf_end - dr->buf;
|
292
292
|
|
293
293
|
if (dr->buf == dr->base_buf) {
|
294
|
-
|
295
|
-
rb_raise(rb_eNoMemError, "Could not allocate memory for large element.\n");
|
296
|
-
}
|
294
|
+
dr->buf = ALLOC_N(char, size * 2);
|
297
295
|
memcpy(dr->buf, old, size);
|
298
296
|
} else {
|
299
|
-
|
300
|
-
rb_raise(rb_eNoMemError, "Could not allocate memory for large element.\n");
|
301
|
-
}
|
297
|
+
REALLOC_N(dr->buf, char, size * 2);
|
302
298
|
}
|
303
299
|
dr->buf_end = dr->buf + size * 2;
|
304
300
|
dr->cur = dr->buf + (dr->cur - old);
|
data/lib/ox/version.rb
CHANGED
data/test/bug3.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
|
3
|
+
$: << '../lib'
|
4
|
+
$: << '../ext'
|
5
|
+
|
6
|
+
require 'ox'
|
7
|
+
|
8
|
+
def name_it()
|
9
|
+
begin
|
10
|
+
"x".foo
|
11
|
+
rescue Exception => e
|
12
|
+
#puts e.message
|
13
|
+
xml = Ox.dump(e, effort: :tolerant)
|
14
|
+
puts xml
|
15
|
+
o = Ox.load(xml, mode: :object)
|
16
|
+
puts o.message
|
17
|
+
puts Ox.dump(e)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
name_it()
|
data/test/bug4.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
|
+
|
7
|
+
require 'stringio'
|
8
|
+
require 'ox'
|
9
|
+
|
10
|
+
x1 = %(<?xml version="1.0" encoding="ISO-8859-1" ?><tag key="value">Français</tag>).encode("ISO-8859-1")
|
11
|
+
# => "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?><tag key=\"value\">Fran\xE7ais</tag>"
|
12
|
+
x1.encoding
|
13
|
+
# => #<Encoding:ISO-8859-1>
|
14
|
+
|
15
|
+
x2 = %(<?xml version="1.0" encoding="UTF-8" ?><tag key="value">Français</tag>)
|
16
|
+
# => "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><tag key=\"value\">Fran\xC3\xA7ais</tag>"
|
17
|
+
x2.encoding
|
18
|
+
# => #<Encoding:UTF-8>
|
19
|
+
|
20
|
+
class OH < ::Ox::Sax
|
21
|
+
def start_element(name)
|
22
|
+
puts "EL: #{name} (#{name.encoding})"
|
23
|
+
end
|
24
|
+
|
25
|
+
def end_element(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def attr(key, value)
|
29
|
+
puts "AT: #{key} => #{value} (#{key.encoding} => #{value.encoding})"
|
30
|
+
end
|
31
|
+
|
32
|
+
def text(value)
|
33
|
+
puts "TX: #{value} (#{value.encoding})"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
::Ox.sax_parse OH.new, StringIO.new(x1)
|
38
|
+
# => AT: version => 1.0 (US-ASCII => ASCII-8BIT)
|
39
|
+
# AT: encoding => ISO-8859-1 (US-ASCII => ISO-8859-1)
|
40
|
+
# EL: tag (US-ASCII)
|
41
|
+
# AT: key => value (US-ASCII => ISO-8859-1)
|
42
|
+
# TX: Fran�ais (ISO-8859-1)
|
43
|
+
|
44
|
+
puts
|
45
|
+
|
46
|
+
::Ox.sax_parse OH.new, StringIO.new(x2)
|
47
|
+
# => AT: version => 1.0 (US-ASCII => ASCII-8BIT)
|
48
|
+
# AT: encoding => UTF-8 (US-ASCII => UTF-8)
|
49
|
+
# EL: tag (US-ASCII)
|
50
|
+
# AT: key => value (US-ASCII => UTF-8)
|
51
|
+
# TX: Français (UTF-8)
|
52
|
+
|
53
|
+
puts
|
54
|
+
x3 = %(<?xml version="1.0" encoding="ISO-8859-1" ?><tag Português="Español">Français</tag>).encode("ISO-8859-1")
|
55
|
+
::Ox.sax_parse OH.new, StringIO.new(x3)
|
56
|
+
|
57
|
+
puts
|
58
|
+
x4 = %(<?xml version="1.0" encoding="UTF-8" ?><tag Português="Español">Français</tag>)
|
59
|
+
::Ox.sax_parse OH.new, StringIO.new(x4)
|
60
|
+
|
data/test/func.rb
CHANGED
@@ -6,6 +6,7 @@ $: << File.join(File.dirname(__FILE__), "../ext")
|
|
6
6
|
|
7
7
|
require 'test/unit'
|
8
8
|
require 'optparse'
|
9
|
+
require 'date'
|
9
10
|
require 'ox'
|
10
11
|
|
11
12
|
$indent = 2
|
@@ -107,6 +108,10 @@ class Func < ::Test::Unit::TestCase
|
|
107
108
|
dump_and_load(Time.now, false)
|
108
109
|
end
|
109
110
|
|
111
|
+
def test_date
|
112
|
+
dump_and_load(Date.new(2011, 1, 5), false)
|
113
|
+
end
|
114
|
+
|
110
115
|
def test_array
|
111
116
|
dump_and_load([], false)
|
112
117
|
dump_and_load([1, 'a'], false)
|
@@ -262,10 +267,30 @@ class Func < ::Test::Unit::TestCase
|
|
262
267
|
e = StandardError.new("Some Error")
|
263
268
|
e.set_backtrace(["./func.rb:119: in test_exception",
|
264
269
|
"./fake.rb:57: in fake_func"])
|
270
|
+
dump_and_load(e, false)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_exception_bag
|
275
|
+
if RUBY_VERSION.start_with?('1.8')
|
276
|
+
assert(true)
|
277
|
+
else
|
278
|
+
xml = %{
|
279
|
+
<e c="FakeError">
|
280
|
+
<s a="mesg">Some Error</s>
|
281
|
+
<a a="bt">
|
282
|
+
<s>./func.rb:119: in test_exception</s>
|
283
|
+
<s>./fake.rb:57: in fake_func</s>
|
284
|
+
</a>
|
285
|
+
</e>
|
286
|
+
}
|
287
|
+
x = Ox.load(xml, :mode => :object, :effort => :auto_define)
|
288
|
+
assert_equal('Some Error', x.message())
|
289
|
+
assert(x.is_a?(Exception))
|
265
290
|
end
|
266
|
-
dump_and_load(e, false)
|
267
291
|
end
|
268
292
|
|
293
|
+
|
269
294
|
def test_struct
|
270
295
|
s = Struct.new('Box', :x, :y, :w, :h)
|
271
296
|
dump_and_load(s.new(2, 4, 10, 20), false)
|
data/test/perf.rb
CHANGED
@@ -45,7 +45,7 @@ class Perf
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
puts
|
48
|
-
puts "Comparison Matrix\n(performance factor, 2.0 row is
|
48
|
+
puts "Comparison Matrix\n(performance factor, 2.0 means row is twice as fast as column)"
|
49
49
|
puts ([' ' * width] + iva.map { |i| "%*s" % [width, i.title] }).join(' ')
|
50
50
|
puts (['-' * width] + iva.map { |i| '-' * width }).join(' ')
|
51
51
|
iva.each do |i|
|
data/test/sax_example.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
|
3
|
+
$: << '../lib'
|
4
|
+
$: << '../ext'
|
5
|
+
|
6
|
+
require 'stringio'
|
7
|
+
require 'ox'
|
8
|
+
|
9
|
+
class Sample < ::Ox::Sax
|
10
|
+
def start_element(name); puts "start: #{name}"; end
|
11
|
+
def end_element(name); puts "end: #{name}"; end
|
12
|
+
def attr(name, value); puts " #{name} => #{value}"; end
|
13
|
+
def text(value); puts "text #{value}"; end
|
14
|
+
end
|
15
|
+
|
16
|
+
io = StringIO.new(%{
|
17
|
+
<top name="sample">
|
18
|
+
<middle name="second">
|
19
|
+
<bottom name="third"/>
|
20
|
+
</middle>
|
21
|
+
</top>
|
22
|
+
})
|
23
|
+
|
24
|
+
handler = Sample.new()
|
25
|
+
Ox.sax_parse(handler, io)
|
26
|
+
|
27
|
+
# outputs
|
28
|
+
# start: top
|
29
|
+
# name => sample
|
30
|
+
# start: middle
|
31
|
+
# name => second
|
32
|
+
# start: bottom
|
33
|
+
# name => third
|
34
|
+
# end: bottom
|
35
|
+
# end: middle
|
36
|
+
# end: top
|
37
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-15 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! "A fast XML parser and object serializer that uses only standard C
|
15
15
|
lib.\n \nOptimized XML (Ox), as the name implies was written to provide
|
@@ -53,6 +53,8 @@ files:
|
|
53
53
|
- test/bench.rb
|
54
54
|
- test/bug1.rb
|
55
55
|
- test/bug2.rb
|
56
|
+
- test/bug3.rb
|
57
|
+
- test/bug4.rb
|
56
58
|
- test/cache16_test.rb
|
57
59
|
- test/cache8_test.rb
|
58
60
|
- test/cache_test.rb
|
@@ -93,6 +95,7 @@ files:
|
|
93
95
|
- test/sample/shape.rb
|
94
96
|
- test/sample/text.rb
|
95
97
|
- test/sample.rb
|
98
|
+
- test/sax_example.rb
|
96
99
|
- test/sax_test.rb
|
97
100
|
- test/test.rb
|
98
101
|
- test/Sample.graffle
|
@@ -126,4 +129,3 @@ signing_key:
|
|
126
129
|
specification_version: 3
|
127
130
|
summary: A fast XML parser and object serializer.
|
128
131
|
test_files: []
|
129
|
-
has_rdoc: true
|