json 2.7.2 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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