json 2.7.2 → 2.10.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,85 @@
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
62
  static void fbuffer_clear(FBuffer *fb);
63
63
  static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
64
- #ifdef JSON_GENERATOR
65
64
  static void fbuffer_append_long(FBuffer *fb, long number);
66
- #endif
67
- static void fbuffer_append_char(FBuffer *fb, char newchr);
68
- #ifdef JSON_GENERATOR
69
- static FBuffer *fbuffer_dup(FBuffer *fb);
70
- static VALUE fbuffer_to_s(FBuffer *fb);
71
- #endif
65
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr);
66
+ static VALUE fbuffer_finalize(FBuffer *fb);
72
67
 
73
- static FBuffer *fbuffer_alloc(unsigned long initial_length)
68
+ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *stack_buffer, long stack_buffer_size)
74
69
  {
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;
70
+ fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
71
+ if (stack_buffer) {
72
+ fb->type = FBUFFER_STACK_ALLOCATED;
73
+ fb->ptr = stack_buffer;
74
+ fb->capa = stack_buffer_size;
75
+ }
81
76
  }
82
77
 
83
78
  static void fbuffer_free(FBuffer *fb)
84
79
  {
85
- if (fb->ptr) ruby_xfree(fb->ptr);
86
- ruby_xfree(fb);
80
+ if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
81
+ ruby_xfree(fb->ptr);
82
+ }
87
83
  }
88
84
 
89
85
  static void fbuffer_clear(FBuffer *fb)
@@ -91,20 +87,57 @@ static void fbuffer_clear(FBuffer *fb)
91
87
  fb->len = 0;
92
88
  }
93
89
 
94
- static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
90
+ static void fbuffer_flush(FBuffer *fb)
91
+ {
92
+ rb_io_write(fb->io, rb_utf8_str_new(fb->ptr, fb->len));
93
+ fbuffer_clear(fb);
94
+ }
95
+
96
+ static void fbuffer_realloc(FBuffer *fb, unsigned long required)
97
+ {
98
+ if (required > fb->capa) {
99
+ if (fb->type == FBUFFER_STACK_ALLOCATED) {
100
+ const char *old_buffer = fb->ptr;
101
+ fb->ptr = ALLOC_N(char, required);
102
+ fb->type = FBUFFER_HEAP_ALLOCATED;
103
+ MEMCPY(fb->ptr, old_buffer, char, fb->len);
104
+ } else {
105
+ REALLOC_N(fb->ptr, char, required);
106
+ }
107
+ fb->capa = required;
108
+ }
109
+ }
110
+
111
+ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
95
112
  {
113
+ if (RB_UNLIKELY(fb->io)) {
114
+ if (fb->capa < FBUFFER_IO_BUFFER_SIZE) {
115
+ fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
116
+ } else {
117
+ fbuffer_flush(fb);
118
+ }
119
+
120
+ if (RB_LIKELY(requested < fb->capa)) {
121
+ return;
122
+ }
123
+ }
124
+
96
125
  unsigned long required;
97
126
 
98
- if (!fb->ptr) {
127
+ if (RB_UNLIKELY(!fb->ptr)) {
99
128
  fb->ptr = ALLOC_N(char, fb->initial_length);
100
129
  fb->capa = fb->initial_length;
101
130
  }
102
131
 
103
132
  for (required = fb->capa; requested > required - fb->len; required <<= 1);
104
133
 
105
- if (required > fb->capa) {
106
- REALLOC_N(fb->ptr, char, required);
107
- fb->capa = required;
134
+ fbuffer_realloc(fb, required);
135
+ }
136
+
137
+ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
138
+ {
139
+ if (RB_UNLIKELY(requested > fb->capa - fb->len)) {
140
+ fbuffer_do_inc_capa(fb, requested);
108
141
  }
109
142
  }
110
143
 
@@ -117,7 +150,6 @@ static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
117
150
  }
118
151
  }
119
152
 
120
- #ifdef JSON_GENERATOR
121
153
  static void fbuffer_append_str(FBuffer *fb, VALUE str)
122
154
  {
123
155
  const char *newstr = StringValuePtr(str);
@@ -127,61 +159,47 @@ static void fbuffer_append_str(FBuffer *fb, VALUE str)
127
159
 
128
160
  fbuffer_append(fb, newstr, len);
129
161
  }
130
- #endif
131
162
 
132
- static void fbuffer_append_char(FBuffer *fb, char newchr)
163
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr)
133
164
  {
134
165
  fbuffer_inc_capa(fb, 1);
135
166
  *(fb->ptr + fb->len) = newchr;
136
167
  fb->len++;
137
168
  }
138
169
 
139
- #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
170
  static long fltoa(long number, char *buf)
150
171
  {
151
- static char digits[] = "0123456789";
172
+ static const char digits[] = "0123456789";
152
173
  long sign = number;
153
174
  char* tmp = buf;
154
175
 
155
176
  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;
177
+ do *tmp-- = digits[number % 10]; while (number /= 10);
178
+ if (sign < 0) *tmp-- = '-';
179
+ return buf - tmp;
160
180
  }
161
181
 
182
+ #define LONG_BUFFER_SIZE 20
162
183
  static void fbuffer_append_long(FBuffer *fb, long number)
163
184
  {
164
- char buf[20];
165
- unsigned long len = fltoa(number, buf);
166
- fbuffer_append(fb, buf, len);
185
+ char buf[LONG_BUFFER_SIZE];
186
+ char *buffer_end = buf + LONG_BUFFER_SIZE;
187
+ long len = fltoa(number, buffer_end - 1);
188
+ fbuffer_append(fb, buffer_end - len, len);
167
189
  }
168
190
 
169
- static FBuffer *fbuffer_dup(FBuffer *fb)
191
+ static VALUE fbuffer_finalize(FBuffer *fb)
170
192
  {
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;
193
+ if (fb->io) {
194
+ fbuffer_flush(fb);
195
+ fbuffer_free(fb);
196
+ rb_io_flush(fb->io);
197
+ return fb->io;
198
+ } else {
199
+ VALUE result = rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
200
+ fbuffer_free(fb);
201
+ return result;
202
+ }
177
203
  }
178
204
 
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;
185
- }
186
- #endif
187
205
  #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