json 2.13.2 → 3.0.0
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/CHANGES.md +208 -8
- data/LEGAL +12 -0
- data/README.md +34 -87
- data/ext/json/ext/fbuffer/fbuffer.h +75 -86
- data/ext/json/ext/generator/extconf.rb +4 -1
- data/ext/json/ext/generator/generator.c +494 -596
- data/ext/json/ext/json.h +196 -0
- data/ext/json/ext/parser/extconf.rb +29 -1
- data/ext/json/ext/parser/parser.c +2091 -723
- data/ext/json/ext/simd/simd.h +42 -22
- data/ext/json/ext/vendor/fast_float_parser.h +814 -0
- data/ext/json/ext/vendor/fpconv.c +13 -12
- data/lib/json/common.rb +199 -389
- data/lib/json/ext/generator/state.rb +8 -37
- data/lib/json/ext.rb +25 -1
- data/lib/json/truffle_ruby/generator.rb +186 -128
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +84 -252
- metadata +5 -18
- data/lib/json/add/bigdecimal.rb +0 -58
- data/lib/json/add/complex.rb +0 -51
- data/lib/json/add/core.rb +0 -12
- data/lib/json/add/date.rb +0 -54
- data/lib/json/add/date_time.rb +0 -67
- data/lib/json/add/exception.rb +0 -49
- data/lib/json/add/ostruct.rb +0 -54
- data/lib/json/add/range.rb +0 -54
- data/lib/json/add/rational.rb +0 -49
- data/lib/json/add/regexp.rb +0 -48
- data/lib/json/add/set.rb +0 -48
- data/lib/json/add/struct.rb +0 -52
- data/lib/json/add/symbol.rb +0 -52
- data/lib/json/add/time.rb +0 -52
- data/lib/json/generic_object.rb +0 -75
|
@@ -1,47 +1,9 @@
|
|
|
1
1
|
#ifndef _FBUFFER_H_
|
|
2
2
|
#define _FBUFFER_H_
|
|
3
3
|
|
|
4
|
-
#include "
|
|
5
|
-
#include "ruby/encoding.h"
|
|
4
|
+
#include "../json.h"
|
|
6
5
|
#include "../vendor/jeaiii-ltoa.h"
|
|
7
6
|
|
|
8
|
-
/* shims */
|
|
9
|
-
/* This is the fallback definition from Ruby 3.4 */
|
|
10
|
-
|
|
11
|
-
#ifndef RBIMPL_STDBOOL_H
|
|
12
|
-
#if defined(__cplusplus)
|
|
13
|
-
# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
|
|
14
|
-
# include <cstdbool>
|
|
15
|
-
# endif
|
|
16
|
-
#elif defined(HAVE_STDBOOL_H)
|
|
17
|
-
# include <stdbool.h>
|
|
18
|
-
#elif !defined(HAVE__BOOL)
|
|
19
|
-
typedef unsigned char _Bool;
|
|
20
|
-
# define bool _Bool
|
|
21
|
-
# define true ((_Bool)+1)
|
|
22
|
-
# define false ((_Bool)+0)
|
|
23
|
-
# define __bool_true_false_are_defined
|
|
24
|
-
#endif
|
|
25
|
-
#endif
|
|
26
|
-
|
|
27
|
-
#ifndef RB_UNLIKELY
|
|
28
|
-
#define RB_UNLIKELY(expr) expr
|
|
29
|
-
#endif
|
|
30
|
-
|
|
31
|
-
#ifndef RB_LIKELY
|
|
32
|
-
#define RB_LIKELY(expr) expr
|
|
33
|
-
#endif
|
|
34
|
-
|
|
35
|
-
#ifndef MAYBE_UNUSED
|
|
36
|
-
# define MAYBE_UNUSED(x) x
|
|
37
|
-
#endif
|
|
38
|
-
|
|
39
|
-
#ifdef RUBY_DEBUG
|
|
40
|
-
#ifndef JSON_DEBUG
|
|
41
|
-
#define JSON_DEBUG RUBY_DEBUG
|
|
42
|
-
#endif
|
|
43
|
-
#endif
|
|
44
|
-
|
|
45
7
|
enum fbuffer_type {
|
|
46
8
|
FBUFFER_HEAP_ALLOCATED = 0,
|
|
47
9
|
FBUFFER_STACK_ALLOCATED = 1,
|
|
@@ -49,11 +11,11 @@ enum fbuffer_type {
|
|
|
49
11
|
|
|
50
12
|
typedef struct FBufferStruct {
|
|
51
13
|
enum fbuffer_type type;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
#
|
|
56
|
-
|
|
14
|
+
size_t initial_length;
|
|
15
|
+
size_t len;
|
|
16
|
+
size_t capa;
|
|
17
|
+
#if JSON_DEBUG
|
|
18
|
+
size_t requested;
|
|
57
19
|
#endif
|
|
58
20
|
char *ptr;
|
|
59
21
|
VALUE io;
|
|
@@ -70,27 +32,31 @@ typedef struct FBufferStruct {
|
|
|
70
32
|
|
|
71
33
|
static void fbuffer_free(FBuffer *fb);
|
|
72
34
|
static void fbuffer_clear(FBuffer *fb);
|
|
73
|
-
static void fbuffer_append(FBuffer *fb, const char *newstr,
|
|
35
|
+
static void fbuffer_append(FBuffer *fb, const char *newstr, size_t len);
|
|
74
36
|
static void fbuffer_append_long(FBuffer *fb, long number);
|
|
75
37
|
static inline void fbuffer_append_char(FBuffer *fb, char newchr);
|
|
76
38
|
static VALUE fbuffer_finalize(FBuffer *fb);
|
|
77
39
|
|
|
78
|
-
static void
|
|
40
|
+
static void fbuffer_init(FBuffer *fb, size_t initial_length, VALUE io, char *stack_buffer, size_t stack_buffer_size)
|
|
79
41
|
{
|
|
80
|
-
|
|
81
|
-
|
|
42
|
+
if (RTEST(io)) {
|
|
43
|
+
JSON_ASSERT(fb->type == FBUFFER_HEAP_ALLOCATED);
|
|
44
|
+
fb->io = io;
|
|
45
|
+
fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_IO_BUFFER_SIZE;
|
|
46
|
+
} else {
|
|
82
47
|
fb->type = FBUFFER_STACK_ALLOCATED;
|
|
83
48
|
fb->ptr = stack_buffer;
|
|
84
49
|
fb->capa = stack_buffer_size;
|
|
50
|
+
fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
|
|
85
51
|
}
|
|
86
|
-
#
|
|
52
|
+
#if JSON_DEBUG
|
|
87
53
|
fb->requested = 0;
|
|
88
54
|
#endif
|
|
89
55
|
}
|
|
90
56
|
|
|
91
|
-
static inline void fbuffer_consumed(FBuffer *fb,
|
|
57
|
+
static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
|
|
92
58
|
{
|
|
93
|
-
#
|
|
59
|
+
#if JSON_DEBUG
|
|
94
60
|
if (consumed > fb->requested) {
|
|
95
61
|
rb_bug("fbuffer: Out of bound write");
|
|
96
62
|
}
|
|
@@ -102,7 +68,7 @@ static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed)
|
|
|
102
68
|
static void fbuffer_free(FBuffer *fb)
|
|
103
69
|
{
|
|
104
70
|
if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
|
|
105
|
-
|
|
71
|
+
JSON_SIZED_FREE_N(fb->ptr, fb->capa);
|
|
106
72
|
}
|
|
107
73
|
}
|
|
108
74
|
|
|
@@ -117,50 +83,45 @@ static void fbuffer_flush(FBuffer *fb)
|
|
|
117
83
|
fbuffer_clear(fb);
|
|
118
84
|
}
|
|
119
85
|
|
|
120
|
-
static void fbuffer_realloc(FBuffer *fb,
|
|
86
|
+
static void fbuffer_realloc(FBuffer *fb, size_t new_capa)
|
|
121
87
|
{
|
|
122
|
-
if (
|
|
88
|
+
if (new_capa > fb->capa) {
|
|
123
89
|
if (fb->type == FBUFFER_STACK_ALLOCATED) {
|
|
124
90
|
const char *old_buffer = fb->ptr;
|
|
125
|
-
fb->ptr = ALLOC_N(char,
|
|
91
|
+
fb->ptr = ALLOC_N(char, new_capa);
|
|
126
92
|
fb->type = FBUFFER_HEAP_ALLOCATED;
|
|
127
93
|
MEMCPY(fb->ptr, old_buffer, char, fb->len);
|
|
128
94
|
} else {
|
|
129
|
-
|
|
95
|
+
JSON_SIZED_REALLOC_N(fb->ptr, char, new_capa, fb->capa);
|
|
130
96
|
}
|
|
131
|
-
fb->capa =
|
|
97
|
+
fb->capa = new_capa;
|
|
132
98
|
}
|
|
133
99
|
}
|
|
134
100
|
|
|
135
|
-
static void fbuffer_do_inc_capa(FBuffer *fb,
|
|
101
|
+
static void fbuffer_do_inc_capa(FBuffer *fb, size_t requested)
|
|
136
102
|
{
|
|
137
103
|
if (RB_UNLIKELY(fb->io)) {
|
|
138
|
-
if (fb->capa
|
|
139
|
-
fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
|
|
140
|
-
} else {
|
|
104
|
+
if (fb->capa != 0) {
|
|
141
105
|
fbuffer_flush(fb);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return;
|
|
106
|
+
if (RB_LIKELY(requested < fb->capa)) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
146
109
|
}
|
|
147
110
|
}
|
|
148
111
|
|
|
149
|
-
|
|
112
|
+
size_t new_capa = fb->capa ? fb->capa : fb->initial_length;
|
|
113
|
+
size_t needed_capa = requested + fb->len;
|
|
150
114
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
fb->capa = fb->initial_length;
|
|
115
|
+
while (new_capa < needed_capa) {
|
|
116
|
+
new_capa *= 2;
|
|
154
117
|
}
|
|
155
118
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
fbuffer_realloc(fb, required);
|
|
119
|
+
fbuffer_realloc(fb, new_capa);
|
|
159
120
|
}
|
|
160
121
|
|
|
161
|
-
static inline void fbuffer_inc_capa(FBuffer *fb,
|
|
122
|
+
static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested)
|
|
162
123
|
{
|
|
163
|
-
#
|
|
124
|
+
#if JSON_DEBUG
|
|
164
125
|
fb->requested = requested;
|
|
165
126
|
#endif
|
|
166
127
|
|
|
@@ -169,19 +130,33 @@ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
|
|
|
169
130
|
}
|
|
170
131
|
}
|
|
171
132
|
|
|
172
|
-
static
|
|
133
|
+
static inline size_t fbuffer_size_mul_or_raise(size_t a, size_t b)
|
|
134
|
+
{
|
|
135
|
+
size_t result = a * b;
|
|
136
|
+
if (RB_UNLIKELY(a != 0 && (result / a) != b)) {
|
|
137
|
+
rb_raise(rb_eArgError, "Buffer overflow, the resulting document is too large to be generated");
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, size_t len)
|
|
143
|
+
{
|
|
144
|
+
MEMCPY(fb->ptr + fb->len, newstr, char, len);
|
|
145
|
+
fbuffer_consumed(fb, len);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static inline void fbuffer_append(FBuffer *fb, const char *newstr, size_t len)
|
|
173
149
|
{
|
|
174
150
|
if (len > 0) {
|
|
175
151
|
fbuffer_inc_capa(fb, len);
|
|
176
|
-
|
|
177
|
-
fbuffer_consumed(fb, len);
|
|
152
|
+
fbuffer_append_reserved(fb, newstr, len);
|
|
178
153
|
}
|
|
179
154
|
}
|
|
180
155
|
|
|
181
156
|
/* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
|
|
182
157
|
static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
|
|
183
158
|
{
|
|
184
|
-
#
|
|
159
|
+
#if JSON_DEBUG
|
|
185
160
|
if (fb->requested < 1) {
|
|
186
161
|
rb_bug("fbuffer: unreserved write");
|
|
187
162
|
}
|
|
@@ -194,12 +169,29 @@ static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
|
|
|
194
169
|
|
|
195
170
|
static void fbuffer_append_str(FBuffer *fb, VALUE str)
|
|
196
171
|
{
|
|
197
|
-
const char *
|
|
198
|
-
|
|
172
|
+
const char *ptr;
|
|
173
|
+
size_t len;
|
|
174
|
+
RSTRING_GETMEM(str, ptr, len);
|
|
199
175
|
|
|
176
|
+
fbuffer_append(fb, ptr, len);
|
|
200
177
|
RB_GC_GUARD(str);
|
|
178
|
+
}
|
|
201
179
|
|
|
202
|
-
|
|
180
|
+
static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
|
|
181
|
+
{
|
|
182
|
+
const char *ptr;
|
|
183
|
+
size_t len;
|
|
184
|
+
RSTRING_GETMEM(str, ptr, len);
|
|
185
|
+
|
|
186
|
+
fbuffer_inc_capa(fb, fbuffer_size_mul_or_raise(repeat, len));
|
|
187
|
+
while (repeat) {
|
|
188
|
+
#if JSON_DEBUG
|
|
189
|
+
fb->requested = len;
|
|
190
|
+
#endif
|
|
191
|
+
fbuffer_append_reserved(fb, ptr, len);
|
|
192
|
+
repeat--;
|
|
193
|
+
}
|
|
194
|
+
RB_GC_GUARD(str);
|
|
203
195
|
}
|
|
204
196
|
|
|
205
197
|
static inline void fbuffer_append_char(FBuffer *fb, char newchr)
|
|
@@ -257,14 +249,11 @@ static VALUE fbuffer_finalize(FBuffer *fb)
|
|
|
257
249
|
{
|
|
258
250
|
if (fb->io) {
|
|
259
251
|
fbuffer_flush(fb);
|
|
260
|
-
fbuffer_free(fb);
|
|
261
252
|
rb_io_flush(fb->io);
|
|
262
253
|
return fb->io;
|
|
263
254
|
} else {
|
|
264
|
-
|
|
265
|
-
fbuffer_free(fb);
|
|
266
|
-
return result;
|
|
255
|
+
return rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
|
|
267
256
|
}
|
|
268
257
|
}
|
|
269
258
|
|
|
270
|
-
#endif
|
|
259
|
+
#endif // _FBUFFER_H_
|
|
@@ -5,8 +5,11 @@ if RUBY_ENGINE == 'truffleruby'
|
|
|
5
5
|
File.write('Makefile', dummy_makefile("").join)
|
|
6
6
|
else
|
|
7
7
|
append_cflags("-std=c99")
|
|
8
|
+
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
|
|
9
|
+
have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
|
|
10
|
+
|
|
8
11
|
$defs << "-DJSON_GENERATOR"
|
|
9
|
-
$defs << "-DJSON_DEBUG" if ENV
|
|
12
|
+
$defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
|
|
10
13
|
|
|
11
14
|
if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
|
|
12
15
|
load __dir__ + "/../simd/conf.rb"
|