ox 2.14.14 → 2.14.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +1 -1
- data/ext/ox/attr.h +33 -39
- data/ext/ox/base64.c +48 -42
- data/ext/ox/base64.h +4 -4
- data/ext/ox/buf.h +80 -86
- data/ext/ox/builder.c +378 -423
- data/ext/ox/cache.c +2 -2
- data/ext/ox/cache8.c +37 -40
- data/ext/ox/cache8.h +7 -7
- data/ext/ox/dump.c +838 -867
- data/ext/ox/err.c +16 -13
- data/ext/ox/err.h +11 -12
- data/ext/ox/extconf.rb +5 -5
- data/ext/ox/gen_load.c +135 -137
- data/ext/ox/hash_load.c +130 -148
- data/ext/ox/helper.h +32 -39
- data/ext/ox/intern.c +1 -2
- data/ext/ox/obj_load.c +590 -644
- data/ext/ox/ox.c +2 -2
- data/ext/ox/ox.h +5 -5
- data/ext/ox/parse.c +836 -874
- data/ext/ox/sax.c +38 -23
- data/ext/ox/sax.h +2 -2
- data/ext/ox/sax_as.c +78 -94
- data/ext/ox/sax_buf.c +85 -94
- data/ext/ox/sax_buf.h +101 -120
- data/ext/ox/sax_hint.c +175 -184
- data/ext/ox/sax_hint.h +19 -19
- data/ext/ox/sax_stack.h +59 -45
- data/ext/ox/slotcache.c +2 -2
- data/ext/ox/slotcache.h +4 -4
- data/ext/ox/special.c +320 -327
- data/ext/ox/special.h +2 -2
- data/ext/ox/type.h +19 -19
- data/lib/ox/bag.rb +13 -9
- data/lib/ox/cdata.rb +0 -2
- data/lib/ox/comment.rb +0 -2
- data/lib/ox/doctype.rb +0 -2
- data/lib/ox/document.rb +3 -5
- data/lib/ox/element.rb +41 -26
- data/lib/ox/error.rb +0 -3
- data/lib/ox/hasattrs.rb +7 -8
- data/lib/ox/instruct.rb +4 -6
- data/lib/ox/node.rb +3 -4
- data/lib/ox/raw.rb +0 -2
- data/lib/ox/sax.rb +20 -36
- data/lib/ox/version.rb +1 -2
- data/lib/ox/xmlrpc_adapter.rb +4 -6
- data/lib/ox.rb +15 -16
- metadata +6 -5
data/ext/ox/sax.c
CHANGED
@@ -761,17 +761,19 @@ CB:
|
|
761
761
|
* code.
|
762
762
|
*/
|
763
763
|
static char read_element_start(SaxDrive dr) {
|
764
|
-
const char *ename =
|
764
|
+
const char *ename = NULL;
|
765
|
+
char ebuf[128];
|
765
766
|
size_t nlen;
|
766
|
-
volatile VALUE name
|
767
|
+
volatile VALUE name = Qnil;
|
767
768
|
char c;
|
768
|
-
int closed;
|
769
769
|
long pos = (long)(dr->buf.pos);
|
770
770
|
long line = (long)(dr->buf.line);
|
771
771
|
long col = (long)(dr->buf.col);
|
772
772
|
Hint h = NULL;
|
773
773
|
int stackless = 0;
|
774
774
|
Nv parent = stack_peek(&dr->stack);
|
775
|
+
bool closed;
|
776
|
+
bool efree = false;
|
775
777
|
|
776
778
|
if ('\0' == (c = read_name_token(dr))) {
|
777
779
|
return '\0';
|
@@ -827,7 +829,7 @@ static char read_element_start(SaxDrive dr) {
|
|
827
829
|
if (0 != top_nv) {
|
828
830
|
char msg[256];
|
829
831
|
|
830
|
-
if (!h->nest && NestOverlay != h->overlay &&
|
832
|
+
if (!h->nest && NestOverlay != h->overlay && nv_same_name(top_nv, h->name, true)) {
|
831
833
|
snprintf(msg,
|
832
834
|
sizeof(msg) - 1,
|
833
835
|
"%s%s can not be nested in a %s document, closing previous.",
|
@@ -844,7 +846,7 @@ static char read_element_start(SaxDrive dr) {
|
|
844
846
|
int ok = 0;
|
845
847
|
|
846
848
|
for (p = h->parents; 0 != *p; p++) {
|
847
|
-
if (
|
849
|
+
if (nv_same_name(top_nv, *p, true)) {
|
848
850
|
ok = 1;
|
849
851
|
break;
|
850
852
|
}
|
@@ -855,7 +857,7 @@ static char read_element_start(SaxDrive dr) {
|
|
855
857
|
"%s%s can not be a child of a %s in a %s document.",
|
856
858
|
INV_ELEMENT,
|
857
859
|
h->name,
|
858
|
-
top_nv
|
860
|
+
nv_name(top_nv),
|
859
861
|
dr->options.hints->name);
|
860
862
|
ox_sax_drive_error(dr, msg);
|
861
863
|
}
|
@@ -864,6 +866,16 @@ static char read_element_start(SaxDrive dr) {
|
|
864
866
|
}
|
865
867
|
}
|
866
868
|
name = str2sym(dr, dr->buf.str, nlen, &ename);
|
869
|
+
if (NULL == ename) {
|
870
|
+
if (sizeof(ebuf) <= nlen) {
|
871
|
+
ename = strndup(dr->buf.str, nlen);
|
872
|
+
efree = true;
|
873
|
+
} else {
|
874
|
+
memcpy(ebuf, dr->buf.str, nlen);
|
875
|
+
ebuf[nlen] = '\0';
|
876
|
+
ename = ebuf;
|
877
|
+
}
|
878
|
+
}
|
867
879
|
if (dr->has_start_element && 0 >= dr->blocked &&
|
868
880
|
(NULL == h || ActiveOverlay == h->overlay || NestOverlay == h->overlay)) {
|
869
881
|
VALUE args[1];
|
@@ -875,9 +887,9 @@ static char read_element_start(SaxDrive dr) {
|
|
875
887
|
rb_funcall2(dr->handler, ox_start_element_id, 1, args);
|
876
888
|
}
|
877
889
|
if ('/' == c) {
|
878
|
-
closed =
|
890
|
+
closed = true;
|
879
891
|
} else if ('>' == c) {
|
880
|
-
closed =
|
892
|
+
closed = false;
|
881
893
|
} else {
|
882
894
|
buf_protect(&dr->buf);
|
883
895
|
c = read_attrs(dr, c, '/', '>', 0, 0, h);
|
@@ -906,11 +918,14 @@ static char read_element_start(SaxDrive dr) {
|
|
906
918
|
} else {
|
907
919
|
stack_push(&dr->stack, ename, nlen, name, h);
|
908
920
|
}
|
921
|
+
if (efree) {
|
922
|
+
free((char *)ename);
|
923
|
+
}
|
909
924
|
if ('>' != c) {
|
910
925
|
ox_sax_drive_error(dr, WRONG_CHAR "element not closed");
|
911
926
|
return c;
|
912
927
|
}
|
913
|
-
dr->buf.str =
|
928
|
+
dr->buf.str = NULL;
|
914
929
|
|
915
930
|
return buf_get(&dr->buf);
|
916
931
|
}
|
@@ -919,7 +934,7 @@ static Nv stack_rev_find(SaxDrive dr, const char *name) {
|
|
919
934
|
Nv nv;
|
920
935
|
|
921
936
|
for (nv = dr->stack.tail - 1; dr->stack.head <= nv; nv--) {
|
922
|
-
if (
|
937
|
+
if (nv_same_name(nv, name, dr->options.smart)) {
|
923
938
|
return nv;
|
924
939
|
}
|
925
940
|
}
|
@@ -944,7 +959,7 @@ static char read_element_end(SaxDrive dr) {
|
|
944
959
|
// c should be > and current is one past so read another char
|
945
960
|
c = buf_get(&dr->buf);
|
946
961
|
nv = stack_peek(&dr->stack);
|
947
|
-
if (0 != nv &&
|
962
|
+
if (0 != nv && nv_same_name(nv, dr->buf.str, dr->options.smart)) {
|
948
963
|
name = nv->val;
|
949
964
|
h = nv->hint;
|
950
965
|
stack_pop(&dr->stack);
|
@@ -997,7 +1012,7 @@ static char read_element_end(SaxDrive dr) {
|
|
997
1012
|
"%selement '%s' close does not match '%s' open",
|
998
1013
|
EL_MISMATCH,
|
999
1014
|
dr->buf.str,
|
1000
|
-
nv
|
1015
|
+
nv_name(nv));
|
1001
1016
|
ox_sax_drive_error_at(dr, msg, pos, line, col);
|
1002
1017
|
for (nv = stack_pop(&dr->stack); match < nv; nv = stack_pop(&dr->stack)) {
|
1003
1018
|
end_element_cb(dr, nv->val, pos, line, col, nv->hint);
|
@@ -1465,18 +1480,18 @@ int ox_sax_collapse_special(SaxDrive dr, char *str, long pos, long line, long co
|
|
1465
1480
|
break;
|
1466
1481
|
}
|
1467
1482
|
case '\r':
|
1468
|
-
|
1483
|
+
s++;
|
1469
1484
|
if ('\n' == *s) {
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1485
|
+
continue;
|
1486
|
+
}
|
1487
|
+
line++;
|
1488
|
+
col = 1;
|
1474
1489
|
*b++ = '\n';
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1490
|
+
break;
|
1491
|
+
case '\n':
|
1492
|
+
line++;
|
1493
|
+
col = 0;
|
1494
|
+
// fall through
|
1480
1495
|
default:
|
1481
1496
|
col++;
|
1482
1497
|
*b++ = *s++;
|
@@ -1512,7 +1527,7 @@ static Nv hint_try_close(SaxDrive dr, const char *name) {
|
|
1512
1527
|
return 0;
|
1513
1528
|
}
|
1514
1529
|
for (nv = stack_peek(&dr->stack); 0 != nv; nv = stack_peek(&dr->stack)) {
|
1515
|
-
if (
|
1530
|
+
if (nv_same_name(nv, name, true)) {
|
1516
1531
|
stack_pop(&dr->stack);
|
1517
1532
|
return nv;
|
1518
1533
|
}
|
data/ext/ox/sax.h
CHANGED
@@ -20,7 +20,7 @@ typedef struct _saxOptions {
|
|
20
20
|
SkipMode skip;
|
21
21
|
char strip_ns[64];
|
22
22
|
Hints hints;
|
23
|
-
} *
|
23
|
+
} *SaxOptions;
|
24
24
|
|
25
25
|
typedef struct _saxDrive {
|
26
26
|
struct _buf buf;
|
@@ -52,7 +52,7 @@ typedef struct _saxDrive {
|
|
52
52
|
bool has_start_element;
|
53
53
|
bool has_end_element;
|
54
54
|
|
55
|
-
} *
|
55
|
+
} *SaxDrive;
|
56
56
|
|
57
57
|
extern void ox_collapse_return(char *str);
|
58
58
|
extern void ox_sax_parse(VALUE handler, VALUE io, SaxOptions options);
|
data/ext/ox/sax_as.c
CHANGED
@@ -3,27 +3,26 @@
|
|
3
3
|
* All rights reserved.
|
4
4
|
*/
|
5
5
|
|
6
|
-
#include <stdlib.h>
|
7
6
|
#include <errno.h>
|
8
7
|
#include <stdio.h>
|
8
|
+
#include <stdlib.h>
|
9
9
|
#include <strings.h>
|
10
10
|
#include <sys/types.h>
|
11
11
|
#if HAVE_SYS_UIO_H
|
12
12
|
#include <sys/uio.h>
|
13
13
|
#endif
|
14
|
-
#include <unistd.h>
|
15
14
|
#include <time.h>
|
15
|
+
#include <unistd.h>
|
16
16
|
|
17
|
+
#include "ox.h"
|
17
18
|
#include "ruby.h"
|
18
19
|
#include "ruby/version.h"
|
19
|
-
#include "ox.h"
|
20
20
|
#include "sax.h"
|
21
21
|
|
22
|
-
static VALUE
|
23
|
-
|
24
|
-
long
|
25
|
-
|
26
|
-
const char *dot = 0;
|
22
|
+
static VALUE parse_double_time(const char *text) {
|
23
|
+
long v = 0;
|
24
|
+
long v2 = 0;
|
25
|
+
const char *dot = 0;
|
27
26
|
char c;
|
28
27
|
|
29
28
|
for (; '.' != *text; text++) {
|
@@ -52,58 +51,57 @@ parse_double_time(const char *text) {
|
|
52
51
|
}
|
53
52
|
|
54
53
|
typedef struct _tp {
|
55
|
-
int
|
56
|
-
char
|
57
|
-
char
|
54
|
+
int cnt;
|
55
|
+
char end;
|
56
|
+
char alt;
|
58
57
|
} *Tp;
|
59
58
|
|
60
|
-
static VALUE
|
61
|
-
|
62
|
-
long
|
63
|
-
long
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
struct tm tm;
|
59
|
+
static VALUE parse_xsd_time(const char *text) {
|
60
|
+
long cargs[10];
|
61
|
+
long *cp = cargs;
|
62
|
+
long v;
|
63
|
+
int i;
|
64
|
+
char c = '\0';
|
65
|
+
struct _tp tpa[10] = {{4, '-', '-'},
|
66
|
+
{2, '-', '-'},
|
67
|
+
{2, 'T', ' '},
|
68
|
+
{2, ':', ':'},
|
69
|
+
{2, ':', ':'},
|
70
|
+
{2, '.', '.'},
|
71
|
+
{9, '+', '-'},
|
72
|
+
{2, ':', ':'},
|
73
|
+
{2, '\0', '\0'},
|
74
|
+
{0, '\0', '\0'}};
|
75
|
+
Tp tp = tpa;
|
76
|
+
struct tm tm;
|
79
77
|
|
80
78
|
memset(cargs, 0, sizeof(cargs));
|
81
79
|
for (; 0 != tp->cnt; tp++) {
|
82
|
-
for (i = tp->cnt, v = 0; 0 < i
|
80
|
+
for (i = tp->cnt, v = 0; 0 < i; text++, i--) {
|
83
81
|
c = *text;
|
84
82
|
if (c < '0' || '9' < c) {
|
85
83
|
if ('\0' == c || tp->end == c || tp->alt == c) {
|
86
84
|
break;
|
87
85
|
}
|
88
|
-
|
86
|
+
return Qnil;
|
89
87
|
}
|
90
88
|
v = 10 * v + (long)(c - '0');
|
91
89
|
}
|
92
|
-
|
93
|
-
|
94
|
-
|
90
|
+
if ('\0' == c) {
|
91
|
+
break;
|
92
|
+
}
|
95
93
|
c = *text++;
|
96
94
|
if (tp->end != c && tp->alt != c) {
|
97
|
-
|
95
|
+
return Qnil;
|
98
96
|
}
|
99
97
|
*cp++ = v;
|
100
98
|
}
|
101
99
|
tm.tm_year = (int)cargs[0] - 1900;
|
102
|
-
tm.tm_mon
|
100
|
+
tm.tm_mon = (int)cargs[1] - 1;
|
103
101
|
tm.tm_mday = (int)cargs[2];
|
104
102
|
tm.tm_hour = (int)cargs[3];
|
105
|
-
tm.tm_min
|
106
|
-
tm.tm_sec
|
103
|
+
tm.tm_min = (int)cargs[4];
|
104
|
+
tm.tm_sec = (int)cargs[5];
|
107
105
|
#if HAVE_RB_TIME_NANO_NEW
|
108
106
|
return rb_time_nano_new(mktime(&tm), cargs[6]);
|
109
107
|
#else
|
@@ -115,30 +113,24 @@ parse_xsd_time(const char *text) {
|
|
115
113
|
*
|
116
114
|
* *return* value as an String.
|
117
115
|
*/
|
118
|
-
static VALUE
|
119
|
-
|
120
|
-
|
121
|
-
VALUE rs;
|
116
|
+
static VALUE sax_value_as_s(VALUE self) {
|
117
|
+
SaxDrive dr = DATA_PTR(self);
|
118
|
+
VALUE rs;
|
122
119
|
|
123
120
|
if ('\0' == *dr->buf.str) {
|
124
|
-
|
121
|
+
return Qnil;
|
125
122
|
}
|
126
123
|
if (dr->options.convert_special) {
|
127
|
-
|
124
|
+
ox_sax_collapse_special(dr, dr->buf.str, dr->buf.pos, dr->buf.line, dr->buf.col);
|
128
125
|
}
|
129
126
|
switch (dr->options.skip) {
|
130
|
-
case CrSkip:
|
131
|
-
|
132
|
-
|
133
|
-
case SpcSkip:
|
134
|
-
buf_collapse_white(dr->buf.str);
|
135
|
-
break;
|
136
|
-
default:
|
137
|
-
break;
|
127
|
+
case CrSkip: buf_collapse_return(dr->buf.str); break;
|
128
|
+
case SpcSkip: buf_collapse_white(dr->buf.str); break;
|
129
|
+
default: break;
|
138
130
|
}
|
139
131
|
rs = rb_str_new2(dr->buf.str);
|
140
132
|
if (0 != dr->encoding) {
|
141
|
-
|
133
|
+
rb_enc_associate(rs, dr->encoding);
|
142
134
|
}
|
143
135
|
return rs;
|
144
136
|
}
|
@@ -147,12 +139,11 @@ sax_value_as_s(VALUE self) {
|
|
147
139
|
*
|
148
140
|
* *return* value as an Symbol.
|
149
141
|
*/
|
150
|
-
static VALUE
|
151
|
-
|
152
|
-
SaxDrive dr = DATA_PTR(self);
|
142
|
+
static VALUE sax_value_as_sym(VALUE self) {
|
143
|
+
SaxDrive dr = DATA_PTR(self);
|
153
144
|
|
154
145
|
if ('\0' == *dr->buf.str) {
|
155
|
-
|
146
|
+
return Qnil;
|
156
147
|
}
|
157
148
|
return str2sym(dr, dr->buf.str, strlen(dr->buf.str), 0);
|
158
149
|
}
|
@@ -161,12 +152,11 @@ sax_value_as_sym(VALUE self) {
|
|
161
152
|
*
|
162
153
|
* *return* value as an Float.
|
163
154
|
*/
|
164
|
-
static VALUE
|
165
|
-
|
166
|
-
SaxDrive dr = DATA_PTR(self);
|
155
|
+
static VALUE sax_value_as_f(VALUE self) {
|
156
|
+
SaxDrive dr = DATA_PTR(self);
|
167
157
|
|
168
158
|
if ('\0' == *dr->buf.str) {
|
169
|
-
|
159
|
+
return Qnil;
|
170
160
|
}
|
171
161
|
return rb_float_new(strtod(dr->buf.str, 0));
|
172
162
|
}
|
@@ -175,31 +165,30 @@ sax_value_as_f(VALUE self) {
|
|
175
165
|
*
|
176
166
|
* *return* value as an Fixnum.
|
177
167
|
*/
|
178
|
-
static VALUE
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
int neg = 0;
|
168
|
+
static VALUE sax_value_as_i(VALUE self) {
|
169
|
+
SaxDrive dr = DATA_PTR(self);
|
170
|
+
const char *s = dr->buf.str;
|
171
|
+
long n = 0;
|
172
|
+
int neg = 0;
|
184
173
|
|
185
174
|
if ('\0' == *s) {
|
186
|
-
|
175
|
+
return Qnil;
|
187
176
|
}
|
188
177
|
if ('-' == *s) {
|
189
|
-
|
190
|
-
|
178
|
+
neg = 1;
|
179
|
+
s++;
|
191
180
|
} else if ('+' == *s) {
|
192
|
-
|
181
|
+
s++;
|
193
182
|
}
|
194
183
|
for (; '\0' != *s; s++) {
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
184
|
+
if ('0' <= *s && *s <= '9') {
|
185
|
+
n = n * 10 + (*s - '0');
|
186
|
+
} else {
|
187
|
+
rb_raise(ox_arg_error_class, "Not a valid Fixnum.\n");
|
188
|
+
}
|
200
189
|
}
|
201
190
|
if (neg) {
|
202
|
-
|
191
|
+
n = -n;
|
203
192
|
}
|
204
193
|
return LONG2NUM(n);
|
205
194
|
}
|
@@ -208,22 +197,20 @@ sax_value_as_i(VALUE self) {
|
|
208
197
|
*
|
209
198
|
* *return* value as an Time.
|
210
199
|
*/
|
211
|
-
static VALUE
|
212
|
-
|
213
|
-
|
214
|
-
const char *str = dr->buf.str;
|
200
|
+
static VALUE sax_value_as_time(VALUE self) {
|
201
|
+
SaxDrive dr = DATA_PTR(self);
|
202
|
+
const char *str = dr->buf.str;
|
215
203
|
VALUE t;
|
216
204
|
|
217
205
|
if ('\0' == *str) {
|
218
|
-
|
206
|
+
return Qnil;
|
219
207
|
}
|
220
|
-
if (Qnil == (t = parse_double_time(str)) &&
|
221
|
-
|
222
|
-
VALUE args[1];
|
208
|
+
if (Qnil == (t = parse_double_time(str)) && Qnil == (t = parse_xsd_time(str))) {
|
209
|
+
VALUE args[1];
|
223
210
|
|
224
211
|
/*printf("**** time parse\n"); */
|
225
212
|
*args = rb_str_new2(str);
|
226
|
-
t
|
213
|
+
t = rb_funcall2(ox_time_class, ox_parse_id, 1, args);
|
227
214
|
}
|
228
215
|
return t;
|
229
216
|
}
|
@@ -232,8 +219,7 @@ sax_value_as_time(VALUE self) {
|
|
232
219
|
*
|
233
220
|
* *return* value as an boolean.
|
234
221
|
*/
|
235
|
-
static VALUE
|
236
|
-
sax_value_as_bool(VALUE self) {
|
222
|
+
static VALUE sax_value_as_bool(VALUE self) {
|
237
223
|
return (0 == strcasecmp("true", ((SaxDrive)DATA_PTR(self))->buf.str)) ? Qtrue : Qfalse;
|
238
224
|
}
|
239
225
|
|
@@ -241,8 +227,7 @@ sax_value_as_bool(VALUE self) {
|
|
241
227
|
*
|
242
228
|
* *return* true if the value is empty.
|
243
229
|
*/
|
244
|
-
static VALUE
|
245
|
-
sax_value_empty(VALUE self) {
|
230
|
+
static VALUE sax_value_empty(VALUE self) {
|
246
231
|
return ('\0' == *((SaxDrive)DATA_PTR(self))->buf.str) ? Qtrue : Qfalse;
|
247
232
|
}
|
248
233
|
|
@@ -251,15 +236,14 @@ sax_value_empty(VALUE self) {
|
|
251
236
|
* Values in the SAX callbacks. They can be converted to various different
|
252
237
|
* types. with the _as_x()_ methods.
|
253
238
|
*/
|
254
|
-
void
|
255
|
-
ox_sax_define() {
|
239
|
+
void ox_sax_define() {
|
256
240
|
#if 0
|
257
241
|
ox = rb_define_module("Ox");
|
258
242
|
#if RUBY_API_VERSION_CODE >= 30200
|
259
243
|
sax_module = rb_define_class_under(ox, "Sax", rb_cObject);
|
260
244
|
#endif
|
261
245
|
#endif
|
262
|
-
VALUE
|
246
|
+
VALUE sax_module = rb_const_get_at(Ox, rb_intern("Sax"));
|
263
247
|
|
264
248
|
ox_sax_value_class = rb_define_class_under(sax_module, "Value", rb_cObject);
|
265
249
|
#if RUBY_API_VERSION_CODE >= 30200
|