ox 2.12.0 → 2.12.1
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 +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.
|