ox 2.14.18 → 2.14.19

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: fd178b1fd415d3a97ef3b60e73896d52fd3eea1e9ef7a32dd0de316e00a21542
4
- data.tar.gz: f9813bab8a071e6ba9efa07a92c228d3ea783a29503cfc763e72e73220899fe8
3
+ metadata.gz: 8f79925bdad366a8453ecda24602c7372371b5ac90363def31f7a21c5f46e85a
4
+ data.tar.gz: 1d88152e72cd654b215592b9874f6cf4c018853fcbfe3a5e3a37aa4f15a7d0f1
5
5
  SHA512:
6
- metadata.gz: 1a7cfc1bfbe0693f52f66f662d4f0f8eeabe20bc50ddefb854abde16e1f1e1c8236b64a2c1ebd51d6de18a697f588ff4d60f854e7b50b383db14ad6eed57ae92
7
- data.tar.gz: ae9344f3607e94721eafda29f7255be6a36a0340dd4de3b03d249e616126ec340f5c9485f855ba342f33c951d7153c1b47e0b95aaada4e1936741f2b6755452c
6
+ metadata.gz: ed6c242bf2a70049e9af314614fc9c47f51fb4740a1fdb4785fa693d1c93586bf10b4a1c73ba60e6e88c39c6b6b6d283b324ffbd27cac51e915a1fc48c69b5a0
7
+ data.tar.gz: 8c0d35c215e6720fff4c82cb711f9f9991b6dfcd91c4ec1c74ac656c52ef1cb74fcc93a4171fbbe28b09aee0ceefe8c50173d20af4935321207db93f45009b18
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All changes to the Ox gem are documented here. Releases follow semantic versioning.
4
4
 
5
+ ## [2.14.19] - 2024-12-25
6
+
7
+ ### Fixed
8
+
9
+ - Code cleanup in sax.c to close issue #363.
10
+
11
+ - Updated the dump options documentation to `:with_xml` option to resolve #352.
12
+
13
+ - Updated the sax tests to pass to resolve #335.
14
+
15
+ - Element#replace_text on nil `@nodes` no longer fails. Closes #364.
16
+
5
17
  ## [2.14.18] - 2024-03-21
6
18
 
7
19
  ### Fixed
data/ext/ox/builder.c CHANGED
@@ -17,6 +17,19 @@
17
17
 
18
18
  #define MAX_DEPTH 128
19
19
 
