ox 2.14.4 → 2.14.8
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 +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 */
|