ox 2.4.0 → 2.4.1

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 CHANGED
@@ -34,6 +34,18 @@ A fast XML parser and Object marshaller as a Ruby gem.
34
34
 
35
35
  ## Release Notes
36
36
 
37
+ ### Release 2.4.1
38
+
39
+ - Made SAX smarter a little smarter or rather let it handle unquoted string
40
+ with a / at the end.
41
+
42
+ - Fixed bug with reporting errors of element names that are too long.
43
+
44
+ - Added overlay feature to give control over which elements generate callbacks
45
+ with the SAX parser.
46
+
47
+ - Element.locate now includes self if the path is relative and starts with a wildcard.
48
+
37
49
  ### Release 2.4.0
38
50
 
39
51
  - Added Ox::Builder that constructs an XML string or writes XML to a stream
@@ -154,6 +166,19 @@ puts "Same? #{doc == doc2}"
154
166
  # true
155
167
  ```
156
168
 
169
+ ### HTML Parsing:
170
+
171
+ Ox can be used to parse HTML with a few options changes. HTML is often loose in
172
+ regard to conformance. For HTML parsing try these options.
173
+
174
+ ```ruby
175
+ Ox.default_options = {
176
+ mode: :generic,
177
+ effort: :tolerant,
178
+ smart: true
179
+ }
180
+ ```
181
+
157
182
  ### SAX XML Parsing:
158
183
 
159
184
  ```ruby
@@ -533,19 +533,19 @@ dump_first_obj(VALUE obj, Out out) {
533
533
  if ('\0' == *copts->encoding) {
534
534
  dump_value(out, "<?xml version=\"1.0\"?>", 21);
535
535
  } else {
536
- cnt = sprintf(buf, "<?xml version=\"1.0\" encoding=\"%s\"?>", copts->encoding);
536
+ cnt = snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"%s\"?>", copts->encoding);
537
537
  dump_value(out, buf, cnt);
538
538
  }
539
539
  }