20
+ static void builder_free(void *ptr);
21
+
22
+ static const rb_data_type_t ox_builder_type = {
23
+ "Ox/builder",
24
+ {
25
+ NULL,
26
+ builder_free,
27
+ NULL,
28
+ },
29
+ 0,
30
+ 0,
31
+ };
32
+
20
33
  typedef struct _element {
21
34
  char *name;
22
35
  char buf[64];
@@ -353,14 +366,14 @@ static VALUE builder_new(int argc, VALUE *argv, VALUE self) {
353
366
  init(b, 0, indent, buf_size);
354
367
 
355
368
  if (rb_block_given_p()) {
356
- volatile VALUE rb = Data_Wrap_Struct(builder_class, NULL, builder_free, b);
369
+ volatile VALUE rb = TypedData_Wrap_Struct(builder_class, &ox_builder_type, b);
357
370
 
358
371
  rb_yield(rb);
359
372
  bclose(b);
360
373
 
361
374
  return to_s(b);
362
375
  } else {
363
- return Data_Wrap_Struct(builder_class, NULL, builder_free, b);
376
+ return TypedData_Wrap_Struct(builder_class, &ox_builder_type, b);
364
377
  }
365
378
  }
366
379
 
@@ -408,12 +421,12 @@ static VALUE builder_file(int argc, VALUE *argv, VALUE self) {
408
421
  init(b, fileno(f), indent, buf_size);
409
422
 
410
423
  if (rb_block_given_p()) {
411
- volatile VALUE rb = Data_Wrap_Struct(builder_class, NULL, builder_free, b);
424
+ volatile VALUE rb = TypedData_Wrap_Struct(builder_class, &ox_builder_type, b);
412
425
  rb_yield(rb);
413
426
  bclose(b);
414
427
  return Qnil;
415
428
  } else {
416
- return Data_Wrap_Struct(builder_class, NULL, builder_free, b);
429
+ return TypedData_Wrap_Struct(builder_class, &ox_builder_type, b);
417
430
  }
418
431
  }
419
432
 
@@ -461,12 +474,12 @@ static VALUE builder_io(int argc, VALUE *argv, VALUE self) {
461
474
  init(b, fd, indent, buf_size);
462
475
 
463
476
  if (rb_block_given_p()) {
464
- volatile VALUE rb = Data_Wrap_Struct(builder_class, NULL, builder_free, b);
477
+ volatile VALUE rb = TypedData_Wrap_Struct(builder_class, &ox_builder_type, b);
465
478
  rb_yield(rb);
466
479
  bclose(b);
467
480
  return Qnil;
468
481
  } else {
469
- return Data_Wrap_Struct(builder_class, NULL, builder_free, b);
482
+ return TypedData_Wrap_Struct(builder_class, &ox_builder_type, b);
470
483
  }
471
484
  }
472
485
 
@@ -478,8 +491,9 @@ static VALUE builder_io(int argc, VALUE *argv, VALUE self) {
478
491
  * - +options+ - (Hash) version or encoding
479
492
  */
480
493
  static VALUE builder_instruct(int argc, VALUE *argv, VALUE self) {
481
- Builder b = (Builder)DATA_PTR(self);
494
+ Builder b;
482
495
 
496
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
483
497
  i_am_a_child(b, false);
484
498
  append_indent(b);
485
499
  if (0 == argc) {
@@ -548,11 +562,13 @@ static VALUE builder_instruct(int argc, VALUE *argv, VALUE self) {
548
562
  * - +attributes+ - (Hash) of the element
549
563
  */
550
564
  static VALUE builder_element(int argc, VALUE *argv, VALUE self) {
551
- Builder b = (Builder)DATA_PTR(self);
565
+ Builder b;
552
566
  Element e;
553
567
  const char *name;
554
568
  long len;
555
569
 
570
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
571
+
556
572
  if (1 > argc) {
557
573
  rb_raise(ox_arg_error_class, "missing element name");
558
574
  }
@@ -608,10 +624,12 @@ static VALUE builder_element(int argc, VALUE *argv, VALUE self) {
608
624
  * - +attributes+ - (Hash) of the element
609
625
  */
610
626
  static VALUE builder_void_element(int argc, VALUE *argv, VALUE self) {
611
- Builder b = (Builder)DATA_PTR(self);
627
+ Builder b;
612
628
  const char *name;
613
629
  long len;
614
630
 
631
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
632
+
615
633
  if (1 > argc) {
616
634
  rb_raise(ox_arg_error_class, "missing element name");
617
635
  }
@@ -649,8 +667,9 @@ static VALUE builder_void_element(int argc, VALUE *argv, VALUE self) {
649
667
  * - +text+ - (String) contents of the comment
650
668
  */
651
669
  static VALUE builder_comment(VALUE self, VALUE text) {
652
- Builder b = (Builder)DATA_PTR(self);
670
+ Builder b;
653
671
 
672
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
654
673
  rb_check_type(text, T_STRING);
655
674
  i_am_a_child(b, false);
656
675
  append_indent(b);
@@ -671,8 +690,9 @@ static VALUE builder_comment(VALUE self, VALUE text) {
671
690
  * - +text+ - (String) contents of the doctype
672
691
  */
673
692
  static VALUE builder_doctype(VALUE self, VALUE text) {
674
- Builder b = (Builder)DATA_PTR(self);
693
+ Builder b;
675
694
 
695
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
676
696
  rb_check_type(text, T_STRING);
677
697
  i_am_a_child(b, false);
678
698
  append_indent(b);
@@ -694,10 +714,12 @@ static VALUE builder_doctype(VALUE self, VALUE text) {
694
714
  * - +strip_invalid_chars+ - [true|false] strips any characters invalid for XML, defaults to false
695
715
  */
696
716
  static VALUE builder_text(int argc, VALUE *argv, VALUE self) {
697
- Builder b = (Builder)DATA_PTR(self);
717
+ Builder b;
698
718
  volatile VALUE v;
699
719
  volatile VALUE strip_invalid_chars;
700
720
 
721
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
722
+
701
723
  if ((0 == argc) || (argc > 2)) {
702
724
  rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1..2)", argc);
703
725
  }
@@ -721,13 +743,15 @@ static VALUE builder_text(int argc, VALUE *argv, VALUE self) {
721
743
  * - +data+ - (String) contents of the CDATA element
722
744
  */
723
745
  static VALUE builder_cdata(VALUE self, VALUE data) {
724
- Builder b = (Builder)DATA_PTR(self);
746
+ Builder b;
725
747
  volatile VALUE v = data;
726
748
  const char *str;
727
749
  const char *s;
728
750
  const char *end;
729
751
  int len;
730
752
 
753
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
754
+
731
755
  v = rb_String(v);
732
756
  str = StringValuePtr(v);
733
757
  len = (int)RSTRING_LEN(v);
@@ -761,13 +785,14 @@ static VALUE builder_cdata(VALUE self, VALUE data) {
761
785
  * - +text+ - (String) contents to be added
762
786
  */
763
787
  static VALUE builder_raw(VALUE self, VALUE text) {
764
- Builder b = (Builder)DATA_PTR(self);
788
+ Builder b;
765
789
  volatile VALUE v = text;
766
790
  const char *str;
767
791
  const char *s;
768
792
  const char *end;
769
793
  int len;
770
794
 
795
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
771
796
  v = rb_String(v);
772
797
  str = StringValuePtr(v);
773
798
  len = (int)RSTRING_LEN(v);
@@ -792,7 +817,10 @@ static VALUE builder_raw(VALUE self, VALUE text) {
792
817
  * Returns the JSON document string in what ever state the construction is at.
793
818
  */
794
819
  static VALUE builder_to_s(VALUE self) {
795
- return to_s((Builder)DATA_PTR(self));
820
+ Builder b;
821
+
822
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
823
+ return to_s(b);
796
824
  }
797
825
 
798
826
  /* call-seq: line()
@@ -800,7 +828,10 @@ static VALUE builder_to_s(VALUE self) {
800
828
  * Returns the current line in the output. The first line is line 1.
801
829
  */
802
830
  static VALUE builder_line(VALUE self) {
803
- return LONG2NUM(((Builder)DATA_PTR(self))->line);
831
+ Builder b;
832
+
833
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
834
+ return LONG2NUM(b->line);
804
835
  }
805
836
 
806
837
  /* call-seq: column()
@@ -809,7 +840,10 @@ static VALUE builder_line(VALUE self) {
809
840
  * column 1.
810
841
  */
811
842
  static VALUE builder_column(VALUE self) {
812
- return LONG2NUM(((Builder)DATA_PTR(self))->col);
843
+ Builder b;
844
+
845
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
846
+ return LONG2NUM(b->col);
813
847
  }
814
848
 
815
849
  /* call-seq: indent()
@@ -817,7 +851,10 @@ static VALUE builder_column(VALUE self) {
817
851
  * Returns the indentation level
818
852
  */
819
853
  static VALUE builder_get_indent(VALUE self) {
820
- return INT2NUM(((Builder)DATA_PTR(self))->indent);
854
+ Builder b;
855
+
856
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
857
+ return INT2NUM(b->indent);
821
858
  }
822
859
 
823
860
  /* call-seq: indent=(indent)
@@ -827,11 +864,15 @@ static VALUE builder_get_indent(VALUE self) {
827
864
  * - +indent+ (Fixnum) indentaion level, negative values excludes terminating newline
828
865
  */
829
866
  static VALUE builder_set_indent(VALUE self, VALUE indent) {
867
+ Builder b;
868
+
869
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
870
+
830
871
  if (rb_cInteger != rb_obj_class(indent)) {
831
872
  rb_raise(ox_parse_error_class, "indent must be a fixnum.\n");
832
873
  }
833
874
 
834
- ((Builder)DATA_PTR(self))->indent = NUM2INT(indent);
875
+ b->indent = NUM2INT(indent);
835
876
  return Qnil;
836
877
  }
837
878
 
@@ -840,7 +881,10 @@ static VALUE builder_set_indent(VALUE self, VALUE indent) {
840
881
  * Returns the number of bytes written.
841
882
  */
842
883
  static VALUE builder_pos(VALUE self) {
843
- return LONG2NUM(((Builder)DATA_PTR(self))->pos);
884
+ Builder b;
885
+
886
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
887
+ return LONG2NUM(b->pos);
844
888
  }
845
889
 
846
890
  /* call-seq: pop()
@@ -848,7 +892,9 @@ static VALUE builder_pos(VALUE self) {
848
892
  * Closes the current element.
849
893
  */
850
894
  static VALUE builder_pop(VALUE self) {
851
- pop((Builder)DATA_PTR(self));
895
+ Builder b;
896
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
897
+ pop(b);
852
898
 
853
899
  return Qnil;
854
900
  }
@@ -858,7 +904,10 @@ static VALUE builder_pop(VALUE self) {
858
904
  * Closes the all elements and the document.
859
905
  */
860
906
  static VALUE builder_close(VALUE self) {
861
- bclose((Builder)DATA_PTR(self));
907
+ Builder b;
908
+
909
+ TypedData_Get_Struct(self, struct _builder, &ox_builder_type, b);
910
+ bclose(b);
862
911
 
863
912
  return Qnil;
864
913
  }
data/ext/ox/cache.c CHANGED
@@ -54,6 +54,17 @@ typedef struct _cache {
54
54
  bool mark;
55
55
  } *Cache;
56
56
 
57
+ const rb_data_type_t ox_cache_type = {
58
+ "Ox/Cache",
59
+ {
60
+ ox_cache_mark,
61
+ ox_cache_free,
62
+ NULL,
63
+ },
64
+ 0,
65
+ 0,
66
+ };
67
+
57
68
  static uint64_t hash_calc(const uint8_t *key, size_t len) {
58
69
  const uint8_t *end = key + len;
59
70
  const uint8_t *endless = key + (len & 0xFFFFFFFC);
@@ -263,7 +274,8 @@ Cache ox_cache_create(size_t size, VALUE (*form)(const char *str, size_t len), b
263
274
  return c;
264
275
  }
265
276
 
266
- void ox_cache_free(Cache c) {
277
+ void ox_cache_free(void *ptr) {
278
+ Cache c = (Cache)ptr;
267
279
  uint64_t i;
268
280
 
269
281
  for (i = 0; i < c->size; i++) {
@@ -279,7 +291,8 @@ void ox_cache_free(Cache c) {
279
291
  free(c);
280
292
  }
281
293
 
282
- void ox_cache_mark(Cache c) {
294
+ void ox_cache_mark(void *ptr) {
295
+ Cache c = (Cache)ptr;
283
296
  uint64_t i;
284
297
 
285
298
  #if !HAVE_PTHREAD_MUTEX_INIT
data/ext/ox/cache.h CHANGED
@@ -11,9 +11,11 @@
11
11
 
12
12
  struct _cache;
13
13
 
14
+ extern const rb_data_type_t ox_cache_type;
15
+
14
16
  extern struct _cache *ox_cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool mark, bool locking);
15
- extern void ox_cache_free(struct _cache *c);
16
- extern void ox_cache_mark(struct _cache *c);
17
+ extern void ox_cache_free(void *ptr);
18
+ extern void ox_cache_mark(void *ptr);
17
19
  extern VALUE ox_cache_intern(struct _cache *c, const char *key, size_t len, const char **keyp);
18
20
 
19
21
  #endif /* OX_CACHE_H */
data/ext/ox/foo.h ADDED
@@ -0,0 +1,204 @@
1
+ /* sax_buf.h
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #ifndef OX_SAX_BUF_H
7
+ #define OX_SAX_BUF_H
8
+
9
+ #include <stdio.h>
10
+
11
+ typedef struct _buf {
12
+ char base[0x00001000];
13
+ char *head;
14
+ char *end;
15
+ char *tail;
16
+ char *read_end; /* one past last character read */
17
+ char *pro; /* protection start, buffer can not slide past this point */
18
+ char *str; /* start of current string being read */
19
+ off_t pos;
20
+ off_t line;
21
+ off_t col;
22
+ off_t pro_pos;
23
+ off_t pro_line;
24
+ off_t pro_col;
25
+ int (*read_func)(struct _buf *buf);
26
+ union {
27
+ int fd;
28
+ VALUE io;
29
+ const char *str;
30
+ } in;
31
+ struct _saxDrive *dr;
32
+ } *Buf;
33
+
34
+ typedef struct _checkPt {
35
+ off_t pro_dif;
36
+ off_t pos;
37
+ off_t line;
38
+ off_t col;
39
+ char c;
40
+ } *CheckPt;
41
+
42
+ #define CHECK_PT_INIT {-1, 0, 0, 0, '\0'}
43
+
44
+ extern void ox_sax_buf_init(Buf buf, VALUE io);
45
+ extern int ox_sax_buf_read(Buf buf);
46
+
47
+ static inline char buf_get(Buf buf) {
48
+ // printf("*** drive get from '%s' from start: %ld buf: %p from read_end: %ld\n", buf->tail, buf->tail -
49
+ // buf->head, buf->head, buf->read_end - buf->tail);
50
+ if (buf->read_end <= buf->tail) {
51
+ if (0 != ox_sax_buf_read(buf)) {
52
+ return '\0';
53
+ }
54
+ }
55
+ if ('\n' == *buf->tail) {
56
+ buf->line++;
57
+ buf->col = 0;
58
+ } else {
59
+ buf->col++;
60
+ }
61
+ buf->pos++;
62
+
63
+ return *buf->tail++;
64
+ }
65
+
66
+ static inline void buf_backup(Buf buf) {
67
+ buf->tail--;
68
+ buf->col--;
69
+ buf->pos--;
70
+ if (0 >= buf->col) {
71
+ buf->line--;
72
+ // allow col to be negative since we never backup twice in a row
73
+ }
74
+ }
75
+
76
+ static inline void buf_protect(Buf buf) {
77
+ buf->pro = buf->tail;
78
+ buf->str = buf->tail; // can't have str before pro
79
+ buf->pro_pos = buf->pos;
80
+ buf->pro_line = buf->line;
81
+ buf->pro_col = buf->col;
82
+ }
83
+
84
+ static inline void buf_reset(Buf buf) {
85
+ buf->tail = buf->pro;
86
+ buf->pos = buf->pro_pos;
87
+ buf->line = buf->pro_line;
88
+ buf->col = buf->pro_col;
89
+ }
90
+
91
+ /* Starts by reading a character so it is safe to use with an empty or
92
+ * compacted buffer.
93
+ */
94
+ static inline char buf_next_non_white(Buf buf) {
95
+ char c;
96
+
97
+ while ('\0' != (c = buf_get(buf))) {
98
+ switch (c) {
99
+ case ' ':
100
+ case '\t':
101
+ case '\f':
102
+ case '\n':
103
+ case '\r': break;
104
+ default: return c;
105
+ }
106
+ }
107
+ return '\0';
108
+ }
109
+
110
+ /* Starts by reading a character so it is safe to use with an empty or
111
+ * compacted buffer.
112
+ */
113
+ static inline char buf_next_white(Buf buf) {
114
+ char c;
115
+
116
+ while ('\0' != (c = buf_get(buf))) {
117
+ switch (c) {
118
+ case ' ':
119
+ case '\t':
120
+ case '\f':
121
+ case '\n':
122
+ case '\r':
123
+ case '\0': return c;
124
+ default: break;
125
+ }
126
+ }
127
+ return '\0';
128
+ }
129
+
130
+ static inline void buf_cleanup(Buf buf) {
131
+ if (buf->base != buf->head && 0 != buf->head) {
132
+ xfree(buf->head);
133
+ buf->head = 0;
134
+ }
135
+ }
136
+
137
+ static inline int is_white(char c) {
138
+ switch (c) {
139
+ case ' ':
140
+ case '\t':
141
+ case '\f':
142
+ case '\n':
143
+ case '\r': return 1;
144
+ default: break;
145
+ }
146
+ return 0;
147
+ }
148
+
149
+ static inline void buf_checkpoint(Buf buf, CheckPt cp) {
150
+ cp->pro_dif = (int)(buf->tail - buf->pro);
151
+ cp->pos = buf->pos;
152
+ cp->line = buf->line;
153
+ cp->col = buf->col;
154
+ cp->c = *(buf->tail - 1);
155
+ }
156
+
157
+ static inline int buf_checkset(CheckPt cp) {
158
+ return (0 <= cp->pro_dif);
159
+ }
160
+
161
+ static inline char buf_checkback(Buf buf, CheckPt cp) {
162
+ buf->tail = buf->pro + cp->pro_dif;
163
+ buf->pos = cp->pos;
164
+ buf->line = cp->line;
165
+ buf->col = cp->col;
166
+ return cp->c;
167
+ }
168
+
169
+ static inline void buf_collapse_return(char *str) {
170
+ char *s = str;
171
+ char *back = str;
172
+
173
+ for (; '\0' != *s; s++) {
174
+ if (back != str && '\n' == *s && '\r' == *(back - 1)) {
175
+ *(back - 1) = '\n';
176
+ } else {
177
+ *back++ = *s;
178
+ }
179
+ }
180
+ *back = '\0';
181
+ }
182
+
183
+ static inline void buf_collapse_white(char *str) {
184
+ char *s = str;
185
+ char *back = str;
186
+
187
+ for (; '\0' != *s; s++) {
188
+ switch (*s) {
189
+ case ' ':
190
+ case '\t':
191
+ case '\f':
192
+ case '\n':
193
+ case '\r':
194
+ if (back == str || ' ' != *(back - 1)) {
195
+ *back++ = ' ';
196
+ }
197
+ break;
198
+ default: *back++ = *s; break;
199
+ }
200
+ }
201
+ *back = '\0';
202
+ }
203
+
204
+ #endif /* OX_SAX_BUF_H */
data/ext/ox/intern.c CHANGED
@@ -67,26 +67,26 @@ static VALUE form_id(const char *str, size_t len) {
67
67
  return (VALUE)rb_intern3(str, len, rb_utf8_encoding());
68
68
  }
69
69
 
70
- void ox_hash_init() {
70
+ void ox_hash_init(void) {
71
71
  VALUE cache_class = rb_define_class_under(Ox, "Cache", rb_cObject);
72
72
  #if RUBY_API_VERSION_CODE >= 30200
73
73
  rb_undef_alloc_func(cache_class);
74
74
  #endif
75
75
 
76
76
  ox_str_cache = ox_cache_create(0, form_str, true, false);
77
- ox_str_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_str_cache);
77
+ ox_str_cache_obj = TypedData_Wrap_Struct(cache_class, &ox_cache_type, ox_str_cache);
78
78
  rb_gc_register_address(&ox_str_cache_obj);
79
79
 
80
80
  ox_sym_cache = ox_cache_create(0, form_sym, true, false);
81
- ox_sym_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_sym_cache);
81
+ ox_sym_cache_obj = TypedData_Wrap_Struct(cache_class, &ox_cache_type, ox_sym_cache);
82
82
  rb_gc_register_address(&ox_sym_cache_obj);
83
83
 
84
84
  ox_attr_cache = ox_cache_create(0, form_attr, false, false);
85
- ox_attr_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_attr_cache);
85
+ ox_attr_cache_obj = TypedData_Wrap_Struct(cache_class, &ox_cache_type, ox_attr_cache);
86
86
  rb_gc_register_address(&ox_attr_cache_obj);
87
87
 
88
88
  ox_id_cache = ox_cache_create(0, form_id, false, false);
89
- ox_id_cache_obj = Data_Wrap_Struct(cache_class, ox_cache_mark, ox_cache_free, ox_id_cache);
89
+ ox_id_cache_obj = TypedData_Wrap_Struct(cache_class, &ox_cache_type, ox_id_cache);
90
90
  rb_gc_register_address(&ox_id_cache_obj);
91
91
  }
92
92
 
data/ext/ox/obj_load.c CHANGED
@@ -234,7 +234,7 @@ static unsigned long get_id_from_attrs(PInfo pi, Attr a) {
234
234
  return 0;
235
235
  }
236
236
 
237
- static CircArray circ_array_new() {
237
+ static CircArray circ_array_new(void) {
238
238
  CircArray ca;
239
239
 
240
240
  ca = ALLOC(struct _circArray);
data/ext/ox/ox.c CHANGED
@@ -1273,6 +1273,9 @@ static void parse_dump_options(VALUE ropts, Options copts) {
1273
1273
  * :strict
1274
1274
  * - _:strict_ - raise an NotImplementedError if an undumpable object is encountered
1275
1275
  * - _:tolerant_ - replaces undumplable objects with nil
1276
+ * - *:with_dtd* [true|false|nil] include DTD in the dump
1277
+ * - *:with_instruct* [true|false|nil] include instructions in the dump
1278
+ * - *:with_xml* [true|false|nil] include XML prolog in the dump
1276
1279
  *
1277
1280
  * Note that an indent of less than zero will result in a tight one line output
1278
1281
  * unless the text in the XML fields contain new line characters.
@@ -1310,6 +1313,9 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
1310
1313
  * :strict
1311
1314
  * - _:strict_ - raise an NotImplementedError if an undumpable object is encountered
1312
1315
  * - _:tolerant_ - replaces undumplable objects with nil
1316
+ * - *:with_dtd* [true|false|nil] include DTD in the dump
1317
+ * - *:with_instruct* [true|false|nil] include instructions in the dump
1318
+ * - *:with_xml* [true|false|nil] include XML prolog in the dump
1313
1319
  *
1314
1320
  * Note that an indent of less than zero will result in a tight one line output
1315
1321
  * unless the text in the XML fields contain new line characters.
@@ -1331,6 +1337,9 @@ static VALUE to_xml(int argc, VALUE *argv, VALUE self) {
1331
1337
  * :strict
1332
1338
  * - _:strict_ - raise an NotImplementedError if an undumpable object is encountered
1333
1339
  * - _:tolerant_ - replaces undumplable objects with nil
1340
+ * - *:with_dtd* [true|false|nil] include DTD in the dump
1341
+ * - *:with_instruct* [true|false|nil] include instructions in the dump
1342
+ * - *:with_xml* [true|false|nil] include XML prolog in the dump
1334
1343
  *
1335
1344
  * Note that an indent of less than zero will result in a tight one line output
1336
1345
  * unless the text in the XML fields contain new line characters.
@@ -1363,7 +1372,7 @@ static VALUE cache8_test(VALUE self) {
1363
1372
  }
1364
1373
  #endif
1365
1374
 
1366
- void Init_ox() {
1375
+ void Init_ox(void) {
1367
1376
  #if HAVE_RB_EXT_RACTOR_SAFE
1368
1377
  rb_ext_ractor_safe(true);
1369
1378
  #endif
data/ext/ox/parse.c CHANGED
@@ -18,6 +18,7 @@
18
18
  #include "ruby.h"
19
19
  #include "special.h"
20
20
 
21
+ static void mark_pi_cb(void *ptr);
21
22
  static void read_instruction(PInfo pi);
22
23
  static void read_doctype(PInfo pi);
23
24
  static void read_comment(PInfo pi);
@@ -33,6 +34,17 @@ static char *read_coded_chars(PInfo pi, char *text);
33
34
  static void next_non_white(PInfo pi);
34
35
  static int collapse_special(PInfo pi, char *str);
35
36
 
37
+ static const rb_data_type_t ox_wrap_type = {
38
+ "Object",
39
+ {
40
+ mark_pi_cb,
41
+ NULL,
42
+ NULL,
43
+ },
44
+ 0,
45
+ 0,
46
+ };
47
+
36
48
  /* This XML parser is a single pass, destructive, callback parser. It is a
37
49
  * single pass parse since it only make one pass over the characters in the
38
50
  * XML document string. It is destructive because it re-uses the content of
@@ -140,7 +152,7 @@ ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options
140
152
  // initialize parse info
141
153
  helper_stack_init(&pi.helpers);
142
154
  // Protect against GC
143
- wrap = Data_Wrap_Struct(rb_cObject, mark_pi_cb, NULL, &pi);
155
+ wrap = TypedData_Wrap_Struct(rb_cObject, &ox_wrap_type, &pi);
144
156
 
145
157
  err_init(&pi.err);
146
158
  pi.str = xml;
data/ext/ox/sax.c CHANGED
@@ -62,6 +62,17 @@ static Nv hint_try_close(SaxDrive dr, const char *name);
62
62
 
63
63
  VALUE ox_sax_value_class = Qnil;
64
64
 
65
+ const rb_data_type_t ox_sax_value_type = {
66
+ "Ox/Sax/Value",
67
+ {
68
+ NULL,
69
+ NULL,
70
+ NULL,
71
+ },
72
+ 0,
73
+ 0,
74
+ };
75
+
65
76
  static VALUE protect_parse(VALUE drp) {
66
77
  parse((SaxDrive)drp);
67
78
 
@@ -256,7 +267,7 @@ static void sax_drive_init(SaxDrive dr, VALUE handler, VALUE io, SaxOptions opti
256
267
  dr->buf.dr = dr;
257
268
  stack_init(&dr->stack);
258
269
  dr->handler = handler;
259
- dr->value_obj = Data_Wrap_Struct(ox_sax_value_class, 0, 0, dr);
270
+ dr->value_obj = TypedData_Wrap_Struct(ox_sax_value_class, &ox_sax_value_type, dr);
260
271
  rb_gc_register_address(&dr->value_obj);
261
272
  dr->options = *options;
262
273
  dr->err = 0;
@@ -984,7 +995,11 @@ static char read_element_end(SaxDrive dr) {
984
995
  } else {
985
996
  snprintf(msg, sizeof(msg) - 1, "%selement '%s' closed but not opened", EL_MISMATCH, dr->buf.str);
986
997
  ox_sax_drive_error_at(dr, msg, pos, line, col);
987
- name = str2sym(dr, dr->buf.str, dr->buf.tail - dr->buf.str - 2, 0);
998
+ if ('\x00' == *dr->buf.tail) {
999
+ name = str2sym(dr, dr->buf.str, dr->buf.tail - dr->buf.str - 1, 0);
1000
+ } else {
1001
+ name = str2sym(dr, dr->buf.str, dr->buf.tail - dr->buf.str - 2, 0);
1002
+ }
988
1003
  if (dr->has_start_element && 0 >= dr->blocked &&
989
1004
  (NULL == h || ActiveOverlay == h->overlay || NestOverlay == h->overlay)) {
990
1005
  VALUE args[1];
data/ext/ox/sax.h CHANGED
@@ -54,6 +54,8 @@ typedef struct _saxDrive {
54
54
 
55
55
  } *SaxDrive;
56
56
 
57
+ extern const rb_data_type_t ox_sax_value_type;
58
+
57
59
  extern void ox_collapse_return(char *str);
58
60
  extern void ox_sax_parse(VALUE handler, VALUE io, SaxOptions options);
59
61
  extern void ox_sax_drive_cleanup(SaxDrive dr);
data/ext/ox/sax_as.c CHANGED
@@ -106,9 +106,11 @@ static VALUE parse_xsd_time(const char *text) {
106
106
  * *return* value as an String.
107
107
  */
108
108
  static VALUE sax_value_as_s(VALUE self) {
109
- SaxDrive dr = DATA_PTR(self);
109
+ SaxDrive dr;
110
110
  VALUE rs;
111
111
 
112
+ TypedData_Get_Struct(self, struct _saxDrive, &ox_sax_value_type, dr);
113
+
112
114
  if ('\0' == *dr->buf.str) {
113
115
  return Qnil;
114
116
  }
@@ -132,7 +134,9 @@ static VALUE sax_value_as_s(VALUE self) {
132
134
  * *return* value as an Symbol.
133
135
  */
134
136
  static VALUE sax_value_as_sym(VALUE self) {
135
- SaxDrive dr = DATA_PTR(self);
137
+ SaxDrive dr;
138
+
139
+ TypedData_Get_Struct(self, struct _saxDrive, &ox_sax_value_type, dr);
136
140
 
137
141
  if ('\0' == *dr->buf.str) {
138
142
  return Qnil;
@@ -145,7 +149,9 @@ static VALUE sax_value_as_sym(VALUE self) {
145
149
  * *return* value as an Float.
146
150
  */
147
151
  static VALUE sax_value_as_f(VALUE self) {
148
- SaxDrive dr = DATA_PTR(self);
152
+ SaxDrive dr;
153
+
154
+ TypedData_Get_Struct(self, struct _saxDrive, &ox_sax_value_type, dr);
149
155
 
150
156
  if ('\0' == *dr->buf.str) {
151
157
  return Qnil;
@@ -158,11 +164,14 @@ static VALUE sax_value_as_f(VALUE self) {
158
164
  * *return* value as an Fixnum.
159
165
  */
160
166
  static VALUE sax_value_as_i(VALUE self) {
161
- SaxDrive dr = DATA_PTR(self);
162
- const char *s = dr->buf.str;
167
+ SaxDrive dr;
168
+ const char *s;
163
169
  long n = 0;
164
170
  int neg = 0;
165
171
 
172
+ TypedData_Get_Struct(self, struct _saxDrive, &ox_sax_value_type, dr);
173
+ s = dr->buf.str;
174
+
166
175
  if ('\0' == *s) {
167
176
  return Qnil;
168
177
  }
@@ -190,10 +199,13 @@ static VALUE sax_value_as_i(VALUE self) {
190
199
  * *return* value as an Time.
191
200
  */
192
201
  static VALUE sax_value_as_time(VALUE self) {
193
- SaxDrive dr = DATA_PTR(self);
194
- const char *str = dr->buf.str;
202
+ SaxDrive dr;
203
+ const char *str;
195
204
  VALUE t;
196
205
 
206
+ TypedData_Get_Struct(self, struct _saxDrive, &ox_sax_value_type, dr);
207
+ str = dr->buf.str;
208
+
197
209
  if ('\0' == *str) {
198
210
  return Qnil;
199
211
  }
@@ -212,7 +224,10 @@ static VALUE sax_value_as_time(VALUE self) {
212
224
  * *return* value as an boolean.
213
225
  */
214
226
  static VALUE sax_value_as_bool(VALUE self) {
215
- return (0 == strcasecmp("true", ((SaxDrive)DATA_PTR(self))->buf.str)) ? Qtrue : Qfalse;
227
+ SaxDrive dr;
228
+
229
+ TypedData_Get_Struct(self, struct _saxDrive, &ox_sax_value_type, dr);
230
+ return (0 == strcasecmp("true", dr->buf.str)) ? Qtrue : Qfalse;
216
231
  }
217
232
 
218
233
  /* call-seq: empty()
@@ -220,7 +235,10 @@ static VALUE sax_value_as_bool(VALUE self) {
220
235
  * *return* true if the value is empty.
221
236
  */
222
237
  static VALUE sax_value_empty(VALUE self) {
223
- return ('\0' == *((SaxDrive)DATA_PTR(self))->buf.str) ? Qtrue : Qfalse;
238
+ SaxDrive dr;
239
+
240
+ TypedData_Get_Struct(self, struct _saxDrive, &ox_sax_value_type, dr);
241
+ return ('\0' == *dr->buf.str) ? Qtrue : Qfalse;
224
242
  }
225
243
 
226
244
  /* Document-class: Ox::Sax::Value
@@ -228,7 +246,7 @@ static VALUE sax_value_empty(VALUE self) {
228
246
  * Values in the SAX callbacks. They can be converted to various different
229
247
  * types. with the _as_x()_ methods.
230
248
  */
231
- void ox_sax_define() {
249
+ void ox_sax_define(void) {
232
250
  #if 0
233
251
  ox = rb_define_module("Ox");
234
252
  #if RUBY_API_VERSION_CODE >= 30200
data/ext/ox/sax_buf.c CHANGED
@@ -198,7 +198,7 @@ static int read_from_str(Buf buf) {
198
198
  if (max < cnt) {
199
199
  cnt = max;
200
200
  }
201
- strncpy(buf->tail, buf->in.str, cnt);
201
+ memcpy(buf->tail, buf->in.str, cnt);
202
202
  s = buf->tail + cnt - 1;
203
203
  *s = '\0';
204
204
  cnt = s - buf->tail;
data/ext/ox/sax_buf.h CHANGED
@@ -39,8 +39,7 @@ typedef struct _checkPt {
39
39
  char c;
40
40
  } *CheckPt;
41
41
 
42
- #define CHECK_PT_INIT \
43
- { -1, 0, 0, 0, '\0' }
42
+ #define CHECK_PT_INIT {-1, 0, 0, 0, '\0'}
44
43
 
45
44
  extern void ox_sax_buf_init(Buf buf, VALUE io);
46
45
  extern int ox_sax_buf_read(Buf buf);
data/ext/ox/sax_hint.c CHANGED
@@ -153,7 +153,7 @@ static struct _hint html_hint_array[] = {
153
153
  };
154
154
  static struct _hints html_hints = {"HTML", html_hint_array, sizeof(html_hint_array) / sizeof(*html_hint_array)};
155
155
 
156
- Hints ox_hints_html() {
156
+ Hints ox_hints_html(void) {
157
157
  return &html_hints;
158
158
  }
159
159
 
data/ext/ox/special.c CHANGED
@@ -367,7 +367,7 @@ static Slot cache_get(const char *key) {
367
367
  return NULL;
368
368
  }
369
369
 
370
- static void cache_init() {
370
+ static void cache_init(void) {
371
371
  Slot e = entities;
372
372
 
373
373
  memset(&entity_cache, 0, sizeof(struct _cache));
data/lib/ox/element.rb CHANGED
@@ -79,7 +79,7 @@ module Ox
79
79
  # - +other+ [Object] Object compare _self_ to.
80
80
  # *return* [Boolean] true if both Objects are equivalent, otherwise false.
81
81
  def eql?(other)
82
- return false unless super(other)
82
+ return false unless super
83
83
  return false unless attributes == other.attributes
84
84
  return false unless nodes == other.nodes
85
85
 
@@ -100,7 +100,11 @@ module Ox
100
100
  def replace_text(txt)
101
101
  raise 'the argument to replace_text() must be a String' unless txt.is_a?(String)
102
102
 
103
- @nodes.clear
103
+ if !instance_variable_defined?(:@nodes) or @nodes.nil?
104
+ @node = []
105
+ else
106
+ @nodes.clear
107
+ end
104
108
  @nodes << txt
105
109
  end
106
110
 
data/lib/ox/instruct.rb CHANGED
@@ -23,7 +23,7 @@ module Ox
23
23
  # - +other+ [Object] Object compare _self_ to.
24
24
  # *return* [Boolean] true if both Objects are equivalent, otherwise false.
25
25
  def eql?(other)
26
- return false unless super(other)
26
+ return false unless super
27
27
  return false unless attributes == other.attributes
28
28
  return false unless content == other.content
29
29
 
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.18'
3
+ VERSION = '2.14.19'
4
4
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ox
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.14.18
4
+ version: 2.14.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-21 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2024-12-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bigdecimal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
13
27
  description: "A fast XML parser and object serializer that uses only standard C lib.\n\nOptimized
14
28
  XML (Ox), as the name implies was written to provide speed optimized\nXML handling.
15
29
  It was designed to be an alternative to Nokogiri and other Ruby\nXML parsers for
@@ -38,6 +52,7 @@ files:
38
52
  - ext/ox/err.c
39
53
  - ext/ox/err.h
40
54
  - ext/ox/extconf.rb
55
+ - ext/ox/foo.h
41
56
  - ext/ox/gen_load.c
42
57
  - ext/ox/hash_load.c
43
58
  - ext/ox/helper.h
@@ -79,6 +94,11 @@ homepage: http://www.ohler.com/ox
79
94
  licenses:
80
95
  - MIT
81
96
  metadata:
97
+ bug_tracker_uri: https://github.com/ohler55/ox/issues
98
+ changelog_uri: https://github.com/ohler55/ox/blob/master/CHANGELOG.md
99
+ documentation_uri: http://www.ohler.com/ox/doc/index.html
100
+ homepage_uri: http://www.ohler.com/ox/
101
+ source_code_uri: https://github.com/ohler55/ox
82
102
  rubygems_mfa_required: 'true'
83
103
  post_install_message:
84
104
  rdoc_options:
@@ -105,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
125
  - !ruby/object:Gem::Version
106
126
  version: '0'
107
127
  requirements: []
108
- rubygems_version: 3.4.10
128
+ rubygems_version: 3.5.11
109
129
  signing_key:
110
130
  specification_version: 4
111
131
  summary: A fast XML parser and object serializer.