json 2.7.2 → 2.9.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.
@@ -1,89 +1,91 @@
1
-
2
1
  #ifndef _FBUFFER_H_
3
2
  #define _FBUFFER_H_
4
3
 
5
4
  #include "ruby.h"
5
+ #include "ruby/encoding.h"
6
6
 
7
- #ifndef RHASH_SIZE
8
- #define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
7
+ /* shims */
8
+ /* This is the fallback definition from Ruby 3.4 */
9
+
10
+ #ifndef RBIMPL_STDBOOL_H
11
+ #if defined(__cplusplus)
12
+ # if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
13
+ # include <cstdbool>
14
+ # endif
15
+ #elif defined(HAVE_STDBOOL_H)
16
+ # include <stdbool.h>
17
+ #elif !defined(HAVE__BOOL)
18
+ typedef unsigned char _Bool;
19
+ # define bool _Bool
20
+ # define true ((_Bool)+1)
21
+ # define false ((_Bool)+0)
22
+ # define __bool_true_false_are_defined
9
23
  #endif
10
-
11
- #ifndef RFLOAT_VALUE
12
- #define RFLOAT_VALUE(val) (RFLOAT(val)->value)
13
24
  #endif
14
25
 
15
- #ifndef RARRAY_LEN
16
- #define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len
17
- #endif
18
- #ifndef RSTRING_PTR
19
- #define RSTRING_PTR(string) RSTRING(string)->ptr
20
- #endif
21
- #ifndef RSTRING_LEN
22
- #define RSTRING_LEN(string) RSTRING(string)->len
26
+ #ifndef RB_UNLIKELY
27
+ #define RB_UNLIKELY(expr) expr
23
28
  #endif
24
29
 
25
- #ifdef PRIsVALUE
26
- # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
27
- # define RB_OBJ_STRING(obj) (obj)
28
- #else
29
- # define PRIsVALUE "s"
30
- # define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
31
- # define RB_OBJ_STRING(obj) StringValueCStr(obj)
30
+ #ifndef RB_LIKELY
31
+ #define RB_LIKELY(expr) expr
32
32
  #endif
33
33
 
34
- #ifdef HAVE_RUBY_ENCODING_H
35
- #include "ruby/encoding.h"
36
- #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
37
- #else
38
- #define FORCE_UTF8(obj)
34
+ #ifndef MAYBE_UNUSED
35
+ # define MAYBE_UNUSED(x) x
39
36
  #endif
40
37
 
41
- /* We don't need to guard objects for rbx, so let's do nothing at all. */
42
- #ifndef RB_GC_GUARD
43
- #define RB_GC_GUARD(object)
44
- #endif
38
+ enum fbuffer_type {
39
+ FBUFFER_HEAP_ALLOCATED = 0,
40
+ FBUFFER_STACK_ALLOCATED = 1,
41
+ };
45
42
 
46
43
  typedef struct FBufferStruct {
44
+ enum fbuffer_type type;
47
45
  unsigned long initial_length;
48
- char *ptr;
49
46
  unsigned long len;
50
47
  unsigned long capa;
48
+ char *ptr;
49
+ VALUE io;
51
50
  } FBuffer;
52
51
 
52
+ #define FBUFFER_STACK_SIZE 512
53
+ #define FBUFFER_IO_BUFFER_SIZE (16384 - 1)
53
54
  #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
54
55
 
55
- #define FBUFFER_PTR(fb) (fb->ptr)
56
- #define FBUFFER_LEN(fb) (fb->len)
57
- #define FBUFFER_CAPA(fb) (fb->capa)
56
+ #define FBUFFER_PTR(fb) ((fb)->ptr)
57
+ #define FBUFFER_LEN(fb) ((fb)->len)
58
+ #define FBUFFER_CAPA(fb) ((fb)->capa)
58
59
  #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
59
60
 
