ox 2.13.1 → 2.14.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -74,19 +74,14 @@ unmark(PInfo pi, VALUE val) {
74
74
  }
75
75
 
76
76
  static void
77
- add_text(PInfo pi, char *text, int closed) {
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 HAS_ENCODING_SUPPORT
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 HAS_ENCODING_SUPPORT
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;
@@ -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, /* instruct, */
43
- 0, /* add_doctype, */
44
- 0, /* add_comment, */
45
- 0, /* add_cdata, */
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
- /* raise an error if name is not defined */
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
- /* use encoding as the indicator for Ruby 1.8.7 or 1.9.x */
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
- /* 2010-07-09T10:47:45.895826162+09:00 */
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
- #if HAS_ONIG
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 HAS_ENCODING_SUPPORT
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 HAS_ENCODING_SUPPORT
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 HAS_ENCODING_SUPPORT
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)) { /* top level object */
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
- /* h->obj will be replaced by add_text if it is called */
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: /* sub elements read next */
622
- /* value will be read in the following add_text */
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 = rb_range_new(ox_zero_fixnum, ox_zero_fixnum, Qfalse);
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
- /* special catch for empty strings */
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
- RSTRUCT_SET(ph->obj, 0, h->obj);
746
+ rb_ary_store(ph->obj, 0, h->obj);
772
747
  } else if (ox_end_id == h->var) {
773
- RSTRUCT_SET(ph->obj, 1, h->obj);
748
+ rb_ary_store(ph->obj, 1, h->obj);
774
749
  } else if (ox_excl_id == h->var) {
775
- RSTRUCT_SET(ph->obj, 2, h->obj);
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
- /* debug functions */
909
+ // debug functions
939
910
  static void
940
911
  fill_indent(PInfo pi, char *buf, size_t size) {
941
912
  size_t cnt;
@@ -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 HAS_ENCODING_SUPPORT
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 &lt; 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 HAS_ENCODING_SUPPORT
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
- #if HAS_GC_GUARD
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
- #if HAS_GC_GUARD
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 HAS_ENCODING_SUPPORT
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
- #if HAS_GC_GUARD
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
- #if HAS_GC_GUARD
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
- obj = ox_parse(xml, len, ox_hash_callbacks, 0, &options, err);
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
- obj = ox_parse(xml, len, ox_hash_no_attrs_callbacks, 0, &options, err);
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 HAS_ENCODING_SUPPORT
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 HAS_ENCODING_SUPPORT
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: to_file(file_path, obj, options)
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", dump, -1);
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 HAS_ENCODING_SUPPORT
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
- #if HAS_GC_GUARD
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);