ox 2.14.16 → 2.14.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ba2060f84fb1cfb231c2dd8be4e8cf54e1533f7381f88ce45ab75ff18bb5ed5
4
- data.tar.gz: c3a4ef0949a291c44a1502ce21bdecd6d1a594f6b2260f37dd042e0f87fe676d
3
+ metadata.gz: 9b849217680d29abfe528da7bd89f0d5b2700f19a28dd09ed176a663f4cd35ab
4
+ data.tar.gz: 1a4690fc380ca55710b5ddf1d862503a1e6ef7cdfa9a5ebfb973c9c5b4ed6ea4
5
5
  SHA512:
6
- metadata.gz: c63630cec28f306285cc3126dca0feb2f997da02394519b7a8649bfb05d00604f4b54778dc07434acb202dfa575ca1cfab35f1cb5f9904c4939a7ce694f5d802
7
- data.tar.gz: 6f01842a610c01ae966bf897f79232cb17b46e6d3ea4c9b5c58996bd59ccd3f60a60626d4fdc76b4d5c78d1b79ceedf82ab7ea7cd2b3b9fa0802103a40ae9655
6
+ metadata.gz: 98b13052c1015400d8bbec0f79525562eb6e47e21826ca7c89b9197096ead85701211139be6562e5a72d411a47f75d0bb8c354b9ccc28e9c9eaf05ac897dc8ce
7
+ data.tar.gz: 94ea365ef3cd0a40e36d743b15b0d587748f0d26df8fcb1a9d660c431c6179011fc3531dc559bea95ea5f5b3594907b17f5f1369c0ac5f660ad657f21c286a04
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All changes to the Ox gem are documented here. Releases follow semantic versioning.
4
4
 
5
+ ## [2.14.17] - 2023-07-14
6
+
7
+ ### Fixed
8
+
9
+ - The sax parser in html mode now allows unquoted attribute values with complaints.
10
+
5
11
  ## [2.14.16] - 2023-04-11
6
12
 
7
13
  ### Fixed
