ox 2.12.0 → 2.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/ext/ox/builder.c +8 -6
- data/ext/ox/dump.c +12 -6
- data/ext/ox/extconf.rb +5 -1
- data/ext/ox/hash_load.c +60 -16
- data/ext/ox/ox.h +4 -1
- data/ext/ox/parse.c +22 -23
- data/ext/ox/sax.c +41 -41
- data/ext/ox/sax.h +1 -1
- data/lib/ox/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d2959b76c94fd92a6234a9cf211f27263ac36da3e0b74bc724edc2f278585a4
|
4
|
+
data.tar.gz: eae845e3147144ee70d3b8f41603295c962c00a202282af8b0bd42cacde02ade
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe53b32f1daae7e8444ce0efa476f3b69fee96b72b5f61dcda51aca3769bac24a2edbfc7aae914bcb073e845af7487d7004fec0b8c6408bee1b3515c6bff6315
|
7
|
+
data.tar.gz: ee673dbd381c0983cf592090c7bf01d99cbd23d9c5a2740892c9db688bf294824e4510ceff4bb31a0e340c13db8b78bb09badae1186c1929edd27ec59b8da9b2
|
data/CHANGELOG.md
CHANGED
@@ -4,8 +4,18 @@ All changes to the Ox gem are documented here. Releases follow semantic versioni
|
|
4
4
|
|
5
5
|
## [Unreleased]
|
6
6
|
|
7
|
+
## [2.12.1] - 2020-01-05
|
8
|
+
|
9
|
+
Ruby 2.7.0
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
- Updated for Ruby 2.7.0. More strict type checking. Function signature changes, and `Object#taint` deprecated.
|
14
|
+
|
7
15
|
## [2.12.0] - 2019-12-18
|
8
16
|
|
17
|
+
### Added
|
18
|
+
|
9
19
|
- Add `no_empty` option to not allow <xyz/> and use <xyz></xyz> instead.
|
10
20
|
|
11
21
|
## [2.11.0] - 2019-06-14
|
data/ext/ox/builder.c
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
typedef struct _element {
|
18
18
|
char *name;
|
19
19
|
char buf[64];
|
20
|
-
|
20
|
+
long len;
|
21
21
|
bool has_child;
|
22
22
|
bool non_text_child;
|
23
23
|
} *Element;
|
@@ -124,7 +124,7 @@ append_string(Builder b, const char *str, size_t size, const char *table, bool s
|
|
124
124
|
char buf[256];
|
125
125
|
char *end = buf + sizeof(buf) - 1;
|
126
126
|
char *bp = buf;
|
127
|
-
|
127
|
+
size_t i = size;
|
128
128
|
int fcnt;
|
129
129
|
|
130
130
|
for (; '\0' != *str && 0 < i; i--, str++) {
|
@@ -183,7 +183,7 @@ append_string(Builder b, const char *str, size_t size, const char *table, bool s
|
|
183
183
|
static void
|
184
184
|
append_sym_str(Builder b, VALUE v) {
|
185
185
|
const char *s;
|
186
|
-
|
186
|
+
long len;
|
187
187
|
|
188
188
|
switch (rb_type(v)) {
|
189
189
|
case T_STRING:
|
@@ -219,7 +219,9 @@ i_am_a_child(Builder b, bool is_text) {
|
|
219
219
|
}
|
220
220
|
|
221
221
|
static int
|
222
|
-
append_attr(VALUE key, VALUE value,
|
222
|
+
append_attr(VALUE key, VALUE value, VALUE bv) {
|
223
|
+
Builder b = (Builder)bv;
|
224
|
+
|
223
225
|
buf_append(&b->buf, ' ');
|
224
226
|
b->col++;
|
225
227
|
b->pos++;
|
@@ -600,7 +602,7 @@ builder_element(int argc, VALUE *argv, VALUE self) {
|
|
600
602
|
Builder b = (Builder)DATA_PTR(self);
|
601
603
|
Element e;
|
602
604
|
const char *name;
|
603
|
-
|
605
|
+
long len;
|
604
606
|
|
605
607
|
if (1 > argc) {
|
606
608
|
rb_raise(ox_arg_error_class, "missing element name");
|
@@ -662,7 +664,7 @@ static VALUE
|
|
662
664
|
builder_void_element(int argc, VALUE *argv, VALUE self) {
|
663
665
|
Builder b = (Builder)DATA_PTR(self);
|
664
666
|
const char *name;
|
665
|
-
|
667
|
+
long len;
|
666
668
|
|
667
669
|
if (1 > argc) {
|
668
670
|
rb_raise(ox_arg_error_class, "missing element name");
|
data/ext/ox/dump.c
CHANGED
@@ -54,7 +54,7 @@ static void dump_obj(ID aid, VALUE obj, int depth, Out out);
|
|
54
54
|
static void dump_gen_doc(VALUE obj, int depth, Out out);
|
55
55
|
static void dump_gen_element(VALUE obj, int depth, Out out);
|
56
56
|
static void dump_gen_instruct(VALUE obj, int depth, Out out);
|
57
|
-
static int dump_gen_attr(VALUE key, VALUE value,
|
57
|
+
static int dump_gen_attr(VALUE key, VALUE value, VALUE ov);
|
58
58
|
static int dump_gen_nodes(VALUE obj, int depth, Out out);
|
59
59
|
static void dump_gen_val_node(VALUE obj, int depth,
|
60
60
|
const char *pre, size_t plen,
|
@@ -67,12 +67,12 @@ static void grow(Out out, size_t len);
|
|
67
67
|
|
68
68
|
static void dump_value(Out out, const char *value, size_t size);
|
69
69
|
static void dump_str_value(Out out, const char *value, size_t size, const char *table);
|
70
|
-
static int dump_var(ID key, VALUE value,
|
70
|
+
static int dump_var(ID key, VALUE value, VALUE ov);
|
71
71
|
static void dump_num(Out out, VALUE obj);
|
72
72
|
static void dump_date(Out out, VALUE obj);
|
73
73
|
static void dump_time_thin(Out out, VALUE obj);
|
74
74
|
static void dump_time_xsd(Out out, VALUE obj);
|
75
|
-
static int dump_hash(VALUE key, VALUE value,
|
75
|
+
static int dump_hash(VALUE key, VALUE value, VALUE ov);
|
76
76
|
|
77
77
|
static int is_xml_friendly(const uchar *str, int len, const char *table);
|
78
78
|
|
@@ -1005,7 +1005,9 @@ dump_obj(ID aid, VALUE obj, int depth, Out out) {
|
|
1005
1005
|
}
|
1006
1006
|
|
1007
1007
|
static int
|
1008
|
-
dump_var(ID key, VALUE value,
|
1008
|
+
dump_var(ID key, VALUE value, VALUE ov) {
|
1009
|
+
Out out = (Out)ov;
|
1010
|
+
|
1009
1011
|
if (T_DATA == rb_type(value) && key == ox_mesg_id) {
|
1010
1012
|
/* There is a secret recipe that keeps Exception mesg attributes as a
|
1011
1013
|
* T_DATA until it is needed. The safe way around this hack is to call
|
@@ -1022,7 +1024,9 @@ dump_var(ID key, VALUE value, Out out) {
|
|
1022
1024
|
}
|
1023
1025
|
|
1024
1026
|
static int
|
1025
|
-
dump_hash(VALUE key, VALUE value,
|
1027
|
+
dump_hash(VALUE key, VALUE value, VALUE ov) {
|
1028
|
+
Out out = (Out)ov;
|
1029
|
+
|
1026
1030
|
dump_obj(0, key, out->depth, out);
|
1027
1031
|
dump_obj(0, value, out->depth, out);
|
1028
1032
|
|
@@ -1198,7 +1202,9 @@ dump_gen_nodes(VALUE obj, int depth, Out out) {
|
|
1198
1202
|
}
|
1199
1203
|
|
1200
1204
|
static int
|
1201
|
-
dump_gen_attr(VALUE key, VALUE value,
|
1205
|
+
dump_gen_attr(VALUE key, VALUE value, VALUE ov) {
|
1206
|
+
Out out = (Out)ov;
|
1207
|
+
|
1202
1208
|
const char *ks;
|
1203
1209
|
size_t klen;
|
1204
1210
|
size_t size;
|
data/ext/ox/extconf.rb
CHANGED
@@ -20,7 +20,7 @@ dflags = {
|
|
20
20
|
'RUBY_VERSION_MICRO' => version[2],
|
21
21
|
'HAS_RB_TIME_TIMESPEC' => ('ruby' == type && ('1.9.3' == RUBY_VERSION)) ? 1 : 0,
|
22
22
|
#'HAS_RB_TIME_TIMESPEC' => ('ruby' == type && ('1.9.3' == RUBY_VERSION || '2' <= version[0])) ? 1 : 0,
|
23
|
-
'HAS_TM_GMTOFF' => ('ruby' == type && (('1' == version[0] && '9' == version[1]) || '2' <= version[0]) &&
|
23
|
+
'HAS_TM_GMTOFF' => ('ruby' == type && (('1' == version[0] && '9' == version[1]) || '2' <= version[0]) &&
|
24
24
|
!(platform.include?('cygwin') || platform.include?('solaris') || platform.include?('linux') || RUBY_PLATFORM =~ /(win|w)32$/)) ? 1 : 0,
|
25
25
|
'HAS_ENCODING_SUPPORT' => (('ruby' == type || 'rubinius' == type || 'macruby' == type) &&
|
26
26
|
(('1' == version[0] && '9' == version[1]) || '2' <= version[0])) ? 1 : 0,
|
@@ -62,6 +62,10 @@ dflags.each do |k,v|
|
|
62
62
|
end
|
63
63
|
$CPPFLAGS += ' -Wall'
|
64
64
|
#puts "*** $CPPFLAGS: #{$CPPFLAGS}"
|
65
|
+
CONFIG['warnflags'].slice!(/ -Wsuggest-attribute=format/)
|
66
|
+
CONFIG['warnflags'].slice!(/ -Wdeclaration-after-statement/)
|
67
|
+
CONFIG['warnflags'].slice!(/ -Wmissing-noreturn/)
|
68
|
+
|
65
69
|
create_makefile(extension_name)
|
66
70
|
|
67
71
|
%x{make clean}
|
data/ext/ox/hash_load.c
CHANGED
@@ -13,12 +13,14 @@
|
|
13
13
|
#include "ruby.h"
|
14
14
|
#include "ox.h"
|
15
15
|
|
16
|
+
#define MARK_INC 256
|
17
|
+
|
16
18
|
// The approach taken for the hash and has_no_attrs parsing is to push just
|
17
19
|
// the key on to the stack and then decide what to do on the way up/out.
|
18
20
|
|
19
21
|
static VALUE
|
20
22
|
create_top(PInfo pi) {
|
21
|
-
volatile VALUE top = rb_hash_new()
|
23
|
+
volatile VALUE top = rb_hash_new();
|
22
24
|
|
23
25
|
helper_stack_push(&pi->helpers, 0, top, HashCode);
|
24
26
|
pi->obj = top;
|
@@ -26,6 +28,51 @@ create_top(PInfo pi) {
|
|
26
28
|
return top;
|
27
29
|
}
|
28
30
|
|
31
|
+
static void
|
32
|
+
mark_value(PInfo pi, VALUE val) {
|
33
|
+
if (NULL == pi->marked) {
|
34
|
+
pi->marked = ALLOC_N(VALUE, MARK_INC);
|
35
|
+
pi->mark_size = MARK_INC;
|
36
|
+
} else if (pi->mark_size <= pi->mark_cnt) {
|
37
|
+
pi->mark_size += MARK_INC;
|
38
|
+
pi->marked = REALLOC_N(pi->marked, VALUE, pi->mark_size);
|
39
|
+
}
|
40
|
+
pi->marked[pi->mark_cnt] = val;
|
41
|
+
pi->mark_cnt++;
|
42
|
+
}
|
43
|
+
|
44
|
+
static bool
|
45
|
+
marked(PInfo pi, VALUE val) {
|
46
|
+
if (NULL != pi->marked) {
|
47
|
+
VALUE *vp = pi->marked + pi->mark_cnt - 1;
|
48
|
+
|
49
|
+
for (; pi->marked <= vp; vp--) {
|
50
|
+
if (val == *vp) {
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
return false;
|
56
|
+
}
|
57
|
+
|
58
|
+
static void
|
59
|
+
unmark(PInfo pi, VALUE val) {
|
60
|
+
if (NULL != pi->marked) {
|
61
|
+
VALUE *vp = pi->marked + pi->mark_cnt - 1;
|
62
|
+
int i;
|
63
|
+
|
64
|
+
for (i = 0; pi->marked <= vp; vp--, i++) {
|
65
|
+
if (val == *vp) {
|
66
|
+
for (; 0 < i; i--, vp++) {
|
67
|
+
*vp = *(vp + 1);
|
68
|
+
}
|
69
|
+
pi->mark_cnt--;
|
70
|
+
break;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
29
76
|
static void
|
30
77
|
add_text(PInfo pi, char *text, int closed) {
|
31
78
|
Helper parent = helper_stack_peek(&pi->helpers);
|
@@ -92,7 +139,7 @@ add_element(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
92
139
|
}
|
93
140
|
a = rb_ary_new();
|
94
141
|
rb_ary_push(a, h);
|
95
|
-
|
142
|
+
mark_value(pi, a);
|
96
143
|
helper_stack_push(&pi->helpers, rb_intern(ename), a, ArrayCode);
|
97
144
|
} else {
|
98
145
|
helper_stack_push(&pi->helpers, rb_intern(ename), Qnil, NoCode);
|
@@ -108,15 +155,14 @@ add_element_no_attrs(PInfo pi, const char *ename, Attr attrs, int hasChildren) {
|
|
108
155
|
}
|
109
156
|
|
110
157
|
static int
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
}
|
158
|
+
umark_hash_cb(VALUE key, VALUE value, VALUE x) {
|
159
|
+
unmark((PInfo)x, value);
|
160
|
+
|
115
161
|
return ST_CONTINUE;
|
116
162
|
}
|
117
163
|
|
118
164
|
static void
|
119
|
-
end_element_core(PInfo pi, const char *ename, bool
|
165
|
+
end_element_core(PInfo pi, const char *ename, bool check_marked) {
|
120
166
|
Helper e = helper_stack_pop(&pi->helpers);
|
121
167
|
Helper parent = helper_stack_peek(&pi->helpers);
|
122
168
|
volatile VALUE pobj = parent->obj;
|
@@ -161,8 +207,8 @@ end_element_core(PInfo pi, const char *ename, bool check_taint) {
|
|
161
207
|
if (Qundef == found) {
|
162
208
|
rb_hash_aset(pobj, key, e->obj);
|
163
209
|
} else if (RUBY_T_ARRAY == rb_type(found)) {
|
164
|
-
if (
|
165
|
-
|
210
|
+
if (check_marked && marked(pi, found)) {
|
211
|
+
unmark(pi, found);
|
166
212
|
a = rb_ary_new();
|
167
213
|
rb_ary_push(a, found);
|
168
214
|
rb_ary_push(a, e->obj);
|
@@ -171,16 +217,16 @@ end_element_core(PInfo pi, const char *ename, bool check_taint) {
|
|
171
217
|
rb_ary_push(found, e->obj);
|
172
218
|
}
|
173
219
|
} else { // something there other than an array
|
174
|
-
if (
|
175
|
-
|
220
|
+
if (check_marked && marked(pi, e->obj)) {
|
221
|
+
unmark(pi, e->obj);
|
176
222
|
}
|
177
223
|
a = rb_ary_new();
|
178
224
|
rb_ary_push(a, found);
|
179
225
|
rb_ary_push(a, e->obj);
|
180
226
|
rb_hash_aset(pobj, key, a);
|
181
227
|
}
|
182
|
-
if (
|
183
|
-
rb_hash_foreach(e->obj,
|
228
|
+
if (check_marked && NULL != pi->marked && RUBY_T_HASH == rb_type(e->obj)) {
|
229
|
+
rb_hash_foreach(e->obj, umark_hash_cb, (VALUE)pi);
|
184
230
|
}
|
185
231
|
}
|
186
232
|
|
@@ -196,9 +242,7 @@ end_element_no_attrs(PInfo pi, const char *ename) {
|
|
196
242
|
|
197
243
|
static void
|
198
244
|
finish(PInfo pi) {
|
199
|
-
|
200
|
-
rb_hash_foreach(pi->obj, untaint_hash_cb, Qnil);
|
201
|
-
}
|
245
|
+
xfree(pi->marked);
|
202
246
|
}
|
203
247
|
|
204
248
|
struct _parseCallbacks _ox_hash_callbacks = {
|
data/ext/ox/ox.h
CHANGED
@@ -155,7 +155,7 @@ typedef struct _options {
|
|
155
155
|
#endif
|
156
156
|
} *Options;
|
157
157
|
|
158
|
-
|
158
|
+
// parse information structure
|
159
159
|
struct _pInfo {
|
160
160
|
struct _helperStack helpers;
|
161
161
|
struct _err err;
|
@@ -167,6 +167,9 @@ struct _pInfo {
|
|
167
167
|
CircArray circ_array;
|
168
168
|
unsigned long id; // set for text types when cirs_array is set
|
169
169
|
Options options;
|
170
|
+
VALUE *marked;
|
171
|
+
int mark_size; // allocated size
|
172
|
+
int mark_cnt;
|
170
173
|
char last; // last character read, rarely set
|
171
174
|
};
|
172
175
|
|
data/ext/ox/parse.c
CHANGED
@@ -121,7 +121,7 @@ ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options
|
|
121
121
|
if (DEBUG <= options->trace) {
|
122
122
|
printf("Parsing xml:\n%s\n", xml);
|
123
123
|
}
|
124
|
-
|
124
|
+
// initialize parse info
|
125
125
|
helper_stack_init(&pi.helpers);
|
126
126
|
// Protect against GC
|
127
127
|
wrap = Data_Wrap_Struct(rb_cObject, mark_pi_cb, NULL, &pi);
|
@@ -134,8 +134,11 @@ ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options
|
|
134
134
|
pi.obj = Qnil;
|
135
135
|
pi.circ_array = 0;
|
136
136
|
pi.options = options;
|
137
|
+
pi.marked = NULL;
|
138
|
+
pi.mark_size = 0;
|
139
|
+
pi.mark_cnt = 0;
|
137
140
|
while (1) {
|
138
|
-
next_non_white(&pi);
|
141
|
+
next_non_white(&pi); // skip white space
|
139
142
|
if ('\0' == *pi.s) {
|
140
143
|
break;
|
141
144
|
}
|
@@ -143,31 +146,31 @@ ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options
|
|
143
146
|
*endp = pi.s;
|
144
147
|
break;
|
145
148
|
}
|
146
|
-
if ('<' != *pi.s) {
|
149
|
+
if ('<' != *pi.s) { // all top level entities start with <
|
147
150
|
set_error(err, "invalid format, expected <", pi.str, pi.s);
|
148
151
|
helper_stack_cleanup(&pi.helpers);
|
149
152
|
return Qnil;
|
150
153
|
}
|
151
|
-
pi.s++;
|
154
|
+
pi.s++; // past <
|
152
155
|
switch (*pi.s) {
|
153
|
-
case '?':
|
156
|
+
case '?': // processing instruction
|
154
157
|
pi.s++;
|
155
158
|
read_instruction(&pi);
|
156
159
|
break;
|
157
|
-
case '!':
|
160
|
+
case '!': // comment or doctype
|
158
161
|
pi.s++;
|
159
162
|
if ('\0' == *pi.s) {
|
160
163
|
set_error(err, "invalid format, DOCTYPE or comment not terminated", pi.str, pi.s);
|
161
164
|
helper_stack_cleanup(&pi.helpers);
|
162
165
|
return Qnil;
|
163
166
|
} else if ('-' == *pi.s) {
|
164
|
-
pi.s++;
|
167
|
+
pi.s++; // skip -
|
165
168
|
if ('-' != *pi.s) {
|
166
169
|
set_error(err, "invalid format, bad comment format", pi.str, pi.s);
|
167
170
|
helper_stack_cleanup(&pi.helpers);
|
168
171
|
return Qnil;
|
169
172
|
} else {
|
170
|
-
pi.s++;
|
173
|
+
pi.s++; // skip second -
|
171
174
|
read_comment(&pi);
|
172
175
|
}
|
173
176
|
} else if ((TolerantEffort == options->effort) ? 0 == strncasecmp("DOCTYPE", pi.s, 7) : 0 == strncmp("DOCTYPE", pi.s, 7)) {
|
@@ -229,8 +232,7 @@ gather_content(const char *src, char *content, size_t len) {
|
|
229
232
|
return 0;
|
230
233
|
}
|
231
234
|
|
232
|
-
|
233
|
-
*/
|
235
|
+
// Entered after the "<?" sequence. Ready to read the rest.
|
234
236
|
static void
|
235
237
|
read_instruction(PInfo pi) {
|
236
238
|
char content[1024];
|
@@ -255,7 +257,7 @@ read_instruction(PInfo pi) {
|
|
255
257
|
}
|
256
258
|
next_non_white(pi);
|
257
259
|
c = *pi->s;
|
258
|
-
*end = '\0';
|
260
|
+
*end = '\0'; // terminate name
|
259
261
|
if ('?' != c) {
|
260
262
|
while ('?' != c) {
|
261
263
|
pi->last = 0;
|
@@ -275,8 +277,8 @@ read_instruction(PInfo pi) {
|
|
275
277
|
attrs_ok = 0;
|
276
278
|
break;
|
277
279
|
}
|
278
|
-
*end = '\0';
|
279
|
-
|
280
|
+
*end = '\0'; // terminate name
|
281
|
+
// read value
|
280
282
|
next_non_white(pi);
|
281
283
|
if (0 == (attr_value = read_quoted_value(pi))) {
|
282
284
|
attr_stack_cleanup(&attrs);
|
@@ -355,9 +357,8 @@ read_delimited(PInfo pi, char end) {
|
|
355
357
|
}
|
356
358
|
}
|
357
359
|
|
358
|
-
|
359
|
-
|
360
|
-
*/
|
360
|
+
// Entered after the "<!DOCTYPE" sequence plus the first character after
|
361
|
+
// that. Ready to read the rest.
|
361
362
|
static void
|
362
363
|
read_doctype(PInfo pi) {
|
363
364
|
char *docType;
|
@@ -376,8 +377,7 @@ read_doctype(PInfo pi) {
|
|
376
377
|
}
|
377
378
|
}
|
378
379
|
|
379
|
-
|
380
|
-
*/
|
380
|
+
// Entered after "<!--". Returns error code.
|
381
381
|
static void
|
382
382
|
read_comment(PInfo pi) {
|
383
383
|
char *end;
|
@@ -406,16 +406,15 @@ read_comment(PInfo pi) {
|
|
406
406
|
break;
|
407
407
|
}
|
408
408
|
}
|
409
|
-
*end = '\0';
|
409
|
+
*end = '\0'; // in case the comment was blank
|
410
410
|
pi->s = end + 3;
|
411
411
|
if (0 != pi->pcb->add_comment) {
|
412
412
|
pi->pcb->add_comment(pi, comment);
|
413
413
|
}
|
414
414
|
}
|
415
415
|
|
416
|
-
|
417
|
-
|
418
|
-
*/
|
416
|
+
// Entered after the '<' and the first character after that. Returns stat
|
417
|
+
// code.
|
419
418
|
static char*
|
420
419
|
read_element(PInfo pi) {
|
421
420
|
struct _attrStack attrs;
|
@@ -439,7 +438,7 @@ read_element(PInfo pi) {
|
|
439
438
|
c = *pi->s;
|
440
439
|
*end = '\0';
|
441
440
|
if ('/' == c) {
|
442
|
-
|
441
|
+
// empty element, no attributes and no children
|
443
442
|
pi->s++;
|
444
443
|
if ('>' != *pi->s) {
|
445
444
|
/*printf("*** '%s' ***\n", pi->s); */
|
data/ext/ox/sax.c
CHANGED
@@ -55,7 +55,7 @@ static char read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml,
|
|
55
55
|
static char read_name_token(SaxDrive dr);
|
56
56
|
static char read_quoted_value(SaxDrive dr);
|
57
57
|
|
58
|
-
static void end_element_cb(SaxDrive dr, VALUE name,
|
58
|
+
static void end_element_cb(SaxDrive dr, VALUE name, long pos, long line, long col, Hint h);
|
59
59
|
|
60
60
|
static void hint_clear_empty(SaxDrive dr);
|
61
61
|
static Nv hint_try_close(SaxDrive dr, const char *name);
|
@@ -221,7 +221,7 @@ ox_sax_drive_cleanup(SaxDrive dr) {
|
|
221
221
|
}
|
222
222
|
|
223
223
|
static void
|
224
|
-
ox_sax_drive_error_at(SaxDrive dr, const char *msg,
|
224
|
+
ox_sax_drive_error_at(SaxDrive dr, const char *msg, off_t pos, off_t line, off_t col) {
|
225
225
|
if (dr->has.error) {
|
226
226
|
VALUE args[3];
|
227
227
|
|
@@ -301,11 +301,11 @@ parse(SaxDrive dr) {
|
|
301
301
|
}
|
302
302
|
c = read_comment(dr);
|
303
303
|
} else {
|
304
|
-
int
|
305
|
-
int
|
306
|
-
|
307
|
-
|
308
|
-
|
304
|
+
int i;
|
305
|
+
int spaced = 0;
|
306
|
+
off_t pos = dr->buf.pos + 1;
|
307
|
+
off_t line = dr->buf.line;
|
308
|
+
off_t col = dr->buf.col + 1;
|
309
309
|
|
310
310
|
if (is_white(c)) {
|
311
311
|
spaced = 1;
|
@@ -359,9 +359,9 @@ parse(SaxDrive dr) {
|
|
359
359
|
parent = stack_peek(&dr->stack);
|
360
360
|
if (0 != parent && 0 == parent->childCnt && dr->has.text && !dr->blocked) {
|
361
361
|
VALUE args[1];
|
362
|
-
|
363
|
-
|
364
|
-
|
362
|
+
off_t pos = dr->buf.pos;
|
363
|
+
off_t line = dr->buf.line;
|
364
|
+
off_t col = dr->buf.col - 1;
|
365
365
|
|
366
366
|
args[0] = rb_str_new2("");
|
367
367
|
#if HAS_ENCODING_SUPPORT
|
@@ -479,9 +479,9 @@ read_instruction(SaxDrive dr) {
|
|
479
479
|
int coff;
|
480
480
|
VALUE target = Qnil;
|
481
481
|
int is_xml;
|
482
|
-
|
483
|
-
|
484
|
-
|
482
|
+
off_t pos = dr->buf.pos - 1;
|
483
|
+
off_t line = dr->buf.line;
|
484
|
+
off_t col = dr->buf.col - 1;
|
485
485
|
|
486
486
|
buf_protect(&dr->buf);
|
487
487
|
if ('\0' == (c = read_name_token(dr))) {
|
@@ -511,7 +511,7 @@ read_instruction(SaxDrive dr) {
|
|
511
511
|
line = dr->buf.line;
|
512
512
|
col = dr->buf.col;
|
513
513
|
read_content(dr, content, sizeof(content) - 1);
|
514
|
-
coff = dr->buf.tail - dr->buf.head;
|
514
|
+
coff = (int)(dr->buf.tail - dr->buf.head);
|
515
515
|
buf_reset(&dr->buf);
|
516
516
|
dr->err = 0;
|
517
517
|
c = read_attrs(dr, c, '?', '?', is_xml, 1, NULL);
|
@@ -523,7 +523,7 @@ read_instruction(SaxDrive dr) {
|
|
523
523
|
VALUE args[1];
|
524
524
|
|
525
525
|
if (dr->options.convert_special) {
|
526
|
-
ox_sax_collapse_special(dr, content, pos, line, col);
|
526
|
+
ox_sax_collapse_special(dr, content, (int)pos, (int)line, (int)col);
|
527
527
|
}
|
528
528
|
args[0] = rb_str_new2(content);
|
529
529
|
#if HAS_ENCODING_SUPPORT
|
@@ -627,9 +627,9 @@ read_delimited(SaxDrive dr, char end) {
|
|
627
627
|
*/
|
628
628
|
static char
|
629
629
|
read_doctype(SaxDrive dr) {
|
630
|
-
|
631
|
-
|
632
|
-
|
630
|
+
long pos = (long)(dr->buf.pos - 9);
|
631
|
+
long line = (long)(dr->buf.line);
|
632
|
+
long col = (long)(dr->buf.col - 9);
|
633
633
|
char *s;
|
634
634
|
Nv parent = stack_peek(&dr->stack);
|
635
635
|
|
@@ -673,9 +673,9 @@ read_cdata(SaxDrive dr) {
|
|
673
673
|
char c;
|
674
674
|
char zero = '\0';
|
675
675
|
int end = 0;
|
676
|
-
|
677
|
-
|
678
|
-
|
676
|
+
long pos = (long)(dr->buf.pos - 9);
|
677
|
+
long line = (long)(dr->buf.line);
|
678
|
+
long col = (long)(dr->buf.col - 9);
|
679
679
|
struct _checkPt cp = CHECK_PT_INIT;
|
680
680
|
Nv parent = stack_peek(&dr->stack);
|
681
681
|
|
@@ -768,9 +768,9 @@ read_comment(SaxDrive dr) {
|
|
768
768
|
char c;
|
769
769
|
char zero = '\0';
|
770
770
|
int end = 0;
|
771
|
-
|
772
|
-
|
773
|
-
|
771
|
+
long pos = (long)(dr->buf.pos - 4);
|
772
|
+
long line = (long)(dr->buf.line);
|
773
|
+
long col = (long)(dr->buf.col - 4);
|
774
774
|
struct _checkPt cp = CHECK_PT_INIT;
|
775
775
|
|
776
776
|
buf_backup(&dr->buf); /* back up to the start in case the cdata is empty */
|
@@ -864,9 +864,9 @@ read_element_start(SaxDrive dr) {
|
|
864
864
|
volatile VALUE name = Qnil;
|
865
865
|
char c;
|
866
866
|
int closed;
|
867
|
-
|
868
|
-
|
869
|
-
|
867
|
+
long pos = (long)(dr->buf.pos);
|
868
|
+
long line = (long)(dr->buf.line);
|
869
|
+
long col = (long)(dr->buf.col);
|
870
870
|
Hint h = NULL;
|
871
871
|
int stackless = 0;
|
872
872
|
Nv parent = stack_peek(&dr->stack);
|
@@ -1020,9 +1020,9 @@ static char
|
|
1020
1020
|
read_element_end(SaxDrive dr) {
|
1021
1021
|
VALUE name = Qnil;
|
1022
1022
|
char c;
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1023
|
+
long pos = (long)(dr->buf.pos - 1);
|
1024
|
+
long line = (long)(dr->buf.line);
|
1025
|
+
long col = (long)(dr->buf.col - 1);
|
1026
1026
|
Nv nv;
|
1027
1027
|
Hint h = NULL;
|
1028
1028
|
|
@@ -1118,9 +1118,9 @@ static char
|
|
1118
1118
|
read_text(SaxDrive dr) {
|
1119
1119
|
VALUE args[1];
|
1120
1120
|
char c;
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1121
|
+
long pos = (long)(dr->buf.pos);
|
1122
|
+
long line = (long)(dr->buf.line);
|
1123
|
+
long col = (long)(dr->buf.col - 1);
|
1124
1124
|
Nv parent = stack_peek(&dr->stack);
|
1125
1125
|
int allWhite = 1;
|
1126
1126
|
|
@@ -1266,9 +1266,9 @@ static char
|
|
1266
1266
|
read_jump(SaxDrive dr, const char *pat) {
|
1267
1267
|
VALUE args[1];
|
1268
1268
|
char c;
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1269
|
+
long pos = (long)(dr->buf.pos);
|
1270
|
+
long line = (long)(dr->buf.line);
|
1271
|
+
long col = (long)(dr->buf.col - 1);
|
1272
1272
|
Nv parent = stack_peek(&dr->stack);
|
1273
1273
|
|
1274
1274
|
buf_protect(&dr->buf);
|
@@ -1330,9 +1330,9 @@ static char
|
|
1330
1330
|
read_attrs(SaxDrive dr, char c, char termc, char term2, int is_xml, int eq_req, Hint h) {
|
1331
1331
|
VALUE name = Qnil;
|
1332
1332
|
int is_encoding = 0;
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1333
|
+
off_t pos;
|
1334
|
+
off_t line;
|
1335
|
+
off_t col;
|
1336
1336
|
char *attr_value;
|
1337
1337
|
|
1338
1338
|
// already protected by caller
|
@@ -1580,7 +1580,7 @@ read_10_uint64(char *b, uint64_t *up) {
|
|
1580
1580
|
}
|
1581
1581
|
|
1582
1582
|
int
|
1583
|
-
ox_sax_collapse_special(SaxDrive dr, char *str,
|
1583
|
+
ox_sax_collapse_special(SaxDrive dr, char *str, long pos, long line, long col) {
|
1584
1584
|
char *s = str;
|
1585
1585
|
char *b = str;
|
1586
1586
|
|
@@ -1731,7 +1731,7 @@ hint_try_close(SaxDrive dr, const char *name) {
|
|
1731
1731
|
}
|
1732
1732
|
|
1733
1733
|
static void
|
1734
|
-
end_element_cb(SaxDrive dr, VALUE name,
|
1734
|
+
end_element_cb(SaxDrive dr, VALUE name, long pos, long line, long col, Hint h) {
|
1735
1735
|
if (dr->has.end_element && 0 >= dr->blocked && (NULL == h || ActiveOverlay == h->overlay || NestOverlay == h->overlay)) {
|
1736
1736
|
if (dr->has.pos) {
|
1737
1737
|
rb_ivar_set(dr->handler, ox_at_pos_id, LONG2NUM(pos));
|
data/ext/ox/sax.h
CHANGED
@@ -46,7 +46,7 @@ extern void ox_collapse_return(char *str);
|
|
46
46
|
extern void ox_sax_parse(VALUE handler, VALUE io, SaxOptions options);
|
47
47
|
extern void ox_sax_drive_cleanup(SaxDrive dr);
|
48
48
|
extern void ox_sax_drive_error(SaxDrive dr, const char *msg);
|
49
|
-
extern int ox_sax_collapse_special(SaxDrive dr, char *str,
|
49
|
+
extern int ox_sax_collapse_special(SaxDrive dr, char *str, long pos, long line, long col);
|
50
50
|
|
51
51
|
extern VALUE ox_sax_value_class;
|
52
52
|
|
data/lib/ox/version.rb
CHANGED
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.12.
|
4
|
+
version: 2.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Ohler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: "A fast XML parser and object serializer that uses only standard C lib.\n
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
description: "A fast XML parser and object serializer that uses only standard C lib.\n\nOptimized
|
14
|
+
XML (Ox), as the name implies was written to provide speed optimized\nXML handling.
|
15
|
+
It was designed to be an alternative to Nokogiri and other Ruby\nXML parsers for
|
16
|
+
generic XML parsing and as an alternative to Marshal for Object\nserialization. "
|
17
17
|
email: peter@ohler.com
|
18
18
|
executables: []
|
19
19
|
extensions:
|
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '0'
|
100
100
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
101
|
+
rubygems_version: 3.1.2
|
102
102
|
signing_key:
|
103
103
|
specification_version: 4
|
104
104
|
summary: A fast XML parser and object serializer.
|