ox 2.14.13 → 2.14.15
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/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
|