json 2.7.2 → 2.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,101 +1,103 @@
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;
51
49
  } FBuffer;
52
50
 
51
+ #define FBUFFER_STACK_SIZE 512
53
52
  #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
54
53
 
55
- #define FBUFFER_PTR(fb) (fb->ptr)
56
- #define FBUFFER_LEN(fb) (fb->len)
57
- #define FBUFFER_CAPA(fb) (fb->capa)
54
+ #define FBUFFER_PTR(fb) ((fb)->ptr)
55
+ #define FBUFFER_LEN(fb) ((fb)->len)
56
+ #define FBUFFER_CAPA(fb) ((fb)->capa)
58
57
  #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
59
58
 
60
- static FBuffer *fbuffer_alloc(unsigned long initial_length);
61
59
  static void fbuffer_free(FBuffer *fb);
60
+ #ifndef JSON_GENERATOR
62
61
  static void fbuffer_clear(FBuffer *fb);
62
+ #endif
63
63
  static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
64
64
  #ifdef JSON_GENERATOR
65
65
  static void fbuffer_append_long(FBuffer *fb, long number);
66
66
  #endif
67
- static void fbuffer_append_char(FBuffer *fb, char newchr);
67
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr);
68
68
  #ifdef JSON_GENERATOR
69
- static FBuffer *fbuffer_dup(FBuffer *fb);
70
69
  static VALUE fbuffer_to_s(FBuffer *fb);
71
70
  #endif
72
71
 
73
- static FBuffer *fbuffer_alloc(unsigned long initial_length)
72
+ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *stack_buffer, long stack_buffer_size)
74
73
  {
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;
74
+ fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
75
+ if (stack_buffer) {
76
+ fb->type = FBUFFER_STACK_ALLOCATED;
77
+ fb->ptr = stack_buffer;
78
+ fb->capa = stack_buffer_size;
79
+ }
81
80
  }
82
81
 
83
82
  static void fbuffer_free(FBuffer *fb)
84
83
  {
85
- if (fb->ptr) ruby_xfree(fb->ptr);
86
- ruby_xfree(fb);
84
+ if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
85
+ ruby_xfree(fb->ptr);
86
+ }
87
87
  }
88
88
 
89
+ #ifndef JSON_GENERATOR
89
90
  static void fbuffer_clear(FBuffer *fb)
90
91
  {
91
92
  fb->len = 0;
92
93
  }
94
+ #endif
93
95
 
94
- static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
96
+ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
95
97
  {
96
98
  unsigned long required;
97
99
 
98
- if (!fb->ptr) {
100
+ if (RB_UNLIKELY(!fb->ptr)) {
99
101
  fb->ptr = ALLOC_N(char, fb->initial_length);
100
102
  fb->capa = fb->initial_length;
101
103
  }
@@ -103,11 +105,25 @@ static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
103
105
  for (required = fb->capa; requested > required - fb->len; required <<= 1);
104
106
 
105
107
  if (required > fb->capa) {
106
- REALLOC_N(fb->ptr, char, required);
108
+ if (fb->type == FBUFFER_STACK_ALLOCATED) {
109
+ const char *old_buffer = fb->ptr;
110
+ fb->ptr = ALLOC_N(char, required);
111
+ fb->type = FBUFFER_HEAP_ALLOCATED;
112
+ MEMCPY(fb->ptr, old_buffer, char, fb->len);
113
+ } else {
114
+ REALLOC_N(fb->ptr, char, required);
115
+ }
107
116
  fb->capa = required;
108
117
  }
109
118
  }
110
119
 
120
+ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
121
+ {
122
+ if (RB_UNLIKELY(requested > fb->capa - fb->len)) {
123
+ fbuffer_do_inc_capa(fb, requested);
124
+ }
125
+ }
126
+
111
127
  static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
112
128
  {
113
129
  if (len > 0) {
@@ -129,7 +145,7 @@ static void fbuffer_append_str(FBuffer *fb, VALUE str)
129
145
  }
130
146
  #endif
131
147
 
132
- static void fbuffer_append_char(FBuffer *fb, char newchr)
148
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr)
133
149
  {
134
150
  fbuffer_inc_capa(fb, 1);
135
151
  *(fb->ptr + fb->len) = newchr;
@@ -137,50 +153,31 @@ static void fbuffer_append_char(FBuffer *fb, char newchr)
137
153
  }
138
154
 
139
155
  #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
156
  static long fltoa(long number, char *buf)
150
157
  {
151
- static char digits[] = "0123456789";
158
+ static const char digits[] = "0123456789";
152
159
  long sign = number;
153
160
  char* tmp = buf;
154
161
 
155
162
  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;
163
+ do *tmp-- = digits[number % 10]; while (number /= 10);
164
+ if (sign < 0) *tmp-- = '-';
165
+ return buf - tmp;
160
166
  }
161
167
 
168
+ #define LONG_BUFFER_SIZE 20
162
169
  static void fbuffer_append_long(FBuffer *fb, long number)
163
170
  {
164
- char buf[20];
165
- unsigned long len = fltoa(number, buf);
166
- fbuffer_append(fb, buf, len);
167
- }
168
-
169
- static FBuffer *fbuffer_dup(FBuffer *fb)
170
- {
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;
171
+ char buf[LONG_BUFFER_SIZE];
172
+ char *buffer_end = buf + LONG_BUFFER_SIZE;
173
+ long len = fltoa(number, buffer_end - 1);
174
+ fbuffer_append(fb, buffer_end - len, len);
177
175
  }
178
176
 
179
177
  static VALUE fbuffer_to_s(FBuffer *fb)
180
178
  {
181
- VALUE result = rb_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
179
+ VALUE result = rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
182
180
  fbuffer_free(fb);
183
- FORCE_UTF8(result);
184
181
  return result;
185
182
  }
186
183
  #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