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 +4 -4
- data/CHANGELOG.md +12 -0
- data/ext/ox/builder.c +71 -22
- data/ext/ox/cache.c +15 -2
- data/ext/ox/cache.h +4 -2
- data/ext/ox/foo.h +204 -0
- data/ext/ox/intern.c +5 -5
- data/ext/ox/obj_load.c +1 -1
- data/ext/ox/ox.c +10 -1
- data/ext/ox/parse.c +13 -1
- data/ext/ox/sax.c +17 -2
- data/ext/ox/sax.h +2 -0
- data/ext/ox/sax_as.c +28 -10
- data/ext/ox/sax_buf.c +1 -1
- data/ext/ox/sax_buf.h +1 -2
- data/ext/ox/sax_hint.c +1 -1
- data/ext/ox/special.c +1 -1
- data/lib/ox/element.rb +6 -2
- data/lib/ox/instruct.rb +1 -1
- data/lib/ox/version.rb +1 -1
- metadata +24 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f79925bdad366a8453ecda24602c7372371b5ac90363def31f7a21c5f46e85a
|
4
|
+
data.tar.gz: 1d88152e72cd654b215592b9874f6cf4c018853fcbfe3a5e3a37aa4f15a7d0f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 =
|
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
|
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 =
|
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
|
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 =
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
16
|
-
extern void ox_cache_mark(
|
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 =
|
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 =
|
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 =
|
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 =
|
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
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 =
|
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 =
|
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
|
-
|
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
|
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
|
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
|
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
|
162
|
-
const char *s
|
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
|
194
|
-
const char *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
|
-
|
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
|
-
|
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
data/ext/ox/sax_buf.h
CHANGED
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
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
|
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.
|
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
|
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
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.
|
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-
|
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.
|
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.
|