data/ext/ox/builder.c CHANGED
@@ -337,21 +337,13 @@ static VALUE builder_new(int argc, VALUE *argv, VALUE self) {
337
337
 
338
338
  rb_check_type(*argv, T_HASH);
339
339
  if (Qnil != (v = rb_hash_lookup(*argv, ox_indent_sym))) {
340
- #ifdef RUBY_INTEGER_UNIFICATION
341
340
  if (rb_cInteger != rb_obj_class(v)) {
342
- #else
343
- if (rb_cFixnum != rb_obj_class(v)) {
344
- #endif
345
341
  rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
346
342
  }
347
343
  indent = NUM2INT(v);
348
344
  }
349
345
  if (Qnil != (v = rb_hash_lookup(*argv, ox_size_sym))) {
350
- #ifdef RUBY_INTEGER_UNIFICATION
351
346
  if (rb_cInteger != rb_obj_class(v)) {
352
- #else
353
- if (rb_cFixnum != rb_obj_class(v)) {
354
- #endif
355
347
  rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
356
348
  }
357
349
  buf_size = NUM2LONG(v);
@@ -400,21 +392,13 @@ static VALUE builder_file(int argc, VALUE *argv, VALUE self) {
400
392
 
401
393
  rb_check_type(argv[1], T_HASH);
402
394
  if (Qnil != (v = rb_hash_lookup(argv[1], ox_indent_sym))) {
403
- #ifdef RUBY_INTEGER_UNIFICATION
404
395
  if (rb_cInteger != rb_obj_class(v)) {
405
- #else
406
- if (rb_cFixnum != rb_obj_class(v)) {
407
- #endif
408
396
  rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
409
397
  }
410
398
  indent = NUM2INT(v);
411
399
  }
412
400
  if (Qnil != (v = rb_hash_lookup(argv[1], ox_size_sym))) {
413
- #ifdef RUBY_INTEGER_UNIFICATION
414
401
  if (rb_cInteger != rb_obj_class(v)) {
415
- #else
416
- if (rb_cFixnum != rb_obj_class(v)) {
417
- #endif
418
402
  rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
419
403
  }
420
404
  buf_size = NUM2LONG(v);
@@ -461,21 +445,13 @@ static VALUE builder_io(int argc, VALUE *argv, VALUE self) {
461
445
 
462
446
  rb_check_type(argv[1], T_HASH);
463
447
  if (Qnil != (v = rb_hash_lookup(argv[1], ox_indent_sym))) {
464
- #ifdef RUBY_INTEGER_UNIFICATION
465
448
  if (rb_cInteger != rb_obj_class(v)) {
466
- #else
467
- if (rb_cFixnum != rb_obj_class(v)) {
468
- #endif
469
449
  rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
470
450
  }
471
451
  indent = NUM2INT(v);
472
452
  }
473
453
  if (Qnil != (v = rb_hash_lookup(argv[1], ox_size_sym))) {
474
- #ifdef RUBY_INTEGER_UNIFICATION
475
454
  if (rb_cInteger != rb_obj_class(v)) {
476
- #else
477
- if (rb_cFixnum != rb_obj_class(v)) {
478
- #endif
479
455
  rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
480
456
  }
481
457
  buf_size = NUM2LONG(v);
@@ -732,9 +708,7 @@ static VALUE builder_text(int argc, VALUE *argv, VALUE self) {
732
708
  strip_invalid_chars = Qfalse;
733
709
  }
734
710
 
735
- if (T_STRING != rb_type(v)) {
736
- v = rb_funcall(v, ox_to_s_id, 0);
737
- }
711
+ v = rb_String(v);
738
712
  i_am_a_child(b, true);
739
713
  append_string(b, StringValuePtr(v), RSTRING_LEN(v), xml_element_chars, RTEST(strip_invalid_chars));
740
714
 
@@ -754,9 +728,7 @@ static VALUE builder_cdata(VALUE self, VALUE data) {
754
728
  const char *end;
755
729
  int len;
756
730
 
757
- if (T_STRING != rb_type(v)) {
758
- v = rb_funcall(v, ox_to_s_id, 0);
759
- }
731
+ v = rb_String(v);
760
732
  str = StringValuePtr(v);
761
733
  len = (int)RSTRING_LEN(v);
762
734
  s = str;
@@ -796,9 +768,7 @@ static VALUE builder_raw(VALUE self, VALUE text) {
796
768
  const char *end;
797
769
  int len;
798
770
 
799
- if (T_STRING != rb_type(v)) {
800
- v = rb_funcall(v, ox_to_s_id, 0);
801
- }
771
+ v = rb_String(v);
802
772
  str = StringValuePtr(v);
803
773
  len = (int)RSTRING_LEN(v);
804
774
  s = str;
@@ -857,11 +827,7 @@ static VALUE builder_get_indent(VALUE self) {
857
827
  * - +indent+ (Fixnum) indentaion level, negative values excludes terminating newline
858
828
  */
859
829
  static VALUE builder_set_indent(VALUE self, VALUE indent) {
860
- #ifdef RUBY_INTEGER_UNIFICATION
861
830
  if (rb_cInteger != rb_obj_class(indent)) {
862
- #else
863
- if (rb_cFixnum != rb_obj_class(indent)) {
864
- #endif
865
831
  rb_raise(ox_parse_error_class, "indent must be a fixnum.\n");
866
832
  }
867
833
 
data/ext/ox/dump.c CHANGED
@@ -159,12 +159,8 @@ static Type obj_class_code(VALUE obj) {
159
159
  case T_OBJECT: return (ox_document_clas == clas || ox_element_clas == clas) ? RawCode : ObjectCode;
160
160
  case T_REGEXP: return RegexpCode;
161
161
  case T_BIGNUM: return BignumCode;
162
- #ifdef T_COMPLEX
163
162
  case T_COMPLEX: return ComplexCode;
164
- #endif
165
- #ifdef T_RATIONAL
166
163
  case T_RATIONAL: return RationalCode;
167
- #endif
168
164
  case T_CLASS: return ClassCode;
169
165
  default: return 0;
170
166
  }
@@ -440,19 +436,13 @@ inline static void dump_num(Out out, VALUE obj) {
440
436
  }
441
437
 
442
438
  static void dump_time_thin(Out out, VALUE obj) {
443
- char buf[64];
444
- char *b = buf + sizeof(buf) - 1;
445
- #if HAVE_RB_TIME_TIMESPEC
439
+ char buf[64];
440
+ char *b = buf + sizeof(buf) - 1;
446
441
  struct timespec ts = rb_time_timespec(obj);
447
442
  time_t sec = ts.tv_sec;
448
443
  long nsec = ts.tv_nsec;
449
- #else
450
- time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
451
- long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
452
- // long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
453
- #endif
454
- char *dot = b - 10;
455
- long size;
444
+ char *dot = b - 10;
445
+ long size;
456
446
 
457
447
  *b-- = '\0';
458
448
  for (; dot < b; b--, nsec /= 10) {
@@ -495,18 +485,12 @@ static void dump_date(Out out, VALUE obj) {
495
485
  }
496
486
 
497
487
  static void dump_time_xsd(Out out, VALUE obj) {
498
- struct tm *tm;
499
- #if HAVE_RB_TIME_TIMESPEC
488
+ struct tm *tm;
500
489
  struct timespec ts = rb_time_timespec(obj);
501
490
  time_t sec = ts.tv_sec;
502
491
  long nsec = ts.tv_nsec;
503
- #else
504
- time_t sec = NUM2LONG(rb_funcall2(obj, ox_tv_sec_id, 0, 0));
505
- long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_nsec_id, 0, 0));
506
- // long nsec = NUM2LONG(rb_funcall2(obj, ox_tv_usec_id, 0, 0)) * 1000;
507
- #endif
508
- int tzhour, tzmin;
509
- char tzsign = '+';
492
+ int tzhour, tzmin;
493
+ char tzsign = '+';
510
494
 
511
495
  if (out->end - out->cur <= 33) {
512
496
  grow(out, 33);
@@ -777,7 +761,7 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
777
761
  e.indent = -1;
778
762
  out->w_end(out, &e);
779
763
  } else if (0 == strcmp("BigDecimal", classname)) {
780
- volatile VALUE rs = rb_funcall(obj, ox_to_s_id, 0);
764
+ volatile VALUE rs = rb_String(obj);
781
765
 
782
766
  e.type = BigDecimalCode;
783
767
  out->w_start(out, &e);
@@ -821,13 +805,8 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
821
805
  } else {
822
806
  char num_buf[16];
823
807
  int d2 = depth + 1;
824
- #ifdef RUBY_INTEGER_UNIFICATION
825
808
  long i;
826
- long cnt = NUM2LONG(rb_struct_size(obj));
827
- #else // UNIFY_FIXNUM_AND_INTEGER
828
- int i;
829
- int cnt = (int)RSTRUCT_LEN(obj);
830
- #endif // UNIFY_FIXNUM_AND_INTEGER
809
+ long cnt = NUM2LONG(rb_struct_size(obj));
831
810
  e.type = StructCode;
832
811
  e.clas.str = rb_class2name(clas);
833
812
  e.clas.len = strlen(e.clas.str);
@@ -866,7 +845,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
866
845
  dump_gen_element(obj, depth + 1, out);
867
846
  out->w_end(out, &e);
868
847
  } else { /* Object */
869
- #if HAVE_RB_IVAR_FOREACH
870
848
  e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
871
849
  cnt = (int)rb_ivar_count(obj);
872
850
  e.closed = (0 >= cnt);
@@ -879,29 +857,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
879
857
  out->depth = od;
880
858
  out->w_end(out, &e);
881
859
  }
882
- #else
883
- volatile VALUE vars = rb_obj_instance_variables(obj);
884
- // volatile VALUE vars = rb_funcall2(obj, rb_intern("instance_variables"), 0, 0);
885
-
886
- e.type = (Qtrue == rb_obj_is_kind_of(obj, rb_eException)) ? ExceptionCode : ObjectCode;
887
- cnt = (int)RARRAY_LEN(vars);
888
- e.closed = (0 >= cnt);
889
- out->w_start(out, &e);
890
- if (0 < cnt) {
891
- const VALUE *np = RARRAY_PTR(vars);
892
- ID vid;
893
- unsigned int od = out->depth;
894
- int i;
895
-
896
- out->depth = depth + 1;
897
- for (i = cnt; 0 < i; i--, np++) {
898
- vid = rb_to_id(*np);
899
- dump_var(vid, rb_ivar_get(obj, vid), out);
900
- }
901
- out->depth = od;
902
- out->w_end(out, &e);
903
- }
904
- #endif
905
860
  }
906
861
  break;
907
862
  }
@@ -940,7 +895,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
940
895
  out->w_end(out, &e);
941
896
  break;
942
897
  }
943
- #ifdef T_COMPLEX
944
898
  case T_COMPLEX: e.type = ComplexCode; out->w_start(out, &e);
945
899
  #ifdef RCOMPLEX
946
900
  dump_obj(0, RCOMPLEX(obj)->real, depth + 1, out);
@@ -951,8 +905,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
951
905
  #endif
952
906
  out->w_end(out, &e);
953
907
  break;
954
- #endif
955
- #ifdef T_RATIONAL
956
908
  case T_RATIONAL: e.type = RationalCode; out->w_start(out, &e);
957
909
  #ifdef RRATIONAL
958
910
  dump_obj(0, RRATIONAL(obj)->num, depth + 1, out);
@@ -963,7 +915,6 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out) {
963
915
  #endif
964
916
  out->w_end(out, &e);
965
917
  break;
966
- #endif
967
918
  case T_CLASS: {
968
919
  e.type = ClassCode;
969
920
  e.clas.str = rb_class2name(obj);
data/ext/ox/extconf.rb CHANGED
@@ -32,14 +32,9 @@ CONFIG['warnflags'].slice!(/ -Wsuggest-attribute=format/)
32
32
  CONFIG['warnflags'].slice!(/ -Wdeclaration-after-statement/)
33
33
  CONFIG['warnflags'].slice!(/ -Wmissing-noreturn/)
34
34
 
35
- have_func('rb_time_timespec')
36
- have_func('rb_struct_alloc_noinit')
37
- have_func('rb_obj_encoding')
38
- have_func('rb_ivar_foreach')
39
35
  have_func('rb_ext_ractor_safe', 'ruby.h')
40
36
  have_func('pthread_mutex_init')
41
37
  have_func('rb_enc_interned_str')
42
- have_func('rb_time_nano_new')
43
38
  have_func('index')
44
39
 
45
40
  have_header('ruby/st.h')
data/ext/ox/gen_load.c CHANGED
@@ -73,9 +73,7 @@ static void create_doc(PInfo pi) {
73
73
 
74
74
  helper_stack_init(&pi->helpers);
75
75
  doc = rb_obj_alloc(ox_document_clas);
76
- #ifdef RB_GC_GUARD
77
76
  RB_GC_GUARD(doc);
78
- #endif
79
77
  nodes = rb_ary_new();
80
78
  rb_ivar_set(doc, ox_attributes_id, rb_hash_new());
81
79
  rb_ivar_set(doc, ox_nodes_id, nodes);
@@ -104,7 +102,7 @@ static void create_prolog_doc(PInfo pi, const char *target, Attr attrs) {
104
102
  VALUE rstr = rb_str_new2(attrs->name);
105
103
 
106
104
  rb_enc_associate(rstr, pi->options->rb_enc);
107
- sym = rb_funcall(rstr, ox_to_sym_id, 0);
105
+ sym = rb_str_intern(rstr);
108
106
  } else {
109
107
  sym = ID2SYM(rb_intern(attrs->name));
110
108
  }
data/ext/ox/obj_load.c CHANGED
@@ -106,11 +106,7 @@ inline static VALUE structname2obj(const char *name) {
106
106
  }
107
107
  }
108
108
  ost = rb_const_get(ox_struct_class, rb_intern(s));
109
- #if HAVE_RB_STRUCT_ALLOC_NOINIT
110
109
  return rb_struct_alloc_noinit(ost);
111
- #else
112
- return rb_struct_new(ost);
113
- #endif
114
110
  }
115
111
 
116
112
  inline static VALUE parse_ulong(const char *s, PInfo pi) {
@@ -643,27 +639,21 @@ static void end_element(PInfo pi, const char *ename) {
643
639
  rb_hash_aset(gh->obj, ph->obj, h->obj);
644
640
  } break;
645
641
  case ComplexCode:
646
- #ifdef T_COMPLEX
647
642
  if (Qundef == ph->obj) {
648
643
  ph->obj = h->obj;
649
644
  } else {
650
645
  ph->obj = rb_complex_new(ph->obj, h->obj);
651
646
  }
652
- #else
653
- set_error(&pi->err, "Complex Objects not implemented in Ruby 1.8.7", pi->str, pi->s);
654
- return;
655
- #endif
656
647
  break;
657
648
  case RationalCode: {
658
649
  if (Qundef == h->obj || RUBY_T_FIXNUM != rb_type(h->obj)) {
659
650
  set_error(&pi->err, "Invalid object format", pi->str, pi->s);
660
651
  return;
661
652
  }
662
- #ifdef T_RATIONAL
663
653
  if (Qundef == ph->obj) {
664
654
  ph->obj = h->obj;
665
655
  } else {
666
- if (Qundef == ph->obj || RUBY_T_FIXNUM != rb_type(h->obj)) {
656
+ if (Qundef == ph->obj || RUBY_T_FIXNUM != rb_type(ph->obj)) {
667
657
  set_error(&pi->err, "Corrupt parse stack, container is wrong type", pi->str, pi->s);
668
658
  return;
669
659
  }
@@ -673,10 +663,6 @@ static void end_element(PInfo pi, const char *ename) {
673
663
  ph->obj = rb_rational_new(ph->obj, h->obj);
674
664
  #endif
675
665
  }
676
- #else
677
- set_error(&pi->err, "Rational Objects not implemented in Ruby 1.8.7", pi->str, pi->s);
678
- return;
679
- #endif
680
666
  break;
681
667
  }
682
668
  default:
@@ -719,11 +705,7 @@ static VALUE parse_double_time(const char *text, VALUE clas) {
719
705
  for (; text - dot <= 9; text++) {
720
706
  v2 *= 10;
721
707
  }
722
- #if HAVE_RB_TIME_NANO_NEW
723
708
  return rb_time_nano_new(v, v2);
724
- #else
725
- return rb_time_new(v, v2 / 1000);
726
- #endif
727
709
  }
728
710
 
729
711
  typedef struct _tp {
@@ -774,11 +756,7 @@ static VALUE parse_xsd_time(const char *text, VALUE clas) {
774
756
  tm.tm_hour = (int)cargs[3];
775
757
  tm.tm_min = (int)cargs[4];
776
758
  tm.tm_sec = (int)cargs[5];
777
- #if HAVE_RB_TIME_NANO_NEW
778
759
  return rb_time_nano_new(mktime(&tm), cargs[6]);
779
- #else
780
- return rb_time_new(mktime(&tm), cargs[6] / 1000);
781
- #endif
782
760
  }
783
761
 
784
762
  // debug functions
@@ -816,7 +794,7 @@ static void debug_stack(PInfo pi, const char *comment) {
816
794
  if (HashCode == h->type) {
817
795
  VALUE v;
818
796
 
819
- v = rb_funcall2(h->var, rb_intern("to_s"), 0, 0);
797
+ v = rb_String(h->var);
820
798
  key = StringValuePtr(v);
821
799
  } else if (ObjectCode == (h - 1)->type || ExceptionCode == (h - 1)->type ||
822
800
  RangeCode == (h - 1)->type || StructCode == (h - 1)->type) {
data/ext/ox/ox.c CHANGED
@@ -73,11 +73,6 @@ ID ox_start_element_id;
73
73
  ID ox_string_id;
74
74
  ID ox_text_id;
75
75
  ID ox_to_c_id;
76
- ID ox_to_s_id;
77
- ID ox_to_sym_id;
78
- ID ox_tv_nsec_id;
79
- ID ox_tv_sec_id;
80
- ID ox_tv_usec_id;
81
76
  ID ox_value_id;
82
77
 
83
78
  VALUE ox_encoding_sym;
@@ -687,17 +682,13 @@ static VALUE to_obj(VALUE self, VALUE ruby_xml) {
687
682
  xml = ALLOCA_N(char, len);
688
683
  }
689
684
  memcpy(xml, x, len);
690
- #ifdef RB_GC_GUARD
691
685
  rb_gc_disable();
692
- #endif
693
686
  obj = ox_parse(xml, len - 1, ox_obj_callbacks, 0, &options, &err);
694
687
  if (SMALL_XML < len) {
695
688
  xfree(xml);
696
689
  }
697
- #ifdef RB_GC_GUARD
698
690
  RB_GC_GUARD(obj);
699
691
  rb_gc_enable();
700
- #endif
701
692
  if (err_has(&err)) {
702
693
  ox_err_raise(&err);
703
694
  }
@@ -740,130 +731,123 @@ static VALUE to_gen(VALUE self, VALUE ruby_xml) {
740
731
  return obj;
741
732
  }
742
733
 
743
- static VALUE load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, Err err) {
744
- VALUE obj;
745
- struct _options options = ox_default_options;
746
-
747
- if (1 == argc && rb_cHash == rb_obj_class(*argv)) {
748
- VALUE h = *argv;
749
- VALUE v;
750
-
751
- if (Qnil != (v = rb_hash_lookup(h, mode_sym))) {
752
- if (object_sym == v) {
753
- options.mode = ObjMode;
754
- } else if (optimized_sym == v) {
755
- options.mode = ObjMode;
756
- } else if (generic_sym == v) {
757
- options.mode = GenMode;
758
- } else if (limited_sym == v) {
759
- options.mode = LimMode;
760
- } else if (hash_sym == v) {
761
- options.mode = HashMode;
762
- } else if (hash_no_attrs_sym == v) {
763
- options.mode = HashNoAttrMode;
764
- } else {
765
- rb_raise(ox_parse_error_class, ":mode must be :generic, :object, :limited, :hash, :hash_no_attrs.\n");
766
- }
767
- }
768
- if (Qnil != (v = rb_hash_lookup(h, effort_sym))) {
769
- if (auto_define_sym == v) {
770
- options.effort = AutoEffort;
771
- } else if (tolerant_sym == v) {
772
- options.effort = TolerantEffort;
773
- } else if (strict_sym == v) {
774
- options.effort = StrictEffort;
775
- } else {
776
- rb_raise(ox_parse_error_class, ":effort must be :strict, :tolerant, or :auto_define.\n");
777
- }
778
- }
779
- if (Qnil != (v = rb_hash_lookup(h, skip_sym))) {
780
- if (skip_none_sym == v) {
781
- options.skip = NoSkip;
782
- } else if (skip_off_sym == v) {
783
- options.skip = OffSkip;
784
- } else if (skip_return_sym == v) {
785
- options.skip = CrSkip;
786
- } else if (skip_white_sym == v) {
787
- options.skip = SpcSkip;
788
- } else {
789
- rb_raise(ox_parse_error_class, ":skip must be :skip_none, :skip_return, :skip_white, or :skip_off.\n");
790
- }
791
- }
792
-
793
- if (Qnil != (v = rb_hash_lookup(h, trace_sym))) {
794
- Check_Type(v, T_FIXNUM);
795
- options.trace = FIX2INT(v);
796
- }
797
- if (Qnil != (v = rb_hash_lookup(h, symbolize_keys_sym))) {
798
- options.sym_keys = (Qfalse == v) ? No : Yes;
734
+ static int load_options_cb(VALUE k, VALUE v, VALUE opts) {
735
+ Options copts = (Options)opts;
736
+
737
+ if (mode_sym == k) {
738
+ if (object_sym == v) {
739
+ copts->mode = ObjMode;
740
+ } else if (optimized_sym == v) {
741
+ copts->mode = ObjMode;
742
+ } else if (generic_sym == v) {
743
+ copts->mode = GenMode;
744
+ } else if (limited_sym == v) {
745
+ copts->mode = LimMode;
746
+ } else if (hash_sym == v) {
747
+ copts->mode = HashMode;
748
+ } else if (hash_no_attrs_sym == v) {
749
+ copts->mode = HashNoAttrMode;
750
+ } else {
751
+ rb_raise(ox_parse_error_class, ":mode must be :generic, :object, :limited, :hash, :hash_no_attrs.\n");
799
752
  }
800
- options.element_key_mod = rb_hash_lookup2(h, element_key_mod_sym, options.element_key_mod);
801
- options.attr_key_mod = rb_hash_lookup2(h, attr_key_mod_sym, options.attr_key_mod);
802
-
803
- if (Qnil != (v = rb_hash_lookup(h, convert_special_sym))) {
804
- options.convert_special = (Qfalse != v);
753
+ } else if (effort_sym == k) {
754
+ if (auto_define_sym == v) {
755
+ copts->effort = AutoEffort;
756
+ } else if (tolerant_sym == v) {
757
+ copts->effort = TolerantEffort;
758
+ } else if (strict_sym == v) {
759
+ copts->effort = StrictEffort;
760
+ } else {
761
+ rb_raise(ox_parse_error_class, ":effort must be :strict, :tolerant, or :auto_define.\n");
805
762
  }
806
- if (Qnil != (v = rb_hash_lookup(h, no_empty_sym))) {
807
- options.no_empty = (Qfalse != v);
763
+ } else if (skip_sym == k) {
764
+ if (skip_none_sym == v) {
765
+ copts->skip = NoSkip;
766
+ } else if (skip_off_sym == v) {
767
+ copts->skip = OffSkip;
768
+ } else if (skip_return_sym == v) {
769
+ copts->skip = CrSkip;
770
+ } else if (skip_white_sym == v) {
771
+ copts->skip = SpcSkip;
772
+ } else {
773
+ rb_raise(ox_parse_error_class, ":skip must be :skip_none, :skip_return, :skip_white, or :skip_off.\n");
808
774
  }
809
-
810
- v = rb_hash_lookup(h, invalid_replace_sym);
775
+ } else if (trace_sym == k) {
776
+ Check_Type(v, T_FIXNUM);
777
+ copts->trace = FIX2INT(v);
778
+ } else if (symbolize_keys_sym == k) {
779
+ copts->sym_keys = (Qfalse == v) ? No : Yes;
780
+ } else if (element_key_mod_sym == k) {
781
+ copts->element_key_mod = v;
782
+ } else if (attr_key_mod_sym == k) {
783
+ copts->attr_key_mod = v;
784
+ } else if (convert_special_sym == k) {
785
+ copts->convert_special = (Qfalse != v);
786
+ } else if (no_empty_sym == k) {
787
+ copts->no_empty = (Qfalse != v);
788
+ } else if (invalid_replace_sym == k) {
811
789
  if (Qnil == v) {
812
- if (Qtrue == rb_funcall(h, has_key_id, 1, invalid_replace_sym)) {
813
- options.allow_invalid = Yes;
814
- }
790
+ copts->allow_invalid = Yes;
815
791
  } else {
816
792
  long slen;
817
793
 
818
794
  Check_Type(v, T_STRING);
819
795
  slen = RSTRING_LEN(v);
820
- if (sizeof(options.inv_repl) - 2 < (size_t)slen) {
796
+ if (sizeof(copts->inv_repl) - 2 < (size_t)slen) {
821
797
  rb_raise(ox_parse_error_class,
822
798
  ":invalid_replace can be no longer than %d characters.",
823
- (int)sizeof(options.inv_repl) - 2);
799
+ (int)sizeof(copts->inv_repl) - 2);
824
800
  }
825
- strncpy(options.inv_repl + 1, StringValuePtr(v), sizeof(options.inv_repl) - 1);
826
- options.inv_repl[sizeof(options.inv_repl) - 1] = '\0';
827
- *options.inv_repl = (char)slen;
828
- options.allow_invalid = No;
801
+ strncpy(copts->inv_repl + 1, StringValuePtr(v), sizeof(copts->inv_repl) - 1);
802
+ copts->inv_repl[sizeof(copts->inv_repl) - 1] = '\0';
803
+ *copts->inv_repl = (char)slen;
804
+ copts->allow_invalid = No;
829
805
  }
830
- v = rb_hash_lookup(h, strip_namespace_sym);
806
+ } else if (strip_namespace_sym == k) {
831
807
  if (Qfalse == v) {
832
- *options.strip_ns = '\0';
808
+ *copts->strip_ns = '\0';
833
809
  } else if (Qtrue == v) {
834
- *options.strip_ns = '*';
835
- options.strip_ns[1] = '\0';
810
+ *copts->strip_ns = '*';
811
+ copts->strip_ns[1] = '\0';
836
812
  } else if (Qnil != v) {
837
813
  long slen;
838
814
 
839
815
  Check_Type(v, T_STRING);
840
816
  slen = RSTRING_LEN(v);
841
- if (sizeof(options.strip_ns) - 1 < (size_t)slen) {
817
+ if (sizeof(copts->strip_ns) - 1 < (size_t)slen) {
842
818
  rb_raise(ox_parse_error_class,
843
819
  ":strip_namespace can be no longer than %d characters.",
844
- (int)sizeof(options.strip_ns) - 1);
820
+ (int)sizeof(copts->strip_ns) - 1);
845
821
  }
846
- strncpy(options.strip_ns, StringValuePtr(v), sizeof(options.strip_ns) - 1);
847
- options.strip_ns[sizeof(options.strip_ns) - 1] = '\0';
822
+ strncpy(copts->strip_ns, StringValuePtr(v), sizeof(copts->strip_ns) - 1);
823
+ copts->strip_ns[sizeof(copts->strip_ns) - 1] = '\0';
848
824
  }
849
- v = rb_hash_lookup(h, margin_sym);
850
- if (Qnil != v) {
851
- long slen;
825
+ } else if (margin_sym == k) {
826
+ long slen;
852
827
 
853
- Check_Type(v, T_STRING);
854
- slen = RSTRING_LEN(v);
855
- if (sizeof(options.margin) - 1 < (size_t)slen) {
856
- rb_raise(ox_parse_error_class,
857
- ":margin can be no longer than %d characters.",
858
- (int)sizeof(options.margin) - 1);
859
- }
860
- strncpy(options.margin, StringValuePtr(v), sizeof(options.margin) - 1);
861
- options.margin[sizeof(options.margin) - 1] = '\0';
862
- options.margin_len = strlen(options.margin);
863
- }
864
- if (Qnil != (v = rb_hash_lookup(h, with_cdata_sym))) {
865
- options.with_cdata = (Qtrue == v);
828
+ Check_Type(v, T_STRING);
829
+ slen = RSTRING_LEN(v);
830
+ if (sizeof(copts->margin) - 1 < (size_t)slen) {
831
+ rb_raise(ox_parse_error_class,
832
+ ":margin can be no longer than %d characters.",
833
+ (int)sizeof(copts->margin) - 1);
866
834
  }
835
+ strncpy(copts->margin, StringValuePtr(v), sizeof(copts->margin) - 1);
836
+ copts->margin[sizeof(copts->margin) - 1] = '\0';
837
+ copts->margin_len = strlen(copts->margin);
838
+ } else if (with_cdata_sym == k) {
839
+ copts->with_cdata = (Qtrue == v);
840
+ }
841
+
842
+ return ST_CONTINUE;
843
+ }
844
+
845
+ static VALUE load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALUE encoding, Err err) {
846
+ VALUE obj;
847
+ struct _options options = ox_default_options;
848
+
849
+ if (1 == argc && rb_cHash == rb_obj_class(*argv)) {
850
+ rb_hash_foreach(*argv, load_options_cb, (VALUE)&options);
867
851
  }
868
852
  if ('\0' == *options.encoding) {
869
853
  if (Qnil != encoding) {
@@ -877,14 +861,10 @@ static VALUE load(char *xml, size_t len, int argc, VALUE *argv, VALUE self, VALU
877
861
  xml = defuse_bom(xml, &options);
878
862
  switch (options.mode) {
879
863
  case ObjMode:
880
- #ifdef RB_GC_GUARD
881
864
  rb_gc_disable();
882
- #endif
883
865
  obj = ox_parse(xml, len, ox_obj_callbacks, 0, &options, err);
884
- #ifdef RB_GC_GUARD
885
866
  RB_GC_GUARD(obj);
886
867
  rb_gc_enable();
887
- #endif
888
868
  break;
889
869
  case GenMode: obj = ox_parse(xml, len, ox_gen_callbacks, 0, &options, err); break;
890
870
  case LimMode: obj = ox_parse(xml, len, ox_limited_callbacks, 0, &options, err); break;
@@ -952,11 +932,7 @@ static VALUE load_str(int argc, VALUE *argv, VALUE self) {
952
932
  } else {
953
933
  xml = ALLOCA_N(char, len);
954
934
  }
955
- #if HAVE_RB_OBJ_ENCODING
956
935
  encoding = rb_obj_encoding(*argv);
957
- #else
958
- encoding = Qnil;
959
- #endif
960
936
  memcpy(xml, StringValuePtr(*argv), len);
961
937
  xml[len - 1] = '\0';
962
938
  obj = load(xml, len - 1, argc - 1, argv + 1, self, encoding, &err);
@@ -1201,21 +1177,13 @@ static void parse_dump_options(VALUE ropts, Options copts) {
1201
1177
  VALUE v;
1202
1178
 
1203
1179
  if (Qnil != (v = rb_hash_lookup(ropts, ox_indent_sym))) {
1204
- #ifdef RUBY_INTEGER_UNIFICATION
1205
1180
  if (rb_cInteger != rb_obj_class(v) && T_FIXNUM != rb_type(v)) {
1206
- #else
1207
- if (rb_cFixnum != rb_obj_class(v)) {
1208
- #endif
1209
1181
  rb_raise(ox_parse_error_class, ":indent must be a Fixnum.\n");
1210
1182
  }
1211
1183
  copts->indent = NUM2INT(v);
1212
1184
  }
1213
1185
  if (Qnil != (v = rb_hash_lookup(ropts, trace_sym))) {
1214
- #ifdef RUBY_INTEGER_UNIFICATION
1215
1186
  if (rb_cInteger != rb_obj_class(v) && T_FIXNUM != rb_type(v)) {
1216
- #else
1217
- if (rb_cFixnum != rb_obj_class(v)) {
1218
- #endif
1219
1187
  rb_raise(ox_parse_error_class, ":trace must be a Fixnum.\n");
1220
1188
  }
1221
1189
  copts->trace = NUM2INT(v);
@@ -1469,11 +1437,6 @@ void Init_ox() {
1469
1437
  ox_string_id = rb_intern("string");
1470
1438
  ox_text_id = rb_intern("text");
1471
1439
  ox_to_c_id = rb_intern("to_c");
1472
- ox_to_s_id = rb_intern("to_s");
1473
- ox_to_sym_id = rb_intern("to_sym");
1474
- ox_tv_nsec_id = rb_intern("tv_nsec");
1475
- ox_tv_sec_id = rb_intern("tv_sec");
1476
- ox_tv_usec_id = rb_intern("tv_usec");
1477
1440
  ox_value_id = rb_intern("value");
1478
1441
 
1479
1442
  encoding_id = rb_intern("encoding");
@@ -1675,8 +1638,6 @@ _ox_raise_error(const char *msg, const char *xml, const char *current, const cha
1675
1638
  xline++;
1676
1639
  }
1677
1640
  }
1678
- #ifdef RB_GC_GUARD
1679
1641
  rb_gc_enable();
1680
- #endif
1681
1642
  rb_raise(ox_parse_error_class, "%s at line %d, column %d [%s:%d]\n", msg, xline, col, file, line);
1682
1643
  }
data/ext/ox/ox.h CHANGED
@@ -205,11 +205,6 @@ extern ID ox_start_element_id;
205
205
  extern ID ox_string_id;
206
206
  extern ID ox_text_id;
207
207
  extern ID ox_to_c_id;
208
- extern ID ox_to_s_id;
209
- extern ID ox_to_sym_id;
210
- extern ID ox_tv_sec_id;
211
- extern ID ox_tv_nsec_id;
212
- extern ID ox_tv_usec_id;
213
208
  extern ID ox_value_id;
214
209
 
215
210
  extern rb_encoding *ox_utf8_encoding;
data/ext/ox/sax.c CHANGED
@@ -55,7 +55,7 @@ static char read_text(SaxDrive dr);
55
55
  static char read_jump(SaxDrive dr, const char *pat);
56
56
  static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req, Hint h);
57
57
  static char read_name_token(SaxDrive dr);
58
- static char read_quoted_value(SaxDrive dr);
58
+ static char read_quoted_value(SaxDrive dr, bool inst);
59
59
 
60
60
  static void hint_clear_empty(SaxDrive dr);
61
61
  static Nv hint_try_close(SaxDrive dr, const char *name);
@@ -469,7 +469,7 @@ DONE:
469
469
  Nv sp;
470
470
 
471
471
  for (sp = dr->stack.tail - 1; dr->stack.head <= sp; sp--) {
472
- snprintf(msg, sizeof(msg) - 1, "%selement '%s' not closed", EL_MISMATCH, sp->name);
472
+ snprintf(msg, sizeof(msg) - 1, "%selement '%s' not closed", EL_MISMATCH, nv_name(sp));
473
473
  ox_sax_drive_error_at(dr, msg, dr->buf.pos, dr->buf.line, dr->buf.col);
474
474
  end_element_cb(dr, sp->val, dr->buf.pos, dr->buf.line, dr->buf.col, sp->hint);
475
475
  }
@@ -1219,6 +1219,7 @@ static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml,
1219
1219
  c = buf_next_non_white(&dr->buf);
1220
1220
  }
1221
1221
  if ('=' != c) {
1222
+ // TBD allow in smart mode
1222
1223
  if (eq_req) {
1223
1224
  dr->err = 1;
1224
1225
  return c;
@@ -1230,7 +1231,7 @@ static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml,
1230
1231
  pos = dr->buf.pos + 1;
1231
1232
  line = dr->buf.line;
1232
1233
  col = dr->buf.col + 1;
1233
- c = read_quoted_value(dr);
1234
+ c = read_quoted_value(dr, '?' == termc);
1234
1235
  attr_value = dr->buf.str;
1235
1236
 
1236
1237
  if (is_encoding) {
@@ -1297,10 +1298,11 @@ static char read_name_token(SaxDrive dr) {
1297
1298
  return '\0';
1298
1299
  }
1299
1300
 
1300
- /* The character after the quote or if there is no quote, the character after the word is returned. dr->buf.tail is one
1301
- * past that. dr->buf.str will point to the token which will be '\0' terminated.
1301
+ /* The character after the quote or if there is no quote, the character after
1302
+ * the word is returned. dr->buf.tail is one past that. dr->buf.str will point
1303
+ * to the token which will be '\0' terminated.
1302
1304
  */
1303
- static char read_quoted_value(SaxDrive dr) {
1305
+ static char read_quoted_value(SaxDrive dr, bool inst) {
1304
1306
  char c;
1305
1307
 
1306
1308
  c = buf_get(&dr->buf);
@@ -1324,19 +1326,27 @@ static char read_quoted_value(SaxDrive dr) {
1324
1326
  }
1325
1327
  // not quoted, look for something that terminates the string
1326
1328
  dr->buf.str = dr->buf.tail - 1;
1327
- ox_sax_drive_error(dr, WRONG_CHAR "attribute value not in quotes");
1329
+ // TBD if smart or html then no error
1330
+ if (!(dr->options.smart && ox_hints_html() != dr->options.hints)) {
1331
+ ox_sax_drive_error(dr, WRONG_CHAR "attribute value not in quotes");
1332
+ }
1328
1333
  while ('\0' != (c = buf_get(&dr->buf))) {
1329
1334
  switch (c) {
1330
1335
  case ' ':
1331
1336
  // case '/':
1332
1337
  case '>':
1333
- case '?': // for instructions
1334
1338
  case '\t':
1335
1339
  case '\n':
1336
1340
  case '\r':
1337
1341
  *(dr->buf.tail - 1) = '\0'; /* terminate value */
1338
1342
  // dr->buf.tail is in the correct position, one after the word terminator
1339
1343
  return c;
1344
+ case '?': // for instructions
1345
+ if (inst) {
1346
+ *(dr->buf.tail - 1) = '\0'; /* terminate value */
1347
+ return c;
1348
+ }
1349
+ break;
1340
1350
  default: break;
1341
1351
  }
1342
1352
  }
data/ext/ox/sax_as.c CHANGED
@@ -43,11 +43,7 @@ static VALUE parse_double_time(const char *text) {
43
43
  for (; text - dot <= 9; text++) {
44
44
  v2 *= 10;
45
45
  }
46
- #if HAVE_RB_TIME_NANO_NEW
47
46
  return rb_time_nano_new(v, v2);
48
- #else
49
- return rb_time_new(v, v2 / 1000);
50
- #endif
51
47
  }
52
48
 
53
49
  typedef struct _tp {
@@ -102,11 +98,7 @@ static VALUE parse_xsd_time(const char *text) {
102
98
  tm.tm_hour = (int)cargs[3];
103
99
  tm.tm_min = (int)cargs[4];
104
100
  tm.tm_sec = (int)cargs[5];
105
- #if HAVE_RB_TIME_NANO_NEW
106
101
  return rb_time_nano_new(mktime(&tm), cargs[6]);
107
- #else
108
- return rb_time_new(mktime(&tm), cargs[6] / 1000);
109
- #endif
110
102
  }
111
103
 
112
104
  /* call-seq: as_s()
data/ext/ox/slotcache.c CHANGED
@@ -145,7 +145,7 @@ static void slot_print(SlotCache c, unsigned int depth) {
145
145
  vs = "undefined";
146
146
  clas = "";
147
147
  } else {
148
- VALUE rs = rb_funcall2((*cp)->value, rb_intern("to_s"), 0, 0);
148
+ VALUE rs = rb_String((*cp)->value);
149
149
 
150
150
  vs = StringValuePtr(rs);
151
151
  clas = rb_class2name(rb_obj_class((*cp)->value));
data/lib/ox/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Ox
2
2
  # Current version of the module.
3
- VERSION = '2.14.16'
3
+ VERSION = '2.14.17'
4
4
  end
@@ -12,6 +12,7 @@ module Ox
12
12
  class StreamParser < XMLRPC::XMLParser::AbstractStreamParser
13
13
  # Create a new instance.
14
14
  def initialize
15
+ super
15
16
  @parser_class = OxParser
16
17
  end
17
18
 
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ox
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.14.16
4
+ version: 2.14.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-12 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
13
33
  description: "A fast XML parser and object serializer that uses only standard C lib.\n\nOptimized
14
34
  XML (Ox), as the name implies was written to provide speed optimized\nXML handling.
15
35
  It was designed to be an alternative to Nokogiri and other Ruby\nXML parsers for