60
- static FBuffer *fbuffer_alloc(unsigned long initial_length);
61
61
  static void fbuffer_free(FBuffer *fb);
62
+ #ifndef JSON_GENERATOR
62
63
  static void fbuffer_clear(FBuffer *fb);
64
+ #endif
63
65
  static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
64
66
  #ifdef JSON_GENERATOR
65
67
  static void fbuffer_append_long(FBuffer *fb, long number);
66
68
  #endif
67
- static void fbuffer_append_char(FBuffer *fb, char newchr);
69
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr);
68
70
  #ifdef JSON_GENERATOR
69
- static FBuffer *fbuffer_dup(FBuffer *fb);
70
- static VALUE fbuffer_to_s(FBuffer *fb);
71
+ static VALUE fbuffer_finalize(FBuffer *fb);
71
72
  #endif
72
73
 
73
- static FBuffer *fbuffer_alloc(unsigned long initial_length)
74
+ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *stack_buffer, long stack_buffer_size)
74
75
  {
75
- FBuffer *fb;
76
- if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
77
- fb = ALLOC(FBuffer);
78
- memset((void *) fb, 0, sizeof(FBuffer));
79
- fb->initial_length = initial_length;
80
- return fb;
76
+ fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
77
+ if (stack_buffer) {
78
+ fb->type = FBUFFER_STACK_ALLOCATED;
79
+ fb->ptr = stack_buffer;
80
+ fb->capa = stack_buffer_size;
81
+ }
81
82
  }
82
83
 
83
84
  static void fbuffer_free(FBuffer *fb)
84
85
  {
85
- if (fb->ptr) ruby_xfree(fb->ptr);
86
- ruby_xfree(fb);
86
+ if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
87
+ ruby_xfree(fb->ptr);
88
+ }
87
89
  }
88
90
 
89
91
  static void fbuffer_clear(FBuffer *fb)
@@ -91,20 +93,57 @@ static void fbuffer_clear(FBuffer *fb)
91
93
  fb->len = 0;
92
94
  }
93
95
 
94
- static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
96
+ static void fbuffer_flush(FBuffer *fb)
97
+ {
98
+ rb_io_write(fb->io, rb_utf8_str_new(fb->ptr, fb->len));
99
+ fbuffer_clear(fb);
100
+ }
101
+
102
+ static void fbuffer_realloc(FBuffer *fb, unsigned long required)
103
+ {
104
+ if (required > fb->capa) {
105
+ if (fb->type == FBUFFER_STACK_ALLOCATED) {
106
+ const char *old_buffer = fb->ptr;
107
+ fb->ptr = ALLOC_N(char, required);
108
+ fb->type = FBUFFER_HEAP_ALLOCATED;
109
+ MEMCPY(fb->ptr, old_buffer, char, fb->len);
110
+ } else {
111
+ REALLOC_N(fb->ptr, char, required);
112
+ }
113
+ fb->capa = required;
114
+ }
115
+ }
116
+
117
+ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
95
118
  {
119
+ if (RB_UNLIKELY(fb->io)) {
120
+ if (fb->capa < FBUFFER_IO_BUFFER_SIZE) {
121
+ fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
122
+ } else {
123
+ fbuffer_flush(fb);
124
+ }
125
+
126
+ if (RB_LIKELY(requested < fb->capa)) {
127
+ return;
128
+ }
129
+ }
130
+
96
131
  unsigned long required;
97
132
 
98
- if (!fb->ptr) {
133
+ if (RB_UNLIKELY(!fb->ptr)) {
99
134
  fb->ptr = ALLOC_N(char, fb->initial_length);
100
135
  fb->capa = fb->initial_length;
101
136
  }
102
137
 
103
138
  for (required = fb->capa; requested > required - fb->len; required <<= 1);
104
139
 
105
- if (required > fb->capa) {
106
- REALLOC_N(fb->ptr, char, required);
107
- fb->capa = required;
140
+ fbuffer_realloc(fb, required);
141
+ }
142
+
143
+ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
144
+ {
145
+ if (RB_UNLIKELY(requested > fb->capa - fb->len)) {
146
+ fbuffer_do_inc_capa(fb, requested);
108
147
  }
109
148
  }
110
149
 
@@ -129,7 +168,7 @@ static void fbuffer_append_str(FBuffer *fb, VALUE str)
129
168
  }
130
169
  #endif
131
170
 
132
- static void fbuffer_append_char(FBuffer *fb, char newchr)
171
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr)
133
172
  {
134
173
  fbuffer_inc_capa(fb, 1);
135
174
  *(fb->ptr + fb->len) = newchr;
@@ -137,51 +176,39 @@ static void fbuffer_append_char(FBuffer *fb, char newchr)
137
176
  }
