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.
@@ -1,47 +1,9 @@
1
1
  #ifndef _FBUFFER_H_
2
2
  #define _FBUFFER_H_
3
3
 
4
- #include "ruby.h"
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
- unsigned long initial_length;
53
- unsigned long len;
54
- unsigned long capa;
55
- #ifdef JSON_DEBUG
56
- unsigned long requested;
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, unsigned long len);
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 fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *stack_buffer, long stack_buffer_size)
40
+ static void fbuffer_init(FBuffer *fb, size_t initial_length, VALUE io, char *stack_buffer, size_t stack_buffer_size)
79
41
  {
80
- fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
81
- if (stack_buffer) {
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
- #ifdef JSON_DEBUG
52
+ #if JSON_DEBUG
87
53
  fb->requested = 0;
88
54
  #endif
89
55
  }
90
56
 
91
- static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed)
57
+ static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
92
58
  {
93
- #ifdef JSON_DEBUG
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
- ruby_xfree(fb->ptr);
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, unsigned long required)
86
+ static void fbuffer_realloc(FBuffer *fb, size_t new_capa)
121
87
  {
122
- if (required > fb->capa) {
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, required);
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
- REALLOC_N(fb->ptr, char, required);
95
+ JSON_SIZED_REALLOC_N(fb->ptr, char, new_capa, fb->capa);
130
96
  }
131
- fb->capa = required;
97
+ fb->capa = new_capa;
132
98
  }
133
99
  }
134
100
 
135
- static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
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 < FBUFFER_IO_BUFFER_SIZE) {
139
- fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
140
- } else {
104
+ if (fb->capa != 0) {
141
105
  fbuffer_flush(fb);
142
- }
143
-
144
- if (RB_LIKELY(requested < fb->capa)) {
145
- return;
106
+ if (RB_LIKELY(requested < fb->capa)) {
107
+ return;
108
+ }
146
109
  }
147
110
  }
148
111
 
149
- unsigned long required;
112
+ size_t new_capa = fb->capa ? fb->capa : fb->initial_length;
113
+ size_t needed_capa = requested + fb->len;
150
114
 
151
- if (RB_UNLIKELY(!fb->ptr)) {
152
- fb->ptr = ALLOC_N(char, fb->initial_length);
153
- fb->capa = fb->initial_length;
115
+ while (new_capa < needed_capa) {
116
+ new_capa *= 2;
154
117
  }
155
118
 
156
- for (required = fb->capa; requested > required - fb->len; required <<= 1);
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, unsigned long requested)
122
+ static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested)
162
123
  {
163
- #ifdef JSON_DEBUG
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 void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
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
- MEMCPY(fb->ptr + fb->len, newstr, char, len);
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
- #ifdef JSON_DEBUG
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 *newstr = StringValuePtr(str);
198
- unsigned long len = RSTRING_LEN(str);
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
- fbuffer_append(fb, newstr, len);
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
- VALUE result = rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
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["JSON_DEBUG"]
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"