ox 2.13.1 → 2.14.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +32 -5
- data/ext/ox/builder.c +5 -1
- data/ext/ox/dump.c +7 -19
- data/ext/ox/extconf.rb +12 -34
- data/ext/ox/gen_load.c +18 -96
- data/ext/ox/hash_load.c +39 -12
- data/ext/ox/obj_load.c +35 -64
- data/ext/ox/ox.c +60 -48
- data/ext/ox/ox.h +7 -15
- data/ext/ox/parse.c +7 -20
- data/ext/ox/sax.c +21 -91
- data/ext/ox/sax.h +1 -3
- data/ext/ox/sax_as.c +2 -6
- data/ext/ox/sax_buf.c +1 -1
- data/ext/ox/special.c +4 -3
- data/lib/ox/element.rb +21 -11
- data/lib/ox/version.rb +1 -1
- metadata +6 -6
data/ext/ox/hash_load.c
CHANGED
@@ -74,19 +74,14 @@ unmark(PInfo pi, VALUE val) {
|
|
74
74
|
}
|
75
75
|
|
76
76
|
static void
|
77
|
-
|
77
|
+
add_str(PInfo pi, VALUE s) {
|
78
78
|
Helper parent = helper_stack_peek(&pi->helpers);
|
79
|
-
volatile VALUE s = rb_str_new2(text);
|
80
79
|
volatile VALUE a;
|
81
80
|
|
82
|
-
#if
|
81
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
83
82
|
if (0 != pi->options->rb_enc) {
|
84
83
|
rb_enc_associate(s, pi->options->rb_enc);
|
85
84
|
}
|
86
|
-
#elif HAS_PRIVATE_ENCODING
|
87
|
-
if (Qnil != pi->options->rb_enc) {
|
88
|
-
rb_funcall(s, ox_force_encoding_id, 1, pi->options->rb_enc);
|
89
|
-
}
|
90
85
|
#endif
|
91
86
|
switch (parent->type) {
|
92
87
|
case NoCode:
|
@@ -106,6 +101,16 @@ add_text(PInfo pi, char *text, int closed) {
|
|
106
101
|
}
|
107
102
|
}
|
108
103
|
|
104
|
+
static void
|
105
|
+
add_text(PInfo pi, char *text, int closed) {
|
106
|
+
add_str(pi, rb_str_new2(text));
|
107
|
+
}
|
108
|
+
|
109
|
+
static void
|
110
|
+
add_cdata(PInfo pi, const char *text, size_t len) {
|
111
|
+
add_str(pi, rb_str_new(text, len));
|
112
|
+
}
|
113
|
+
|
109
114
|
static void
|
110
115
|
add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
111
116
|
if (helper_stack_empty(&pi->helpers)) {
|
@@ -126,14 +131,10 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
126
131
|
key = rb_str_new2(attrs->name);
|
127
132
|
}
|
128
133
|
val = rb_str_new2(attrs->value);
|
129
|
-
#if
|
134
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
130
135
|
if (0 != pi->options->rb_enc) {
|
131
136
|
rb_enc_associate(val, pi->options->rb_enc);
|
132
137
|
}
|
133
|
-
#elif HAS_PRIVATE_ENCODING
|
134
|
-
if (Qnil != pi->options->rb_enc) {
|
135
|
-
rb_funcall(val, ox_force_encoding_id, 1, pi->options->rb_enc);
|
136
|
-
}
|
137
138
|
#endif
|
138
139
|
rb_hash_aset(h, key, val);
|
139
140
|
}
|
@@ -258,6 +259,19 @@ struct _parseCallbacks _ox_hash_callbacks = {
|
|
258
259
|
|
259
260
|
ParseCallbacks ox_hash_callbacks = &_ox_hash_callbacks;
|
260
261
|
|
262
|
+
struct _parseCallbacks _ox_hash_cdata_callbacks = {
|
263
|
+
NULL,
|
264
|
+
NULL,
|
265
|
+
NULL,
|
266
|
+
add_cdata,
|
267
|
+
add_text,
|
268
|
+
add_element,
|
269
|
+
end_element,
|
270
|
+
finish,
|
271
|
+
};
|
272
|
+
|
273
|
+
ParseCallbacks ox_hash_cdata_callbacks = &_ox_hash_cdata_callbacks;
|
274
|
+
|
261
275
|
struct _parseCallbacks _ox_hash_no_attrs_callbacks = {
|
262
276
|
NULL,
|
263
277
|
NULL,
|
@@ -270,3 +284,16 @@ struct _parseCallbacks _ox_hash_no_attrs_callbacks = {
|
|
270
284
|
};
|
271
285
|
|
272
286
|
ParseCallbacks ox_hash_no_attrs_callbacks = &_ox_hash_no_attrs_callbacks;
|
287
|
+
|
288
|
+
struct _parseCallbacks _ox_hash_no_attrs_cdata_callbacks = {
|
289
|
+
NULL,
|
290
|
+
NULL,
|
291
|
+
NULL,
|
292
|
+
add_cdata,
|
293
|
+
add_text,
|
294
|
+
add_element_no_attrs,
|
295
|
+
end_element_no_attrs,
|
296
|
+
NULL,
|
297
|
+
};
|
298
|
+
|
299
|
+
ParseCallbacks ox_hash_no_attrs_cdata_callbacks = &_ox_hash_no_attrs_cdata_callbacks;
|
data/ext/ox/obj_load.c
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
#include <time.h>
|
12
12
|
|
13
13
|
#include "ruby.h"
|
14
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
15
|
+
#include "ruby/encoding.h"
|
16
|
+
#endif
|
14
17
|
#include "base64.h"
|
15
18
|
#include "ox.h"
|
16
19
|
|
@@ -39,10 +42,10 @@ static void fill_indent(PInfo pi, char *buf, size_t size);
|
|
39
42
|
|
40
43
|
|
41
44
|
struct _parseCallbacks _ox_obj_callbacks = {
|
42
|
-
instruct,
|
43
|
-
0,
|
44
|
-
0,
|
45
|
-
0,
|
45
|
+
instruct, // instruct,
|
46
|
+
0, // add_doctype,
|
47
|
+
0, // add_comment,
|
48
|
+
0, // add_cdata,
|
46
49
|
add_text,
|
47
50
|
add_element,
|
48
51
|
end_element,
|
@@ -125,7 +128,7 @@ resolve_classname(VALUE mod, const char *class_name, Effort effort, VALUE base_c
|
|
125
128
|
break;
|
126
129
|
case StrictEffort:
|
127
130
|
default:
|
128
|
-
|
131
|
+
// raise an error if name is not defined
|
129
132
|
clas = rb_const_get_at(mod, ci);
|
130
133
|
break;
|
131
134
|
}
|
@@ -143,7 +146,6 @@ classname2obj(const char *name, PInfo pi, VALUE base_class) {
|
|
143
146
|
}
|
144
147
|
}
|
145
148
|
|
146
|
-
#if HAS_RSTRUCT
|
147
149
|
inline static VALUE
|
148
150
|
structname2obj(const char *name) {
|
149
151
|
VALUE ost;
|
@@ -159,16 +161,12 @@ structname2obj(const char *name) {
|
|
159
161
|
}
|
160
162
|
}
|
161
163
|
ost = rb_const_get(ox_struct_class, rb_intern(s));
|
162
|
-
|
163
|
-
#if HAS_ENCODING_SUPPORT
|
164
|
-
return rb_struct_alloc_noinit(ost);
|
165
|
-
#elif HAS_PRIVATE_ENCODING
|
164
|
+
#if HAVE_RB_STRUCT_ALLOC_NOINIT
|
166
165
|
return rb_struct_alloc_noinit(ost);
|
167
166
|
#else
|
168
167
|
return rb_struct_new(ost);
|
169
168
|
#endif
|
170
169
|
}
|
171
|
-
#endif
|
172
170
|
|
173
171
|
inline static VALUE
|
174
172
|
parse_ulong(const char *s, PInfo pi) {
|
@@ -185,7 +183,7 @@ parse_ulong(const char *s, PInfo pi) {
|
|
185
183
|
return ULONG2NUM(n);
|
186
184
|
}
|
187
185
|
|
188
|
-
|
186
|
+
// 2010-07-09T10:47:45.895826162+09:00
|
189
187
|
inline static VALUE
|
190
188
|
parse_time(const char *text, VALUE clas) {
|
191
189
|
VALUE t;
|
@@ -239,6 +237,7 @@ static ID
|
|
239
237
|
get_var_sym_from_attrs(Attr a, void *encoding) {
|
240
238
|
for (; 0 != a->name; a++) {
|
241
239
|
if ('a' == *a->name && '\0' == *(a->name + 1)) {
|
240
|
+
name2var(a->value, encoding);
|
242
241
|
return name2var(a->value, encoding);
|
243
242
|
}
|
244
243
|
}
|
@@ -255,7 +254,6 @@ get_obj_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
|
255
254
|
return Qundef;
|
256
255
|
}
|
257
256
|
|
258
|
-
#if HAS_RSTRUCT
|
259
257
|
static VALUE
|
260
258
|
get_struct_from_attrs(Attr a) {
|
261
259
|
for (; 0 != a->name; a++) {
|
@@ -265,7 +263,6 @@ get_struct_from_attrs(Attr a) {
|
|
265
263
|
}
|
266
264
|
return Qundef;
|
267
265
|
}
|
268
|
-
#endif
|
269
266
|
|
270
267
|
static VALUE
|
271
268
|
get_class_from_attrs(Attr a, PInfo pi, VALUE base_class) {
|
@@ -363,7 +360,7 @@ parse_regexp(const char *text) {
|
|
363
360
|
int options = 0;
|
364
361
|
|
365
362
|
te = text + strlen(text) - 1;
|
366
|
-
#
|
363
|
+
#ifdef ONIG_OPTION_IGNORECASE
|
367
364
|
for (; text < te && '/' != *te; te--) {
|
368
365
|
switch (*te) {
|
369
366
|
case 'i': options |= ONIG_OPTION_IGNORECASE; break;
|
@@ -379,18 +376,12 @@ parse_regexp(const char *text) {
|
|
379
376
|
static void
|
380
377
|
instruct(PInfo pi, const char *target, Attr attrs, const char *content) {
|
381
378
|
if (0 == strcmp("xml", target)) {
|
382
|
-
#if
|
379
|
+
#if HAVE_RB_ENC_FIND
|
383
380
|
for (; 0 != attrs->name; attrs++) {
|
384
381
|
if (0 == strcmp("encoding", attrs->name)) {
|
385
382
|
pi->options->rb_enc = rb_enc_find(attrs->value);
|
386
383
|
}
|
387
384
|
}
|
388
|
-
#elif HAS_PRIVATE_ENCODING
|
389
|
-
for (; 0 != attrs->name; attrs++) {
|
390
|
-
if (0 == strcmp("encoding", attrs->name)) {
|
391
|
-
pi->options->rb_enc = rb_str_new2(attrs->value);
|
392
|
-
}
|
393
|
-
}
|
394
385
|
#endif
|
395
386
|
}
|
396
387
|
}
|
@@ -417,14 +408,10 @@ add_text(PInfo pi, char *text, int closed) {
|
|
417
408
|
case NoCode:
|
418
409
|
case StringCode:
|
419
410
|
h->obj = rb_str_new2(text);
|
420
|
-
#if
|
411
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
421
412
|
if (0 != pi->options->rb_enc) {
|
422
413
|
rb_enc_associate(h->obj, pi->options->rb_enc);
|
423
414
|
}
|
424
|
-
#elif HAS_PRIVATE_ENCODING
|
425
|
-
if (Qnil != pi->options->rb_enc) {
|
426
|
-
rb_funcall(h->obj, ox_force_encoding_id, 1, pi->options->rb_enc);
|
427
|
-
}
|
428
415
|
#endif
|
429
416
|
if (0 != pi->circ_array) {
|
430
417
|
circ_array_set(pi->circ_array, h->obj, (unsigned long)pi->id);
|
@@ -494,14 +481,10 @@ add_text(PInfo pi, char *text, int closed) {
|
|
494
481
|
|
495
482
|
from_base64(text, (uchar*)str);
|
496
483
|
v = rb_str_new(str, str_size);
|
497
|
-
#if
|
484
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
498
485
|
if (0 != pi->options->rb_enc) {
|
499
486
|
rb_enc_associate(v, pi->options->rb_enc);
|
500
487
|
}
|
501
|
-
#elif HAS_PRIVATE_ENCODING
|
502
|
-
if (0 != pi->options->rb_enc) {
|
503
|
-
rb_funcall(v, ox_force_encoding_id, 1, pi->options->rb_enc);
|
504
|
-
}
|
505
488
|
#endif
|
506
489
|
if (0 != pi->circ_array) {
|
507
490
|
circ_array_set(pi->circ_array, v, (unsigned long)h->obj);
|
@@ -542,11 +525,7 @@ add_text(PInfo pi, char *text, int closed) {
|
|
542
525
|
h->obj = rb_cstr_to_inum(text, 10, 1);
|
543
526
|
break;
|
544
527
|
case BigDecimalCode:
|
545
|
-
#if HAS_BIGDECIMAL
|
546
528
|
h->obj = rb_funcall(rb_cObject, ox_bigdecimal_id, 1, rb_str_new2(text));
|
547
|
-
#else
|
548
|
-
h->obj = Qnil;
|
549
|
-
#endif
|
550
529
|
break;
|
551
530
|
default:
|
552
531
|
h->obj = Qnil;
|
@@ -580,7 +559,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
580
559
|
printf("%s%s\n", indent, buf);
|
581
560
|
}
|
582
561
|
}
|
583
|
-
if (helper_stack_empty(&pi->helpers)) {
|
562
|
+
if (helper_stack_empty(&pi->helpers)) { // top level object
|
584
563
|
if (0 != (id = get_id_from_attrs(pi, attrs))) {
|
585
564
|
pi->circ_array = circ_array_new();
|
586
565
|
}
|
@@ -601,7 +580,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
601
580
|
h->obj = Qfalse;
|
602
581
|
break;
|
603
582
|
case StringCode:
|
604
|
-
|
583
|
+
// h->obj will be replaced by add_text if it is called
|
605
584
|
h->obj = ox_empty_string;
|
606
585
|
if (0 != pi->circ_array) {
|
607
586
|
pi->id = get_id_from_attrs(pi, attrs);
|
@@ -618,8 +597,8 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
618
597
|
case ComplexCode:
|
619
598
|
case DateCode:
|
620
599
|
case TimeCode:
|
621
|
-
case RationalCode:
|
622
|
-
|
600
|
+
case RationalCode: // sub elements read next
|
601
|
+
// value will be read in the following add_text
|
623
602
|
h->obj = Qundef;
|
624
603
|
break;
|
625
604
|
case String64Code:
|
@@ -641,7 +620,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
641
620
|
}
|
642
621
|
break;
|
643
622
|
case RangeCode:
|
644
|
-
h->obj =
|
623
|
+
h->obj = rb_ary_new_from_args(3, Qnil, Qnil, Qfalse);
|
645
624
|
break;
|
646
625
|
case RawCode:
|
647
626
|
if (hasChildren) {
|
@@ -670,15 +649,10 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
670
649
|
}
|
671
650
|
break;
|
672
651
|
case StructCode:
|
673
|
-
#if HAS_RSTRUCT
|
674
652
|
h->obj = get_struct_from_attrs(attrs);
|
675
653
|
if (0 != pi->circ_array) {
|
676
654
|
circ_array_set(pi->circ_array, h->obj, get_id_from_attrs(pi, attrs));
|
677
655
|
}
|
678
|
-
#else
|
679
|
-
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
680
|
-
return;
|
681
|
-
#endif
|
682
656
|
break;
|
683
657
|
case ClassCode:
|
684
658
|
if (Qundef == (h->obj = get_class_from_attrs(attrs, pi, ox_bag_clas))) {
|
@@ -726,12 +700,15 @@ end_element(PInfo pi, const char *ename) {
|
|
726
700
|
Helper ph = helper_stack_peek(&pi->helpers);
|
727
701
|
|
728
702
|
if (ox_empty_string == h->obj) {
|
729
|
-
|
703
|
+
// special catch for empty strings
|
730
704
|
h->obj = rb_str_new2("");
|
731
|
-
}
|
732
|
-
if (Qundef == h->obj) {
|
705
|
+
} else if (Qundef == h->obj) {
|
733
706
|
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
734
707
|
return;
|
708
|
+
} else if (RangeCode == h->type) { // Expect an array of 3 elements.
|
709
|
+
const VALUE *ap = RARRAY_PTR(h->obj);
|
710
|
+
|
711
|
+
h->obj = rb_range_new(*ap, *(ap + 1), Qtrue == *(ap + 2));
|
735
712
|
}
|
736
713
|
pi->obj = h->obj;
|
737
714
|
if (0 != ph) {
|
@@ -742,45 +719,39 @@ end_element(PInfo pi, const char *ename) {
|
|
742
719
|
case ExceptionCode:
|
743
720
|
case ObjectCode:
|
744
721
|
if (Qnil != ph->obj) {
|
745
|
-
if (0 == h->var) {
|
722
|
+
if (0 == h->var || NULL == rb_id2name(h->var )) {
|
746
723
|
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
747
724
|
return;
|
748
725
|
}
|
726
|
+
if (RUBY_T_OBJECT != rb_type(ph->obj)) {
|
727
|
+
set_error(&pi->err, "Corrupt object encoding", pi->str, pi->s);
|
728
|
+
return;
|
729
|
+
}
|
749
730
|
rb_ivar_set(ph->obj, h->var, h->obj);
|
750
731
|
}
|
751
732
|
break;
|
752
733
|
case StructCode:
|
753
|
-
#if HAS_RSTRUCT
|
754
734
|
if (0 == h->var) {
|
755
735
|
set_error(&pi->err, "Invalid element for object mode", pi->str, pi->s);
|
756
736
|
return;
|
757
737
|
}
|
758
738
|
rb_struct_aset(ph->obj, h->var, h->obj);
|
759
|
-
#else
|
760
|
-
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
761
|
-
return;
|
762
|
-
#endif
|
763
739
|
break;
|
764
740
|
case HashCode:
|
765
741
|
// put back h
|
766
742
|
helper_stack_push(&pi->helpers, h->var, h->obj, KeyCode);
|
767
743
|
break;
|
768
744
|
case RangeCode:
|
769
|
-
#if HAS_RSTRUCT
|
770
745
|
if (ox_beg_id == h->var) {
|
771
|
-
|
746
|
+
rb_ary_store(ph->obj, 0, h->obj);
|
772
747
|
} else if (ox_end_id == h->var) {
|
773
|
-
|
748
|
+
rb_ary_store(ph->obj, 1, h->obj);
|
774
749
|
} else if (ox_excl_id == h->var) {
|
775
|
-
|
750
|
+
rb_ary_store(ph->obj, 2, h->obj);
|
776
751
|
} else {
|
777
752
|
set_error(&pi->err, "Invalid range attribute", pi->str, pi->s);
|
778
753
|
return;
|
779
754
|
}
|
780
|
-
#else
|
781
|
-
set_error(&pi->err, "Ruby structs not supported with this verion of Ruby", pi->str, pi->s);
|
782
|
-
return;
|
783
|
-
#endif
|
784
755
|
break;
|
785
756
|
case KeyCode:
|
786
757
|
{
|
@@ -935,7 +906,7 @@ parse_xsd_time(const char *text, VALUE clas) {
|
|
935
906
|
#endif
|
936
907
|
}
|
937
908
|
|
938
|
-
|
909
|
+
// debug functions
|
939
910
|
static void
|
940
911
|
fill_indent(PInfo pi, char *buf, size_t size) {
|
941
912
|
size_t cnt;
|
data/ext/ox/ox.c
CHANGED
@@ -145,6 +145,7 @@ static VALUE symbolize_keys_sym;
|
|
145
145
|
static VALUE symbolize_sym;
|
146
146
|
static VALUE tolerant_sym;
|
147
147
|
static VALUE trace_sym;
|
148
|
+
static VALUE with_cdata_sym;
|
148
149
|
static VALUE with_dtd_sym;
|
149
150
|
static VALUE with_instruct_sym;
|
150
151
|
static VALUE with_xml_sym;
|
@@ -154,10 +155,8 @@ static VALUE element_key_mod_sym;
|
|
154
155
|
static ID encoding_id;
|
155
156
|
static ID has_key_id;
|
156
157
|
|
157
|
-
#if
|
158
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
158
159
|
rb_encoding *ox_utf8_encoding = 0;
|
159
|
-
#elif HAS_PRIVATE_ENCODING
|
160
|
-
VALUE ox_utf8_encoding = Qnil;
|
161
160
|
#else
|
162
161
|
void *ox_utf8_encoding = 0;
|
163
162
|
#endif
|
@@ -181,16 +180,13 @@ struct _options ox_default_options = {
|
|
181
180
|
true, // convert_special
|
182
181
|
No, // allow_invalid
|
183
182
|
false, // no_empty
|
183
|
+
false, // with_cdata
|
184
184
|
{ '\0' }, // inv_repl
|
185
185
|
{ '\0' }, // strip_ns
|
186
186
|
NULL, // html_hints
|
187
187
|
Qnil, // attr_key_mod;
|
188
188
|
Qnil, // element_key_mod;
|
189
|
-
#if HAS_PRIVATE_ENCODING
|
190
|
-
Qnil // rb_enc
|
191
|
-
#else
|
192
189
|
0 // rb_enc
|
193
|
-
#endif
|
194
190
|
};
|
195
191
|
|
196
192
|
extern ParseCallbacks ox_obj_callbacks;
|
@@ -198,7 +194,9 @@ extern ParseCallbacks ox_gen_callbacks;
|
|
198
194
|
extern ParseCallbacks ox_limited_callbacks;
|
199
195
|
extern ParseCallbacks ox_nomode_callbacks;
|
200
196
|
extern ParseCallbacks ox_hash_callbacks;
|
197
|
+
extern ParseCallbacks ox_hash_cdata_callbacks;
|
201
198
|
extern ParseCallbacks ox_hash_no_attrs_callbacks;
|
199
|
+
extern ParseCallbacks ox_hash_no_attrs_cdata_callbacks;
|
202
200
|
|
203
201
|
static void parse_dump_options(VALUE ropts, Options copts);
|
204
202
|
|
@@ -296,6 +294,7 @@ hints_to_overlay(Hints hints) {
|
|
296
294
|
* - _:convert_special_ [true|false|nil] flag indicating special characters like < are converted with the SAX parser
|
297
295
|
* - _:invalid_replace_ [nil|String] replacement string for invalid XML characters on dump. nil indicates include anyway as hex. A string, limited to 10 characters will replace the invalid character with the replace.
|
298
296
|
* - _:no_empty_ [true|false|nil] flag indicating there should be no empty elements in a dump
|
297
|
+
* - _:with_cdata_ [true|false] includes cdata in hash_load results
|
299
298
|
* - _:strip_namespace_ [String|true|false] false or "" results in no namespace stripping. A string of "*" or true will strip all namespaces. Any other non-empty string indicates that matching namespaces will be stripped.
|
300
299
|
* - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
|
301
300
|
* - _:active_ - make the normal callback for the element
|
@@ -330,6 +329,7 @@ get_def_opts(VALUE self) {
|
|
330
329
|
rb_hash_aset(opts, smart_sym, (Yes == ox_default_options.smart) ? Qtrue : ((No == ox_default_options.smart) ? Qfalse : Qnil));
|
331
330
|
rb_hash_aset(opts, convert_special_sym, (ox_default_options.convert_special) ? Qtrue : Qfalse);
|
332
331
|
rb_hash_aset(opts, no_empty_sym, (ox_default_options.no_empty) ? Qtrue : Qfalse);
|
332
|
+
rb_hash_aset(opts, with_cdata_sym, (ox_default_options.with_cdata) ? Qtrue : Qfalse);
|
333
333
|
switch (ox_default_options.mode) {
|
334
334
|
case ObjMode: rb_hash_aset(opts, mode_sym, object_sym); break;
|
335
335
|
case GenMode: rb_hash_aset(opts, mode_sym, generic_sym); break;
|
@@ -437,6 +437,7 @@ sax_html_overlay(VALUE self) {
|
|
437
437
|
* - _:smart_ [true|false|nil] flag indicating the SAX parser uses hints if available (use with html)
|
438
438
|
* - _:invalid_replace_ [nil|String] replacement string for invalid XML characters on dump. nil indicates include anyway as hex. A string, limited to 10 characters will replace the invalid character with the replace.
|
439
439
|
* - _:strip_namespace_ [nil|String|true|false] "" or false result in no namespace stripping. A string of "*" or true will strip all namespaces. Any other non-empty string indicates that matching namespaces will be stripped.
|
440
|
+
* - _:with_cdata_ [true|false] includes cdata in hash_load results
|
440
441
|
* - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
|
441
442
|
* - _:active_ - make the normal callback for the element
|
442
443
|
* - _:nest_ok_ - active but ignore nest check
|
@@ -470,11 +471,8 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
470
471
|
} else {
|
471
472
|
Check_Type(v, T_STRING);
|
472
473
|
strncpy(ox_default_options.encoding, StringValuePtr(v), sizeof(ox_default_options.encoding) - 1);
|
473
|
-
#if
|
474
|
+
#if HAVE_RB_ENC_FIND
|
474
475
|
ox_default_options.rb_enc = rb_enc_find(ox_default_options.encoding);
|
475
|
-
#elif HAS_PRIVATE_ENCODING
|
476
|
-
ox_default_options.rb_enc = rb_str_new2(ox_default_options.encoding);
|
477
|
-
rb_gc_register_address(&ox_default_options.rb_enc);
|
478
476
|
#endif
|
479
477
|
}
|
480
478
|
|
@@ -639,6 +637,10 @@ set_def_opts(VALUE self, VALUE opts) {
|
|
639
637
|
rb_hash_foreach(v, set_overlay, (VALUE)ox_default_options.html_hints);
|
640
638
|
}
|
641
639
|
}
|
640
|
+
if (Qnil != (v = rb_hash_lookup(opts, with_cdata_sym))) {
|
641
|
+
ox_default_options.with_cdata = (Qtrue == v);
|
642
|
+
}
|
643
|
+
|
642
644
|
ox_default_options.element_key_mod = rb_hash_lookup2(opts, element_key_mod_sym, ox_default_options.element_key_mod);
|
643
645
|
ox_default_options.attr_key_mod = rb_hash_lookup2(opts, attr_key_mod_sym, ox_default_options.attr_key_mod);
|
644
646
|
|
@@ -674,14 +676,14 @@ to_obj(VALUE self, VALUE ruby_xml) {
|
|
674
676
|
xml = ALLOCA_N(char, len);
|
675
677
|
}
|
676
678
|
memcpy(xml, x, len);
|
677
|
-
#
|
679
|
+
#ifdef RB_GC_GUARD
|
678
680
|
rb_gc_disable();
|
679
681
|
#endif
|
680
682
|
obj = ox_parse(xml, len - 1, ox_obj_callbacks, 0, &options, &err);
|
681
683
|
if (SMALL_XML < len) {
|
682
684
|
xfree(xml);
|
683
685
|
}
|
684
|
-
#
|
686
|
+
#ifdef RB_GC_GUARD
|
685
687
|
RB_GC_GUARD(obj);
|
686
688
|
rb_gc_enable();
|
687
689
|
#endif
|
@@ -847,8 +849,11 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
847
849
|
options.margin[sizeof(options.margin) - 1] = '\0';
|
848
850
|
options.margin_len = strlen(options.margin);
|
849
851
|
}
|
852
|
+
if (Qnil != (v = rb_hash_lookup(h, with_cdata_sym))) {
|
853
|
+
options.with_cdata = (Qtrue == v);
|
854
|
+
}
|
850
855
|
}
|
851
|
-
#if
|
856
|
+
#if HAVE_RB_ENC_FIND
|
852
857
|
if ('\0' == *options.encoding) {
|
853
858
|
if (Qnil != encoding) {
|
854
859
|
options.rb_enc = rb_enc_from_index(rb_enc_get_index(encoding));
|
@@ -858,26 +863,15 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
858
863
|
} else if (0 == options.rb_enc) {
|
859
864
|
options.rb_enc = rb_enc_find(options.encoding);
|
860
865
|
}
|
861
|
-
#elif HAS_PRIVATE_ENCODING
|
862
|
-
if ('\0' == *options.encoding) {
|
863
|
-
if (Qnil != encoding) {
|
864
|
-
options.rb_enc = encoding;
|
865
|
-
} else {
|
866
|
-
options.rb_enc = Qnil;
|
867
|
-
}
|
868
|
-
} else if (0 == options.rb_enc) {
|
869
|
-
options.rb_enc = rb_str_new2(options.encoding);
|
870
|
-
rb_gc_register_address(&options.rb_enc);
|
871
|
-
}
|
872
866
|
#endif
|
873
867
|
xml = defuse_bom(xml, &options);
|
874
868
|
switch (options.mode) {
|
875
869
|
case ObjMode:
|
876
|
-
#
|
870
|
+
#ifdef RB_GC_GUARD
|
877
871
|
rb_gc_disable();
|
878
872
|
#endif
|
879
873
|
obj = ox_parse(xml, len, ox_obj_callbacks, 0, &options, err);
|
880
|
-
#
|
874
|
+
#ifdef RB_GC_GUARD
|
881
875
|
RB_GC_GUARD(obj);
|
882
876
|
rb_gc_enable();
|
883
877
|
#endif
|
@@ -889,10 +883,18 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
889
883
|
obj = ox_parse(xml, len, ox_limited_callbacks, 0, &options, err);
|
890
884
|
break;
|
891
885
|
case HashMode:
|
892
|
-
|
886
|
+
if (options.with_cdata) {
|
887
|
+
obj = ox_parse(xml, len, ox_hash_cdata_callbacks, 0, &options, err);
|
888
|
+
} else {
|
889
|
+
obj = ox_parse(xml, len, ox_hash_callbacks, 0, &options, err);
|
890
|
+
}
|
893
891
|
break;
|
894
892
|
case HashNoAttrMode:
|
895
|
-
|
893
|
+
if (options.with_cdata) {
|
894
|
+
obj = ox_parse(xml, len, ox_hash_no_attrs_cdata_callbacks, 0, &options, err);
|
895
|
+
} else {
|
896
|
+
obj = ox_parse(xml, len, ox_hash_no_attrs_callbacks, 0, &options, err);
|
897
|
+
}
|
896
898
|
break;
|
897
899
|
case NoMode:
|
898
900
|
obj = ox_parse(xml, len, ox_nomode_callbacks, 0, &options, err);
|
@@ -928,6 +930,7 @@ load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, E
|
|
928
930
|
* - *:symbolize_keys* [true|false|nil] symbolize element attribute keys or leave as Strings
|
929
931
|
* - *:invalid_replace* [nil|String] replacement string for invalid XML characters on dump. nil indicates include anyway as hex. A string, limited to 10 characters will replace the invalid character with the replace.
|
930
932
|
* - *:strip_namespace* [String|true|false] "" or false result in no namespace stripping. A string of "*" or true will strip all namespaces. Any other non-empty string indicates that matching namespaces will be stripped.
|
933
|
+
* - *:with_cdata* [true|false] if true cdata is included in hash_load output otherwise it is not.
|
931
934
|
*/
|
932
935
|
static VALUE
|
933
936
|
load_str(int argc, VALUE *argv, VALUE self) {
|
@@ -946,14 +949,8 @@ load_str(int argc, VALUE *argv, VALUE self) {
|
|
946
949
|
} else {
|
947
950
|
xml = ALLOCA_N(char, len);
|
948
951
|
}
|
949
|
-
#if
|
950
|
-
#ifdef MACRUBY_RUBY
|
951
|
-
encoding = rb_funcall(*argv, encoding_id, 0);
|
952
|
-
#else
|
952
|
+
#if HAVE_RB_OBJ_ENCODING
|
953
953
|
encoding = rb_obj_encoding(*argv);
|
954
|
-
#endif
|
955
|
-
#elif HAS_PRIVATE_ENCODING
|
956
|
-
encoding = rb_funcall(*argv, encoding_id, 0);
|
957
954
|
#else
|
958
955
|
encoding = Qnil;
|
959
956
|
#endif
|
@@ -1319,21 +1316,38 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
1319
1316
|
rb_raise(rb_eNoMemError, "Not enough memory.\n");
|
1320
1317
|
}
|
1321
1318
|
rstr = rb_str_new2(xml);
|
1322
|
-
#if
|
1319
|
+
#if HAVE_RB_ENC_ASSOCIATE
|
1323
1320
|
if ('\0' != *copts.encoding) {
|
1324
1321
|
rb_enc_associate(rstr, rb_enc_find(copts.encoding));
|
1325
1322
|
}
|
1326
|
-
#elif HAS_PRIVATE_ENCODING
|
1327
|
-
if ('\0' != *copts.encoding) {
|
1328
|
-
rb_funcall(rstr, ox_force_encoding_id, 1, rb_str_new2(copts.encoding));
|
1329
|
-
}
|
1330
1323
|
#endif
|
1331
1324
|
xfree(xml);
|
1332
1325
|
|
1333
1326
|
return rstr;
|
1334
1327
|
}
|
1335
1328
|
|
1336
|
-
/* call-seq:
|
1329
|
+
/* call-seq: to_xml(obj, options) => xml-string
|
1330
|
+
*
|
1331
|
+
* Dumps an Object (obj) to a string.
|
1332
|
+
* - +obj+ [Object] Object to serialize as an XML document String
|
1333
|
+
* - +options+ [Hash] formating options
|
1334
|
+
* - *:indent* [Fixnum] format expected
|
1335
|
+
* - *:no_empty* [true|false] if true don't output empty elements
|
1336
|
+
* - *:xsd_date* [true|false] use XSD date format if true, default: false
|
1337
|
+
* - *:circular* [true|false] allow circular references, default: false
|
1338
|
+
* - *:strict|:tolerant]* [ :effort effort to use when an undumpable object (e.g., IO) is encountered, default: :strict
|
1339
|
+
* - _:strict_ - raise an NotImplementedError if an undumpable object is encountered
|
1340
|
+
* - _:tolerant_ - replaces undumplable objects with nil
|
1341
|
+
*
|
1342
|
+
* Note that an indent of less than zero will result in a tight one line output
|
1343
|
+
* unless the text in the XML fields contain new line characters.
|
1344
|
+
*/
|
1345
|
+
static VALUE
|
1346
|
+
to_xml(int argc, VALUE *argv, VALUE self) {
|
1347
|
+
return dump(argc, argv, self);
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
/* call-seq: to_file(file_path, obj, options) => Object
|
1337
1351
|
*
|
1338
1352
|
* Dumps an Object to the specified file.
|
1339
1353
|
* - +file_path+ [String] file path to write the XML document to
|
@@ -1392,7 +1406,7 @@ void Init_ox() {
|
|
1392
1406
|
rb_define_module_function(Ox, "sax_parse", sax_parse, -1);
|
1393
1407
|
rb_define_module_function(Ox, "sax_html", sax_html, -1);
|
1394
1408
|
|
1395
|
-
rb_define_module_function(Ox, "to_xml",
|
1409
|
+
rb_define_module_function(Ox, "to_xml", to_xml, -1);
|
1396
1410
|
rb_define_module_function(Ox, "dump", dump, -1);
|
1397
1411
|
|
1398
1412
|
rb_define_module_function(Ox, "load_file", load_file, -1);
|
@@ -1525,6 +1539,7 @@ void Init_ox() {
|
|
1525
1539
|
symbolize_sym = ID2SYM(rb_intern("symbolize")); rb_gc_register_address(&symbolize_sym);
|
1526
1540
|
tolerant_sym = ID2SYM(rb_intern("tolerant")); rb_gc_register_address(&tolerant_sym);
|
1527
1541
|
trace_sym = ID2SYM(rb_intern("trace")); rb_gc_register_address(&trace_sym);
|
1542
|
+
with_cdata_sym = ID2SYM(rb_intern("with_cdata")); rb_gc_register_address(&with_cdata_sym);
|
1528
1543
|
with_dtd_sym = ID2SYM(rb_intern("with_dtd")); rb_gc_register_address(&with_dtd_sym);
|
1529
1544
|
with_instruct_sym = ID2SYM(rb_intern("with_instructions")); rb_gc_register_address(&with_instruct_sym);
|
1530
1545
|
with_xml_sym = ID2SYM(rb_intern("with_xml")); rb_gc_register_address(&with_xml_sym);
|
@@ -1555,11 +1570,8 @@ void Init_ox() {
|
|
1555
1570
|
rb_define _module_function(Ox, "cache8_test", cache8_test, 0);
|
1556
1571
|
#endif
|
1557
1572
|
|
1558
|
-
#if
|
1573
|
+
#if HAVE_RB_ENC_FIND
|
1559
1574
|
ox_utf8_encoding = rb_enc_find("UTF-8");
|
1560
|
-
#elif HAS_PRIVATE_ENCODING
|
1561
|
-
ox_utf8_encoding = rb_str_new2("UTF-8");
|
1562
|
-
rb_gc_register_address(&ox_utf8_encoding);
|
1563
1575
|
#endif
|
1564
1576
|
}
|
1565
1577
|
|
@@ -1580,7 +1592,7 @@ _ox_raise_error(const char *msg, const char *xml, const char *current, const cha
|
|
1580
1592
|
xline++;
|
1581
1593
|
}
|
1582
1594
|
}
|
1583
|
-
#
|
1595
|
+
#ifdef RB_GC_GUARD
|
1584
1596
|
rb_gc_enable();
|
1585
1597
|
#endif
|
1586
1598
|
rb_raise(ox_parse_error_class, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line);
|