ox 2.14.4 → 2.14.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +1 -1
- data/ext/ox/builder.c +8 -8
- data/ext/ox/cache.c +309 -131
- data/ext/ox/cache.h +10 -10
- data/ext/ox/dump.c +2 -2
- data/ext/ox/extconf.rb +5 -2
- data/ext/ox/gen_load.c +5 -73
- data/ext/ox/hash_load.c +0 -4
- data/ext/ox/intern.c +153 -0
- data/ext/ox/intern.h +25 -0
- data/ext/ox/obj_load.c +14 -86
- data/ext/ox/ox.c +1018 -935
- data/ext/ox/ox.h +186 -210
- data/ext/ox/parse.c +72 -31
- data/ext/ox/sax.c +1093 -1279
- data/ext/ox/sax.h +45 -31
- data/ext/ox/sax_as.c +3 -5
- data/ext/ox/sax_buf.c +7 -16
- data/ext/ox/slotcache.c +158 -0
- data/ext/ox/slotcache.h +19 -0
- data/lib/ox/version.rb +1 -1
- metadata +11 -5
- data/ext/ox/sax_has.h +0 -53
data/ext/ox/sax.h
CHANGED
@@ -8,46 +8,60 @@
|
|
8
8
|
|
9
9
|
#include <stdbool.h>
|
10
10
|
|
11
|
+
#include "ox.h"
|
11
12
|
#include "sax_buf.h"
|
12
|
-
#include "sax_has.h"
|
13
|
-
#include "sax_stack.h"
|
14
13
|
#include "sax_hint.h"
|
15
|
-
#include "
|
14
|
+
#include "sax_stack.h"
|
16
15
|
|
17
16
|
typedef struct _saxOptions {
|
18
|
-
int
|
19
|
-
int
|
20
|
-
int
|
21
|
-
SkipMode
|
22
|
-
char
|
23
|
-
Hints
|
24
|
-
} *SaxOptions;
|
17
|
+
int symbolize;
|
18
|
+
int convert_special;
|
19
|
+
int smart;
|
20
|
+
SkipMode skip;
|
21
|
+
char strip_ns[64];
|
22
|
+
Hints hints;
|
23
|
+
} * SaxOptions;
|
25
24
|
|
26
25
|
typedef struct _saxDrive {
|
27
|
-
struct _buf
|
28
|
-
struct _nStack
|
29
|
-
VALUE
|
30
|
-
VALUE
|
31
|
-
struct _saxOptions
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
26
|
+
struct _buf buf;
|
27
|
+
struct _nStack stack; /* element name stack */
|
28
|
+
VALUE handler;
|
29
|
+
VALUE value_obj;
|
30
|
+
struct _saxOptions options;
|
31
|
+
VALUE (*get_name)(const char *name, size_t len, rb_encoding *encoding, const char **namep);
|
32
|
+
void (*set_pos)(VALUE handler, long pos);
|
33
|
+
void (*set_line)(VALUE handler, long line);
|
34
|
+
void (*set_col)(VALUE handler, long col);
|
35
|
+
void (*attr_cb)(struct _saxDrive *dr, VALUE name, char *value, long pos, long line, long col);
|
36
|
+
void (*attrs_done)(VALUE handler);
|
37
|
+
VALUE (*instruct)(struct _saxDrive *dr, const char *target, long pos, long line, long col);
|
38
|
+
void (*end_instruct)(struct _saxDrive *dr, VALUE target, long pos, long line, long col);
|
39
|
+
void (*doctype)(struct _saxDrive *dr, long pos, long line, long col);
|
40
|
+
void (*comment)(struct _saxDrive *dr, long pos, long line, long col);
|
41
|
+
void (*cdata)(struct _saxDrive *dr, long pos, long line, long col);
|
42
|
+
void (*error)(struct _saxDrive *dr, const char *msg, long pos, long line, long col);
|
43
|
+
|
37
44
|
rb_encoding *encoding;
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
int err;
|
46
|
+
int blocked;
|
47
|
+
bool abort;
|
48
|
+
bool utf8;
|
49
|
+
bool want_attr_name;
|
50
|
+
bool has_text;
|
51
|
+
bool has_value;
|
52
|
+
bool has_start_element;
|
53
|
+
bool has_end_element;
|
54
|
+
|
55
|
+
} * SaxDrive;
|
42
56
|
|
43
|
-
extern void
|
44
|
-
extern void
|
45
|
-
extern void
|
46
|
-
extern void
|
47
|
-
extern int
|
57
|
+
extern void ox_collapse_return(char *str);
|
58
|
+
extern void ox_sax_parse(VALUE handler, VALUE io, SaxOptions options);
|
59
|
+
extern void ox_sax_drive_cleanup(SaxDrive dr);
|
60
|
+
extern void ox_sax_drive_error(SaxDrive dr, const char *msg);
|
61
|
+
extern int ox_sax_collapse_special(SaxDrive dr, char *str, long pos, long line, long col);
|
48
62
|
|
49
|
-
extern VALUE
|
63
|
+
extern VALUE ox_sax_value_class;
|
50
64
|
|
51
|
-
extern VALUE
|
65
|
+
extern VALUE str2sym(SaxDrive dr, const char *str, size_t len, const char **strp);
|
52
66
|
|
53
67
|
#endif /* OX_SAX_H */
|
data/ext/ox/sax_as.c
CHANGED
@@ -43,7 +43,7 @@ parse_double_time(const char *text) {
|
|
43
43
|
for (; text - dot <= 9; text++) {
|
44
44
|
v2 *= 10;
|
45
45
|
}
|
46
|
-
#if
|
46
|
+
#if HAVE_RB_TIME_NANO_NEW
|
47
47
|
return rb_time_nano_new(v, v2);
|
48
48
|
#else
|
49
49
|
return rb_time_new(v, v2 / 1000);
|
@@ -103,7 +103,7 @@ parse_xsd_time(const char *text) {
|
|
103
103
|
tm.tm_hour = (int)cargs[3];
|
104
104
|
tm.tm_min = (int)cargs[4];
|
105
105
|
tm.tm_sec = (int)cargs[5];
|
106
|
-
#if
|
106
|
+
#if HAVE_RB_TIME_NANO_NEW
|
107
107
|
return rb_time_nano_new(mktime(&tm), cargs[6]);
|
108
108
|
#else
|
109
109
|
return rb_time_new(mktime(&tm), cargs[6] / 1000);
|
@@ -136,11 +136,9 @@ sax_value_as_s(VALUE self) {
|
|
136
136
|
break;
|
137
137
|
}
|
138
138
|
rs = rb_str_new2(dr->buf.str);
|
139
|
-
#if HAVE_RB_ENC_ASSOCIATE
|
140
139
|
if (0 != dr->encoding) {
|
141
140
|
rb_enc_associate(rs, dr->encoding);
|
142
141
|
}
|
143
|
-
#endif
|
144
142
|
return rs;
|
145
143
|
}
|
146
144
|
|
@@ -155,7 +153,7 @@ sax_value_as_sym(VALUE self) {
|
|
155
153
|
if ('\0' == *dr->buf.str) {
|
156
154
|
return Qnil;
|
157
155
|
}
|
158
|
-
return str2sym(dr, dr->buf.str, 0);
|
156
|
+
return str2sym(dr, dr->buf.str, strlen(dr->buf.str), 0);
|
159
157
|
}
|
160
158
|
|
161
159
|
/* call-seq: as_f()
|
data/ext/ox/sax_buf.c
CHANGED
@@ -194,30 +194,21 @@ read_from_fd(Buf buf) {
|
|
194
194
|
return 0;
|
195
195
|
}
|
196
196
|
|
197
|
-
static char*
|
198
|
-
ox_stpncpy(char *dest, const char *src, size_t n) {
|
199
|
-
size_t cnt = strlen(src) + 1;
|
200
|
-
|
201
|
-
if (n < cnt) {
|
202
|
-
cnt = n;
|
203
|
-
}
|
204
|
-
strncpy(dest, src, cnt);
|
205
|
-
|
206
|
-
return dest + cnt - 1;
|
207
|
-
}
|
208
|
-
|
209
|
-
|
210
197
|
static int
|
211
198
|
read_from_str(Buf buf) {
|
212
199
|
size_t max = buf->end - buf->tail - 1;
|
213
200
|
char *s;
|
214
|
-
|
201
|
+
size_t cnt;
|
215
202
|
|
216
203
|
if ('\0' == *buf->in.str) {
|
217
|
-
/* done */
|
218
204
|
return -1;
|
219
205
|
}
|
220
|
-
|
206
|
+
cnt = strlen(buf->in.str) + 1;
|
207
|
+
if (max < cnt) {
|
208
|
+
cnt = max;
|
209
|
+
}
|
210
|
+
strncpy(buf->tail, buf->in.str, cnt);
|
211
|
+
s = buf->tail + cnt - 1;
|
221
212
|
*s = '\0';
|
222
213
|
cnt = s - buf->tail;
|
223
214
|
buf->in.str += cnt;
|
data/ext/ox/slotcache.c
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
/* slotcache.c
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "slotcache.h"
|
7
|
+
|
8
|
+
#include <errno.h>
|
9
|
+
#include <stdarg.h>
|
10
|
+
#include <stdint.h>
|
11
|
+
#include <stdio.h>
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include <string.h>
|
14
|
+
#include <strings.h>
|
15
|
+
|
16
|
+
struct _slotCache {
|
17
|
+
/* The key is a length byte followed by the key as a string. If the key is longer than 254 characters then the
|
18
|
+
length is 255. The key can be for a premature value and in that case the length byte is greater than the length
|
19
|
+
of the key. */
|
20
|
+
char *key;
|
21
|
+
VALUE value;
|
22
|
+
struct _slotCache *slots[16];
|
23
|
+
};
|
24
|
+
|
25
|
+
static void slot_print(SlotCache cache, unsigned int depth);
|
26
|
+
|
27
|
+
static char *form_key(const char *s) {
|
28
|
+
size_t len = strlen(s);
|
29
|
+
char *d = ALLOC_N(char, len + 2);
|
30
|
+
|
31
|
+
*(uint8_t *)d = (255 <= len) ? 255 : len;
|
32
|
+
memcpy(d + 1, s, len + 1);
|
33
|
+
|
34
|
+
return d;
|
35
|
+
}
|
36
|
+
|
37
|
+
void slot_cache_new(SlotCache *cache) {
|
38
|
+
*cache = ALLOC(struct _slotCache);
|
39
|
+
(*cache)->key = 0;
|
40
|
+
(*cache)->value = Qundef;
|
41
|
+
memset((*cache)->slots, 0, sizeof((*cache)->slots));
|
42
|
+
}
|
43
|
+
|
44
|
+
VALUE
|
45
|
+
slot_cache_get(SlotCache cache, const char *key, VALUE **slot, const char **keyp) {
|
46
|
+
unsigned char *k = (unsigned char *)key;
|
47
|
+
SlotCache *cp;
|
48
|
+
|
49
|
+
for (; '\0' != *k; k++) {
|
50
|
+
cp = cache->slots + (unsigned int)(*k >> 4); /* upper 4 bits */
|
51
|
+
if (0 == *cp) {
|
52
|
+
slot_cache_new(cp);
|
53
|
+
}
|
54
|
+
cache = *cp;
|
55
|
+
cp = cache->slots + (unsigned int)(*k & 0x0F); /* lower 4 bits */
|
56
|
+
if (0 == *cp) { /* nothing on this tree so set key and value as a premature key/value pair */
|
57
|
+
slot_cache_new(cp);
|
58
|
+
cache = *cp;
|
59
|
+
cache->key = form_key(key);
|
60
|
+
break;
|
61
|
+
} else {
|
62
|
+
int depth = (int)(k - (unsigned char *)key + 1);
|
63
|
+
|
64
|
+
cache = *cp;
|
65
|
+
|
66
|
+
if ('\0' == *(k + 1)) { /* exact match */
|
67
|
+
if (0 == cache->key) { /* nothing in this spot so take it */
|
68
|
+
cache->key = form_key(key);
|
69
|
+
break;
|
70
|
+
} else if ((depth == *cache->key || 255 < depth) && 0 == strcmp(key, cache->key + 1)) { /* match */
|
71
|
+
break;
|
72
|
+
} else { /* have to move the current premature key/value deeper */
|
73
|
+
unsigned char *ck = (unsigned char *)(cache->key + depth + 1);
|
74
|
+
SlotCache orig = *cp;
|
75
|
+
|
76
|
+
cp = (*cp)->slots + (*ck >> 4);
|
77
|
+
slot_cache_new(cp);
|
78
|
+
cp = (*cp)->slots + (*ck & 0x0F);
|
79
|
+
slot_cache_new(cp);
|
80
|
+
(*cp)->key = cache->key;
|
81
|
+
(*cp)->value = cache->value;
|
82
|
+
orig->key = form_key(key);
|
83
|
+
orig->value = Qundef;
|
84
|
+
}
|
85
|
+
} else { /* not exact match but on the path */
|
86
|
+
if (0 != cache->key) { /* there is a key/value here already */
|
87
|
+
if (depth == *cache->key || (255 <= depth && 0 == strncmp(cache->key, key, depth) &&
|
88
|
+
'\0' == cache->key[depth])) { /* key belongs here */
|
89
|
+
continue;
|
90
|
+
} else {
|
91
|
+
unsigned char *ck = (unsigned char *)(cache->key + depth + 1);
|
92
|
+
SlotCache orig = *cp;
|
93
|
+
|
94
|
+
cp = (*cp)->slots + (*ck >> 4);
|
95
|
+
slot_cache_new(cp);
|
96
|
+
cp = (*cp)->slots + (*ck & 0x0F);
|
97
|
+
slot_cache_new(cp);
|
98
|
+
(*cp)->key = cache->key;
|
99
|
+
(*cp)->value = cache->value;
|
100
|
+
orig->key = 0;
|
101
|
+
orig->value = Qundef;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
*slot = &cache->value;
|
108
|
+
if (0 != keyp) {
|
109
|
+
if (0 == cache->key) {
|
110
|
+
printf("*** Error: failed to set the key for '%s'\n", key);
|
111
|
+
*keyp = 0;
|
112
|
+
} else {
|
113
|
+
*keyp = cache->key + 1;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
return cache->value;
|
117
|
+
}
|
118
|
+
|
119
|
+
void slot_cache_print(SlotCache cache) {
|
120
|
+
/*printf("-------------------------------------------\n");*/
|
121
|
+
slot_print(cache, 0);
|
122
|
+
}
|
123
|
+
|
124
|
+
static void slot_print(SlotCache c, unsigned int depth) {
|
125
|
+
char indent[256];
|
126
|
+
SlotCache *cp;
|
127
|
+
unsigned int i;
|
128
|
+
|
129
|
+
if (sizeof(indent) - 1 < depth) {
|
130
|
+
depth = ((int)sizeof(indent) - 1);
|
131
|
+
}
|
132
|
+
memset(indent, ' ', depth);
|
133
|
+
indent[depth] = '\0';
|
134
|
+
for (i = 0, cp = c->slots; i < 16; i++, cp++) {
|
135
|
+
if (0 == *cp) {
|
136
|
+
/*printf("%s%02u:\n", indent, i);*/
|
137
|
+
} else {
|
138
|
+
if (0 == (*cp)->key && Qundef == (*cp)->value) {
|
139
|
+
printf("%s%02u:\n", indent, i);
|
140
|
+
} else {
|
141
|
+
const char *vs;
|
142
|
+
const char *clas;
|
143
|
+
|
144
|
+
if (Qundef == (*cp)->value) {
|
145
|
+
vs = "undefined";
|
146
|
+
clas = "";
|
147
|
+
} else {
|
148
|
+
VALUE rs = rb_funcall2((*cp)->value, rb_intern("to_s"), 0, 0);
|
149
|
+
|
150
|
+
vs = StringValuePtr(rs);
|
151
|
+
clas = rb_class2name(rb_obj_class((*cp)->value));
|
152
|
+
}
|
153
|
+
printf("%s%02u: %s = %s (%s)\n", indent, i, (*cp)->key, vs, clas);
|
154
|
+
}
|
155
|
+
slot_print(*cp, depth + 2);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
data/ext/ox/slotcache.h
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
/* slotcache.h
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
3
|
+
* All rights reserved.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#ifndef SLOT_CACHE_H
|
7
|
+
#define SLOT_CACHE_H
|
8
|
+
|
9
|
+
#include "ruby.h"
|
10
|
+
|
11
|
+
typedef struct _slotCache *SlotCache;
|
12
|
+
|
13
|
+
extern void slot_cache_new(SlotCache *cache);
|
14
|
+
|
15
|
+
extern VALUE slot_cache_get(SlotCache cache, const char *key, VALUE **slot, const char **keyp);
|
16
|
+
|
17
|
+
extern void slot_cache_print(SlotCache cache);
|
18
|
+
|
19
|
+
#endif /* SLOT_CACHE_H */
|
data/lib/ox/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.8
|
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: 2022-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: "A fast XML parser and object serializer that uses only standard C lib.\n\nOptimized
|
14
14
|
XML (Ox), as the name implies was written to provide speed optimized\nXML handling.
|
@@ -41,6 +41,8 @@ files:
|
|
41
41
|
- ext/ox/gen_load.c
|
42
42
|
- ext/ox/hash_load.c
|
43
43
|
- ext/ox/helper.h
|
44
|
+
- ext/ox/intern.c
|
45
|
+
- ext/ox/intern.h
|
44
46
|
- ext/ox/obj_load.c
|
45
47
|
- ext/ox/ox.c
|
46
48
|
- ext/ox/ox.h
|
@@ -50,10 +52,11 @@ files:
|
|
50
52
|
- ext/ox/sax_as.c
|
51
53
|
- ext/ox/sax_buf.c
|
52
54
|
- ext/ox/sax_buf.h
|
53
|
-
- ext/ox/sax_has.h
|
54
55
|
- ext/ox/sax_hint.c
|
55
56
|
- ext/ox/sax_hint.h
|
56
57
|
- ext/ox/sax_stack.h
|
58
|
+
- ext/ox/slotcache.c
|
59
|
+
- ext/ox/slotcache.h
|
57
60
|
- ext/ox/special.c
|
58
61
|
- ext/ox/special.h
|
59
62
|
- ext/ox/type.h
|
@@ -81,9 +84,12 @@ rdoc_options:
|
|
81
84
|
- "--main"
|
82
85
|
- README.md
|
83
86
|
- "--title"
|
84
|
-
- Ox
|
87
|
+
- Ox
|
85
88
|
- "--exclude"
|
86
89
|
- extconf.rb
|
90
|
+
- lib
|
91
|
+
- ext/ox
|
92
|
+
- README.md
|
87
93
|
require_paths:
|
88
94
|
- lib
|
89
95
|
- ext
|
@@ -98,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
104
|
- !ruby/object:Gem::Version
|
99
105
|
version: '0'
|
100
106
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
107
|
+
rubygems_version: 3.3.3
|
102
108
|
signing_key:
|
103
109
|
specification_version: 4
|
104
110
|
summary: A fast XML parser and object serializer.
|
data/ext/ox/sax_has.h
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
/* sax_has.h
|
2
|
-
* Copyright (c) 2011, Peter Ohler
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#ifndef OX_SAX_HAS_H
|
7
|
-
#define OX_SAX_HAS_H
|
8
|
-
|
9
|
-
typedef struct _has {
|
10
|
-
int instruct;
|
11
|
-
int end_instruct;
|
12
|
-
int attr;
|
13
|
-
int attrs_done;
|
14
|
-
int attr_value;
|
15
|
-
int doctype;
|
16
|
-
int comment;
|
17
|
-
int cdata;
|
18
|
-
int text;
|
19
|
-
int value;
|
20
|
-
int start_element;
|
21
|
-
int end_element;
|
22
|
-
int error;
|
23
|
-
int pos;
|
24
|
-
int line;
|
25
|
-
int column;
|
26
|
-
} *Has;
|
27
|
-
|
28
|
-
inline static int
|
29
|
-
respond_to(VALUE obj, ID method) {
|
30
|
-
return rb_respond_to(obj, method);
|
31
|
-
}
|
32
|
-
|
33
|
-
inline static void
|
34
|
-
has_init(Has has, VALUE handler) {
|
35
|
-
has->instruct = respond_to(handler, ox_instruct_id);
|
36
|
-
has->end_instruct = respond_to(handler, ox_end_instruct_id);
|
37
|
-
has->attr = respond_to(handler, ox_attr_id);
|
38
|
-
has->attr_value = respond_to(handler, ox_attr_value_id);
|
39
|
-
has->attrs_done = respond_to(handler, ox_attrs_done_id);
|
40
|
-
has->doctype = respond_to(handler, ox_doctype_id);
|
41
|
-
has->comment = respond_to(handler, ox_comment_id);
|
42
|
-
has->cdata = respond_to(handler, ox_cdata_id);
|
43
|
-
has->text = respond_to(handler, ox_text_id);
|
44
|
-
has->value = respond_to(handler, ox_value_id);
|
45
|
-
has->start_element = respond_to(handler, ox_start_element_id);
|
46
|
-
has->end_element = respond_to(handler, ox_end_element_id);
|
47
|
-
has->error = respond_to(handler, ox_error_id);
|
48
|
-
has->pos = (Qtrue == rb_ivar_defined(handler, ox_at_pos_id));
|
49
|
-
has->line = (Qtrue == rb_ivar_defined(handler, ox_at_line_id));
|
50
|
-
has->column = (Qtrue == rb_ivar_defined(handler, ox_at_column_id));
|
51
|
-
}
|
52
|
-
|
53
|
-
#endif /* OX_SAX_HAS_H */
|