540
540
  if (Yes == copts->with_instruct) {
541
- cnt = sprintf(buf, "%s<?ox version=\"1.0\" mode=\"object\"%s%s?>",
541
+ cnt = snprintf(buf, sizeof(buf), "%s<?ox version=\"1.0\" mode=\"object\"%s%s?>",
542
542
  (out->buf < out->cur) ? "\n" : "",
543
543
  (Yes == copts->circular) ? " circular=\"yes\"" : ((No == copts->circular) ? " circular=\"no\"" : ""),
544
544
  (Yes == copts->xsd_date) ? " xsd_date=\"yes\"" : ((No == copts->xsd_date) ? " xsd_date=\"no\"" : ""));
545
545
  dump_value(out, buf, cnt);
546
546
  }
547
547
  if (Yes == copts->with_dtd) {
548
- cnt = sprintf(buf, "%s<!DOCTYPE %c SYSTEM \"ox.dtd\">", (out->buf < out->cur) ? "\n" : "", obj_class_code(obj));
548
+ cnt = snprintf(buf, sizeof(buf), "%s<!DOCTYPE %c SYSTEM \"ox.dtd\">", (out->buf < out->cur) ? "\n" : "", obj_class_code(obj));
549
549
  dump_value(out, buf, cnt);
550
550
  }
551
551
  dump_obj(0, obj, 0, out);
@@ -648,7 +648,7 @@ dump_obj(ID aid, VALUE obj, int depth, Out out) {
648
648
  break;
649
649
  case T_FLOAT:
650
650
  e.type = FloatCode;
651
- cnt = sprintf(value_buf, "%0.16g", rb_num2dbl(obj)); /* used sprintf due to bug in snprintf */
651
+ cnt = snprintf(value_buf, sizeof(value_buf), "%0.16g", rb_num2dbl(obj));
652
652
  out->w_start(out, &e);
653
653
  dump_value(out, value_buf, cnt);
654
654
  e.indent = -1;
@@ -6,6 +6,7 @@
6
6
  #include <stdlib.h>
7
7
  #include <errno.h>
8
8
  #include <stdint.h>
9
+ #include <stdbool.h>
9
10
  #include <stdio.h>
10
11
  #include <string.h>
11
12
 
@@ -26,6 +27,7 @@ void Init_ox();
26
27
 
27
28
  VALUE Ox = Qnil;
28
29
 
30
+ ID ox_abort_id;
29
31
  ID ox_at_column_id;
30
32
  ID ox_at_content_id;
31
33
  ID ox_at_id;
@@ -104,18 +106,24 @@ Cache ox_symbol_cache = 0;
104
106
  Cache ox_class_cache = 0;
105
107
  Cache ox_attr_cache = 0;
106
108
 
109
+ static VALUE abort_sym;
110
+ static VALUE active_sym;
107
111
  static VALUE auto_define_sym;
108
112
  static VALUE auto_sym;
113
+ static VALUE block_sym;
109
114
  static VALUE circular_sym;
110
115
  static VALUE convert_special_sym;
111
116
  static VALUE effort_sym;
112
117
  static VALUE generic_sym;
118
+ static VALUE inactive_sym;
113
119
  static VALUE invalid_replace_sym;
114
120
  static VALUE limited_sym;
115
121
  static VALUE mode_sym;
116
122
  static VALUE object_sym;
123
+ static VALUE off_sym;
117
124
  static VALUE opt_format_sym;
118
125
  static VALUE optimized_sym;
126
+ static VALUE overlay_sym;
119
127
  static VALUE skip_none_sym;
120
128
  static VALUE skip_return_sym;
121
129
  static VALUE skip_sym;
@@ -161,6 +169,7 @@ struct _Options ox_default_options = {
161
169
  No, /* allow_invalid */
162
170
  { '\0' }, /* inv_repl */
163
171
  { '\0' }, /* strip_ns */
172
+ NULL, /* html_hints */
164
173
  #if HAS_PRIVATE_ENCODING
165
174
  Qnil /* rb_enc */
166
175
  #else
@@ -224,7 +233,28 @@ defuse_bom(char *xml, Options options) {
224
233
  return xml;
225
234
  }
226
235
 
227
- /* call-seq: ox_default_options() => Hash
236
+ static VALUE
237
+ hints_to_overlay(Hints hints) {
238
+ volatile VALUE overlay = rb_hash_new();
239
+ Hint h;
240
+ int i;
241
+ VALUE ov;
242
+
243
+ for (i = hints->size, h = hints->hints; 0 < i; i--, h++) {
244
+ switch (h->overlay) {
245
+ case InactiveOverlay: ov = inactive_sym; break;
246
+ case BlockOverlay: ov = block_sym; break;
247
+ case OffOverlay: ov = off_sym; break;
248
+ case AbortOverlay: ov = abort_sym; break;
249
+ case ActiveOverlay:
250
+ default: ov = active_sym; break;
251
+ }
252
+ rb_hash_aset(overlay, rb_str_new2(h->name), ov);
253
+ }
254
+ return overlay;
255
+ }
256
+
257
+ /* call-seq: default_options() => Hash
228
258
  *
229
259
  * Returns the default load and dump options as a Hash. The options are
230
260
  * - _:indent_ [Fixnum] number of spaces to indent each element in an XML document
@@ -243,6 +273,13 @@ defuse_bom(char *xml, Options options) {
243
273
  * - _:convert_special_ [true|false|nil] flag indicating special characters like &lt; are converted with the SAX parser
244
274
  * - _: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.
245
275
  * - _: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.
276
+ * - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
277
+ * - _:active_ - make the normal callback for the element
278
+ * - _:inactive_ - do not make the element start, end, or attribute callbacks for this element only
279
+ * - _:block_ - block this and all children callbacks
280
+ * - _:off_ - block this element and it's children unless the child element is active
281
+ * - _:abort_ - abort the html processing and return
282
+ *
246
283
  * *return* [Hash] all current option settings.
247
284
  *
248
285
  * Note that an indent of less than zero will result in a tight one line output
@@ -296,10 +333,54 @@ get_def_opts(VALUE self) {
296
333
  } else {
297
334
  rb_hash_aset(opts, strip_namespace_sym, rb_str_new(ox_default_options.strip_ns, strlen(ox_default_options.strip_ns)));
298
335
  }
336
+ if (NULL == ox_default_options.html_hints) {
337
+ //rb_hash_aset(opts, overlay_sym, hints_to_overlay(ox_hints_html()));
338
+ rb_hash_aset(opts, overlay_sym, Qnil);
339
+ } else {
340
+ rb_hash_aset(opts, overlay_sym, hints_to_overlay(ox_default_options.html_hints));
341
+ }
299
342
  return opts;
300
343
  }
301
344
 
302
- /* call-seq: ox_default_options=(opts)
345
+ static int
346
+ set_overlay(VALUE key, VALUE value, VALUE ctx) {
347
+ Hints hints = (Hints)ctx;
348
+ Hint hint;
349
+
350
+ if (NULL != (hint = ox_hint_find(hints, StringValuePtr(key)))) {
351
+ if (active_sym == value) {
352
+ hint->overlay = ActiveOverlay;
353
+ } else if (inactive_sym == value) {
354
+ hint->overlay = InactiveOverlay;
355
+ } else if (block_sym == value) {
356
+ hint->overlay = BlockOverlay;
357
+ } else if (off_sym == value) {
358
+ hint->overlay = OffOverlay;
359
+ } else if (abort_sym == value) {
360
+ hint->overlay = AbortOverlay;
361
+ }
362
+ }
363
+ return ST_CONTINUE;
364
+ }
365
+
366
+ /* call-seq: sax_html_overlay() => Hash
367
+ *
368
+ * Returns an overlay hash that can be modified and used as an overlay in the
369
+ * default options or in the sax_html() function call. Values for the keys are:
370
+ * - _:active_ - make the normal callback for the element
371
+ * - _:inactive_ - do not make the element start, end, or attribute callbacks for this element only
372
+ * - _:block_ - block this and all children callbacks
373
+ * - _:off_ - block this element and it's children unless the child element is active
374
+ * - _:abort_ - abort the html processing and return
375
+ *
376
+ * *return* [Hash] default SAX HTML settings
377
+ */
378
+ static VALUE
379
+ sax_html_overlay(VALUE self) {
380
+ return hints_to_overlay(ox_hints_html());
381
+ }
382
+
383
+ /* call-seq: default_options=(opts)
303
384
  *
304
385
  * Sets the default options for load and dump.
305
386
  * - +opts+ [Hash] opts options to change
@@ -314,9 +395,17 @@ get_def_opts(VALUE self) {
314
395
  * - _:mode_ [:object|:generic|:limited|nil] load method to use for XML
315
396
  * - _:effort_ [:strict|:tolerant|:auto_define] set the tolerance level for loading
316
397
  * - _:symbolize_keys_ [true|false|nil] symbolize element attribute keys or leave as Strings
317
- * - _skip_ [:skip_none|:skip_return|:skip_white] determines how to handle white space in text
398
+ * - _:skip_ [:skip_none|:skip_return|:skip_white] determines how to handle white space in text
399
+ * - _:smart_ [true|false|nil] flag indicating the SAX parser uses hints if available (use with html)
318
400
  * - _: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.
319
401
  * - _: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.
402
+ * - _:overlay_ [Hash] a Hash of keys that match html element names and values that are one of
403
+ * - _:active_ - make the normal callback for the element
404
+ * - _:inactive_ - do not make the element start, end, or attribute callbacks for this element only
405
+ * - _:block_ - block this and all children callbacks
406
+ * - _:off_ - block this element and it's children unless the child element is active
407
+ * - _:abort_ - abort the html processing and return
408
+ *
320
409
  * *return* [nil]
321
410
  */
322
411
  static VALUE
@@ -461,6 +550,24 @@ set_def_opts(VALUE self, VALUE opts) {
461
550
  rb_raise(ox_parse_error_class, "%s must be true or false.\n", rb_id2name(SYM2ID(o->sym)));
462
551
  }
463
552
  }
553
+ v = rb_hash_aref(opts, overlay_sym);
554
+ if (Qnil == v) {
555
+ ox_hints_destroy(ox_default_options.html_hints);
556
+ ox_default_options.html_hints = NULL;
557
+ } else {
558
+ int cnt;
559
+
560
+ Check_Type(v, T_HASH);
561
+ cnt = (int)RHASH_SIZE(v);
562
+ if (0 == cnt) {
563
+ ox_hints_destroy(ox_default_options.html_hints);
564
+ ox_default_options.html_hints = NULL;
565
+ } else {
566
+ ox_hints_destroy(ox_default_options.html_hints);
567
+ ox_default_options.html_hints = ox_hints_dup(ox_hints_html());
568
+ rb_hash_foreach(v, set_overlay, (VALUE)ox_default_options.html_hints);
569
+ }
570
+ }
464
571
  return Qnil;
465
572
  }
466
573
 
@@ -834,6 +941,7 @@ sax_parse(int argc, VALUE *argv, VALUE self) {
834
941
  options.convert_special = ox_default_options.convert_special;
835
942
  options.smart = (Yes == ox_default_options.smart);
836
943
  options.skip = ox_default_options.skip;
944
+ options.hints = NULL;
837
945
  strcpy(options.strip_ns, ox_default_options.strip_ns);
838
946
 
839
947
  if (argc < 2) {
@@ -886,6 +994,81 @@ sax_parse(int argc, VALUE *argv, VALUE self) {
886
994
  return Qnil;
887
995
  }
888
996
 
997
+ /* call-seq: sax_html(handler, io, options)
998
+ *
999
+ * Parses an IO stream or file containing an XML document. Raises an exception
1000
+ * if the XML is malformed or the classes specified are not valid.
1001
+ * - +handler+ [Ox::Sax] SAX (responds to OX::Sax methods) like handler
1002
+ * - +io+ [IO|String] IO Object to read from
1003
+ * - +options+ [Hash] options parse options
1004
+ * - *:convert_special* [true|false] flag indicating special characters like &lt; are converted
1005
+ * - *:symbolize* [true|false] flag indicating the parser symbolize element and attribute names
1006
+ * - *:skip* [:skip_return|:skip_white] flag indicating the parser skips \r or collapse white space into a single space. Default (skip nothing)
1007
+ * - *:overlay* [Hash] a Hash of keys that match html element names and values that are one of
1008
+ * - _:active_ - make the normal callback for the element
1009
+ * - _:inactive_ - do not make the element start, end, or attribute callbacks for this element only
1010
+ * - _:block_ - block this and all children callbacks
1011
+ * - _:off_ - block this element and it's children unless the child element is active
1012
+ * - _:abort_ - abort the html processing and return
1013
+ */
1014
+ static VALUE
1015
+ sax_html(int argc, VALUE *argv, VALUE self) {
1016
+ struct _SaxOptions options;
1017
+ bool free_hints = false;
1018
+
1019
+ options.symbolize = (No != ox_default_options.sym_keys);
1020
+ options.convert_special = ox_default_options.convert_special;
1021
+ options.smart = true;
1022
+ options.skip = ox_default_options.skip;
1023
+ options.hints = ox_default_options.html_hints;
1024
+ if (NULL == options.hints) {
1025
+ options.hints = ox_hints_html();
1026
+ }
1027
+ *options.strip_ns = '\0';
1028
+
1029
+ if (argc < 2) {
1030
+ rb_raise(ox_parse_error_class, "Wrong number of arguments to sax_html.\n");
1031
+ }
1032
+ if (3 <= argc && rb_cHash == rb_obj_class(argv[2])) {
1033
+ volatile VALUE h = argv[2];
1034
+ volatile VALUE v;
1035
+
1036
+ if (Qnil != (v = rb_hash_lookup(h, convert_special_sym))) {
1037
+ options.convert_special = (Qtrue == v);
1038
+ }
1039
+ if (Qnil != (v = rb_hash_lookup(h, symbolize_sym))) {
1040
+ options.symbolize = (Qtrue == v);
1041
+ }
1042
+ if (Qnil != (v = rb_hash_lookup(h, skip_sym))) {
1043
+ if (skip_return_sym == v) {
1044
+ options.skip = CrSkip;
1045
+ } else if (skip_white_sym == v) {
1046
+ options.skip = SpcSkip;
1047
+ } else if (skip_none_sym == v) {
1048
+ options.skip = NoSkip;
1049
+ }
1050
+ }
1051
+ if (Qnil != (v = rb_hash_lookup(h, overlay_sym))) {
1052
+ int cnt;
1053
+
1054
+ Check_Type(v, T_HASH);
1055
+ cnt = (int)RHASH_SIZE(v);
1056
+ if (0 == cnt) {
1057
+ options.hints = ox_hints_html();
1058
+ } else {
1059
+ options.hints = ox_hints_dup(options.hints);
1060
+ free_hints = true;
1061
+ rb_hash_foreach(v, set_overlay, (VALUE)options.hints);
1062
+ }
1063
+ }
1064
+ }
1065
+ ox_sax_parse(argv[0], argv[1], &options);
1066
+ if (free_hints) {
1067
+ ox_hints_destroy(options.hints);
1068
+ }
1069
+ return Qnil;
1070
+ }
1071
+
889
1072
  static void
890
1073
  parse_dump_options(VALUE ropts, Options copts) {
891
1074
  struct _YesNoOpt ynos[] = {
@@ -1065,6 +1248,7 @@ void Init_ox() {
1065
1248
  rb_define_module_function(Ox, "parse", to_gen, 1);
1066
1249
  rb_define_module_function(Ox, "load", load_str, -1);
1067
1250
  rb_define_module_function(Ox, "sax_parse", sax_parse, -1);
1251
+ rb_define_module_function(Ox, "sax_html", sax_html, -1);
1068
1252
 
1069
1253
  rb_define_module_function(Ox, "to_xml", dump, -1);
1070
1254
  rb_define_module_function(Ox, "dump", dump, -1);
@@ -1072,6 +1256,8 @@ void Init_ox() {
1072
1256
  rb_define_module_function(Ox, "load_file", load_file, -1);
1073
1257
  rb_define_module_function(Ox, "to_file", to_file, -1);
1074
1258
 
1259
+ rb_define_module_function(Ox, "sax_html_overlay", sax_html_overlay, 0);
1260
+
1075
1261
  ox_init_builder(Ox);
1076
1262
 
1077
1263
  rb_require("time");
@@ -1079,6 +1265,7 @@ void Init_ox() {
1079
1265
  rb_require("bigdecimal");
1080
1266
  rb_require("stringio");
1081
1267
 
1268
+ ox_abort_id = rb_intern("abort");
1082
1269
  ox_at_column_id = rb_intern("@column");
1083
1270
  ox_at_content_id = rb_intern("@content");
1084
1271
  ox_at_id = rb_intern("at");
@@ -1151,30 +1338,36 @@ void Init_ox() {
1151
1338
  ox_stringio_class = rb_const_get(rb_cObject, rb_intern("StringIO"));
1152
1339
  ox_bigdecimal_class = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
1153
1340
 
1341
+ abort_sym = ID2SYM(rb_intern("abort")); rb_gc_register_address(&abort_sym);
1342
+ active_sym = ID2SYM(rb_intern("active")); rb_gc_register_address(&active_sym);
1154
1343
  auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
1155
1344
  auto_sym = ID2SYM(rb_intern("auto")); rb_gc_register_address(&auto_sym);
1345
+ block_sym = ID2SYM(rb_intern("block")); rb_gc_register_address(&block_sym);
1156
1346
  circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
1157
1347
  convert_special_sym = ID2SYM(rb_intern("convert_special")); rb_gc_register_address(&convert_special_sym);
1158
1348
  effort_sym = ID2SYM(rb_intern("effort")); rb_gc_register_address(&effort_sym);
1159
1349
  generic_sym = ID2SYM(rb_intern("generic")); rb_gc_register_address(&generic_sym);
1160
- ox_indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&ox_indent_sym);
1161
- ox_size_sym = ID2SYM(rb_intern("size")); rb_gc_register_address(&ox_size_sym);
1350
+ inactive_sym = ID2SYM(rb_intern("inactive")); rb_gc_register_address(&inactive_sym);
1162
1351
  invalid_replace_sym = ID2SYM(rb_intern("invalid_replace")); rb_gc_register_address(&invalid_replace_sym);
1163
1352
  limited_sym = ID2SYM(rb_intern("limited")); rb_gc_register_address(&limited_sym);
1164
1353
  mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
1165
1354
  object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
1355
+ off_sym = ID2SYM(rb_intern("off")); rb_gc_register_address(&off_sym);
1166
1356
  opt_format_sym = ID2SYM(rb_intern("opt_format")); rb_gc_register_address(&opt_format_sym);
1167
1357
  optimized_sym = ID2SYM(rb_intern("optimized")); rb_gc_register_address(&optimized_sym);
1358
+ overlay_sym = ID2SYM(rb_intern("overlay")); rb_gc_register_address(&overlay_sym);
1168
1359
  ox_encoding_sym = ID2SYM(rb_intern("encoding")); rb_gc_register_address(&ox_encoding_sym);
1169
- ox_version_sym = ID2SYM(rb_intern("version")); rb_gc_register_address(&ox_version_sym);
1360
+ ox_indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&ox_indent_sym);
1361
+ ox_size_sym = ID2SYM(rb_intern("size")); rb_gc_register_address(&ox_size_sym);
1170
1362
  ox_standalone_sym = ID2SYM(rb_intern("standalone")); rb_gc_register_address(&ox_standalone_sym);
1363
+ ox_version_sym = ID2SYM(rb_intern("version")); rb_gc_register_address(&ox_version_sym);
1171
1364
  skip_none_sym = ID2SYM(rb_intern("skip_none")); rb_gc_register_address(&skip_none_sym);
1172
1365
  skip_return_sym = ID2SYM(rb_intern("skip_return")); rb_gc_register_address(&skip_return_sym);
1173
1366
  skip_sym = ID2SYM(rb_intern("skip")); rb_gc_register_address(&skip_sym);
1174
- strip_namespace_sym = ID2SYM(rb_intern("strip_namespace")); rb_gc_register_address(&strip_namespace_sym);
1175
1367
  skip_white_sym = ID2SYM(rb_intern("skip_white")); rb_gc_register_address(&skip_white_sym);
1176
1368
  smart_sym = ID2SYM(rb_intern("smart")); rb_gc_register_address(&smart_sym);
1177
1369
  strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
1370
+ strip_namespace_sym = ID2SYM(rb_intern("strip_namespace")); rb_gc_register_address(&strip_namespace_sym);
1178
1371
  symbolize_keys_sym = ID2SYM(rb_intern("symbolize_keys")); rb_gc_register_address(&symbolize_keys_sym);
1179
1372
  symbolize_sym = ID2SYM(rb_intern("symbolize")); rb_gc_register_address(&symbolize_sym);
1180
1373
  tolerant_sym = ID2SYM(rb_intern("tolerant")); rb_gc_register_address(&tolerant_sym);
@@ -119,29 +119,30 @@ typedef struct _CircArray {
119
119
  } *CircArray;
120
120
 
121
121
  typedef struct _Options {
122
- char encoding[64]; /* encoding, stored in the option to avoid GC invalidation in default values */
123
- int indent; /* indention for dump, default 2 */
124
- int trace; /* trace level */
125
- char with_dtd; /* YesNo */
126
- char with_xml; /* YesNo */
127
- char with_instruct; /* YesNo */
128
- char circular; /* YesNo */
129
- char xsd_date; /* YesNo */
130
- char mode; /* LoadMode */
131
- char effort; /* Effort */
132
- char sym_keys; /* symbolize keys */
133
- char skip; /* skip mode */
134
- char smart; /* YesNo sax smart mode */
135
- char convert_special;/* boolean true or false */
136
- char allow_invalid; /* YesNo */
137
- char inv_repl[12]; /* max 10 valid characters, first character is the length */
138
- char strip_ns[64]; /* namespace to strip, \0 is no-strip, \* is all, else only matches */
122
+ char encoding[64]; /* encoding, stored in the option to avoid GC invalidation in default values */
123
+ int indent; /* indention for dump, default 2 */
124
+ int trace; /* trace level */
125
+ char with_dtd; /* YesNo */
126
+ char with_xml; /* YesNo */
127
+ char with_instruct; /* YesNo */
128
+ char circular; /* YesNo */
129
+ char xsd_date; /* YesNo */
130
+ char mode; /* LoadMode */
131
+ char effort; /* Effort */
132
+ char sym_keys; /* symbolize keys */
133
+ char skip; /* skip mode */
134
+ char smart; /* YesNo sax smart mode */
135
+ char convert_special;/* boolean true or false */
136
+ char allow_invalid; /* YesNo */
137
+ char inv_repl[12]; /* max 10 valid characters, first character is the length */
138
+ char strip_ns[64]; /* namespace to strip, \0 is no-strip, \* is all, else only matches */
139
+ struct _Hints *html_hints; /* html hints */
139
140
  #if HAS_ENCODING_SUPPORT
140
- rb_encoding *rb_enc;
141
+ rb_encoding *rb_enc;
141
142
  #elif HAS_PRIVATE_ENCODING
142
- VALUE rb_enc;
143
+ VALUE rb_enc;
143
144
  #else
144
- void *rb_enc;
145
+ void *rb_enc;
145
146
  #endif
146
147
  } *Options;
147
148
 
@@ -171,6 +172,7 @@ extern struct _Options ox_default_options;
171
172
 
172
173
  extern VALUE Ox;
173
174
 
175
+ extern ID ox_abort_id;
174
176
  extern ID ox_at_column_id;
175
177
  extern ID ox_at_content_id;
176
178
  extern ID ox_at_id;