138
177
 
139
178
  #ifdef JSON_GENERATOR
140
- static void freverse(char *start, char *end)
141
- {
142
- char c;
143
-
144
- while (end > start) {
145
- c = *end, *end-- = *start, *start++ = c;
146
- }
147
- }
148
-
149
179
  static long fltoa(long number, char *buf)
150
180
  {
151
- static char digits[] = "0123456789";
181
+ static const char digits[] = "0123456789";
152
182
  long sign = number;
153
183
  char* tmp = buf;
154
184
 
155
185
  if (sign < 0) number = -number;
156
- do *tmp++ = digits[number % 10]; while (number /= 10);
157
- if (sign < 0) *tmp++ = '-';
158
- freverse(buf, tmp - 1);
159
- return tmp - buf;
186
+ do *tmp-- = digits[number % 10]; while (number /= 10);
187
+ if (sign < 0) *tmp-- = '-';
188
+ return buf - tmp;
160
189
  }
161
190
 
191
+ #define LONG_BUFFER_SIZE 20
162
192
  static void fbuffer_append_long(FBuffer *fb, long number)
163
193
  {
164
- char buf[20];
165
- unsigned long len = fltoa(number, buf);
166
- fbuffer_append(fb, buf, len);
194
+ char buf[LONG_BUFFER_SIZE];
195
+ char *buffer_end = buf + LONG_BUFFER_SIZE;
196
+ long len = fltoa(number, buffer_end - 1);
197
+ fbuffer_append(fb, buffer_end - len, len);
167
198
  }
168
199
 
169
- static FBuffer *fbuffer_dup(FBuffer *fb)
200
+ static VALUE fbuffer_finalize(FBuffer *fb)
170
201
  {
171
- unsigned long len = fb->len;
172
- FBuffer *result;
173
-
174
- result = fbuffer_alloc(len);
175
- fbuffer_append(result, FBUFFER_PAIR(fb));
176
- return result;
177
- }
178
-
179
- static VALUE fbuffer_to_s(FBuffer *fb)
180
- {
181
- VALUE result = rb_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
182
- fbuffer_free(fb);
183
- FORCE_UTF8(result);
184
- return result;
202
+ if (fb->io) {
203
+ fbuffer_flush(fb);
204
+ fbuffer_free(fb);
205
+ rb_io_flush(fb->io);
206
+ return fb->io;
207
+ } else {
208
+ VALUE result = rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
209
+ fbuffer_free(fb);
210
+ return result;
211
+ }
185
212
  }
186
213
  #endif
187
214
  #endif
@@ -1,4 +1,10 @@
1
1
  require 'mkmf'
2
2
 
3
- $defs << "-DJSON_GENERATOR"
4
- create_makefile 'json/ext/generator'
3
+ if RUBY_ENGINE == 'truffleruby'
4
+ # The pure-Ruby generator is faster on TruffleRuby, so skip compiling the generator extension
5
+ File.write('Makefile', dummy_makefile("").join)
6
+ else
7
+ append_cflags("-std=c99")
8
+ $defs << "-DJSON_GENERATOR"
9
+ create_makefile 'json/ext/generator'
10
+ end