json-extended 2.20.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.
data/COPYING ADDED
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
data/LEGAL ADDED
@@ -0,0 +1,20 @@
1
+ # -*- rdoc -*-
2
+
3
+ = LEGAL NOTICE INFORMATION
4
+ --------------------------
5
+
6
+ All the files in this distribution are covered under either the Ruby's
7
+ license (see the file COPYING) or public-domain except some files
8
+ mentioned below.
9
+
10
+ ext/json/ext/vendor/fpconv.h::
11
+ This file is adapted from https://github.com/night-shift/fpconv
12
+ It is licensed under Boost Software License 1.0.
13
+
14
+ ext/json/ext/vendor/jeaiii-ltoa.h::
15
+ This file is adapted from https://github.com/jeaiii/itoa
16
+ It is licensed under the MIT License
17
+
18
+ ext/json/ext/vendor/fast_float_parser.h::
19
+ This file is adapted from the Fast Float C++ library by The fast_float authors https://github.com/fastfloat/fast_float
20
+ It is licensed under the MIT License
data/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # JSON implementation for Ruby
2
+
3
+ [![CI](https://github.com/ruby/json/actions/workflows/ci.yml/badge.svg)](https://github.com/ruby/json/actions/workflows/ci.yml)
4
+
5
+ ## Description
6
+
7
+ This is an implementation of the JSON specification according to RFC 7159
8
+ http://www.ietf.org/rfc/rfc7159.txt .
9
+
10
+ The JSON generator generate UTF-8 character sequences by default.
11
+ If an :ascii\_only option with a true value is given, they escape all
12
+ non-ASCII and control characters with \uXXXX escape sequences, and support
13
+ UTF-16 surrogate pairs in order to be able to generate the whole range of
14
+ unicode code points.
15
+
16
+ All strings, that are to be encoded as JSON strings, should be UTF-8 byte
17
+ sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
18
+ encoded, please use the to\_json\_raw\_object method of String (which produces
19
+ an object, that contains a byte array) and decode the result on the receiving
20
+ endpoint.
21
+
22
+ ## Installation
23
+
24
+ Install the gem and add to the application's Gemfile by executing:
25
+
26
+ $ bundle add json
27
+
28
+ If bundler is not being used to manage dependencies, install the gem by executing:
29
+
30
+ $ gem install json
31
+
32
+ ## Basic Usage
33
+
34
+ To use JSON you can
35
+
36
+ ```ruby
37
+ require 'json'
38
+ ```
39
+
40
+ Now you can parse a JSON document into a ruby data structure by calling
41
+
42
+ ```ruby
43
+ JSON.parse(document)
44
+ ```
45
+
46
+ If you want to generate a JSON document from a ruby data structure call
47
+ ```ruby
48
+ JSON.generate(data)
49
+ ```
50
+
51
+ You can also use the `pretty_generate` method (which formats the output more
52
+ verbosely and nicely) or `fast_generate` (which doesn't do any of the security
53
+ checks generate performs, e. g. nesting deepness checks).
54
+
55
+ ## Casting non native types
56
+
57
+ JSON documents can only support Hashes, Arrays, Strings, Integers and Floats.
58
+
59
+ By default if you attempt to serialize something else, `JSON.generate` will
60
+ search for a `#to_json` method on that object:
61
+
62
+ ```ruby
63
+ Position = Struct.new(:latitude, :longitude) do
64
+ def to_json(state = nil, *)
65
+ JSON::State.from_state(state).generate({
66
+ latitude: latitude,
67
+ longitude: longitude,
68
+ })
69
+ end
70
+ end
71
+
72
+ JSON.generate([
73
+ Position.new(12323.234, 435345.233),
74
+ Position.new(23434.676, 159435.324),
75
+ ]) # => [{"latitude":12323.234,"longitude":435345.233},{"latitude":23434.676,"longitude":159435.324}]
76
+ ```
77
+
78
+ If a `#to_json` method isn't defined on the object, `JSON.generate` will fallback to call `#to_s`:
79
+
80
+ ```ruby
81
+ JSON.generate(Object.new) # => "#<Object:0x000000011e768b98>"
82
+ ```
83
+
84
+ Both of these behavior can be disabled using the `strict: true` option:
85
+
86
+ ```ruby
87
+ JSON.generate(Object.new, strict: true) # => Object not allowed in JSON (JSON::GeneratorError)
88
+ JSON.generate(Position.new(1, 2)) # => Position not allowed in JSON (JSON::GeneratorError)
89
+ ```
90
+
91
+ ## JSON::Coder
92
+
93
+ Since `#to_json` methods are global, it can sometimes be problematic if you need a given type to be
94
+ serialized in different ways in different locations.
95
+
96
+ Instead it is recommended to use the newer `JSON::Coder` API:
97
+
98
+ ```ruby
99
+ module MyApp
100
+ API_JSON_CODER = JSON::Coder.new do |object, is_object_key|
101
+ case object
102
+ when Time
103
+ object.iso8601(3)
104
+ else
105
+ object
106
+ end
107
+ end
108
+ end
109
+
110
+ puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
111
+ ```
112
+
113
+ The provided block is called for all objects that don't have a native JSON equivalent, and
114
+ must return a Ruby object that has a native JSON equivalent.
115
+
116
+ It is also called for objects that do have a JSON equivalent, but are used as Hash keys, for instance `{ 1 => 2}`,
117
+ as well as for strings that aren't valid UTF-8:
118
+
119
+ ```ruby
120
+ coder = JSON::Combining.new do |object, is_object_key|
121
+ case object
122
+ when String
123
+ if !string.valid_encoding? || string.encoding != Encoding::UTF_8
124
+ Base64.encode64(string)
125
+ else
126
+ string
127
+ end
128
+ else
129
+ object
130
+ end
131
+ end
132
+ ```
133
+
134
+ ## Combining JSON fragments
135
+
136
+ To combine JSON fragments into a bigger JSON document, you can use `JSON::Fragment`:
137
+
138
+ ```ruby
139
+ posts_json = cache.fetch_multi(post_ids) do |post_id|
140
+ JSON.generate(Post.find(post_id))
141
+ end
142
+ posts_json.map! { |post_json| JSON::Fragment.new(post_json) }
143
+ JSON.generate({ posts: posts_json, count: posts_json.count })
144
+ ```
145
+
146
+ ## Round-tripping arbitrary types
147
+
148
+ > [!CAUTION]
149
+ > You should never use `JSON.unsafe_load` nor `JSON.parse(str, create_additions: true)` to parse untrusted user input,
150
+ > as it can lead to remote code execution vulnerabilities.
151
+
152
+ To create a JSON document from a ruby data structure, you can call
153
+ `JSON.generate` like that:
154
+
155
+ ```ruby
156
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
157
+ # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
158
+ ```
159
+
160
+ To get back a ruby data structure from a JSON document, you have to call
161
+ JSON.parse on it:
162
+
163
+ ```ruby
164
+ JSON.parse json
165
+ # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
166
+ ```
167
+
168
+ Note, that the range from the original data structure is a simple
169
+ string now. The reason for this is, that JSON doesn't support ranges
170
+ or arbitrary classes. In this case the json library falls back to call
171
+ `Object#to_json`, which is the same as `#to_s.to_json`.
172
+
173
+ It's possible to add JSON support serialization to arbitrary classes by
174
+ simply implementing a more specialized version of the `#to_json method`, that
175
+ should return a JSON object (a hash converted to JSON with `#to_json`) like
176
+ this (don't forget the `*a` for all the arguments):
177
+
178
+ ```ruby
179
+ class Range
180
+ def to_json(*a)
181
+ {
182
+ 'json_class' => self.class.name, # = 'Range'
183
+ 'data' => [ first, last, exclude_end? ]
184
+ }.to_json(*a)
185
+ end
186
+ end
187
+ ```
188
+
189
+ The hash key `json_class` is the class, that will be asked to deserialise the
190
+ JSON representation later. In this case it's `Range`, but any namespace of
191
+ the form `A::B` or `::A::B` will do. All other keys are arbitrary and can be
192
+ used to store the necessary data to configure the object to be deserialised.
193
+
194
+ If the key `json_class` is found in a JSON object, the JSON parser checks
195
+ if the given class responds to the `json_create` class method. If so, it is
196
+ called with the JSON object converted to a Ruby hash. So a range can
197
+ be deserialised by implementing `Range.json_create` like this:
198
+
199
+ ```ruby
200
+ class Range
201
+ def self.json_create(o)
202
+ new(*o['data'])
203
+ end
204
+ end
205
+ ```
206
+
207
+ Now it possible to serialise/deserialise ranges as well:
208
+
209
+ ```ruby
210
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
211
+ # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
212
+ JSON.parse json
213
+ # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
214
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
215
+ # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
216
+ JSON.unsafe_load json
217
+ # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
218
+ ```
219
+
220
+ `JSON.generate` always creates the shortest possible string representation of a
221
+ ruby data structure in one line. This is good for data storage or network
222
+ protocols, but not so good for humans to read. Fortunately there's also
223
+ `JSON.pretty_generate` (or `JSON.pretty_generate`) that creates a more readable
224
+ output:
225
+
226
+ ```ruby
227
+ puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
228
+ [
229
+ 1,
230
+ 2,
231
+ {
232
+ "a": 3.141
233
+ },
234
+ false,
235
+ true,
236
+ null,
237
+ {
238
+ "json_class": "Range",
239
+ "data": [
240
+ 4,
241
+ 10,
242
+ false
243
+ ]
244
+ }
245
+ ]
246
+ ```
247
+
248
+ There are also the methods `Kernel#j` for generate, and `Kernel#jj` for
249
+ `pretty_generate` output to the console, that work analogous to Core Ruby's `p` and
250
+ the `pp` library's `pp` methods.
251
+
252
+ ## Security
253
+
254
+ When parsing or serializing untrusted input, parser and generator options should never be user controlled.
255
+
256
+ ```ruby
257
+ # Dangerous, DO NOT DO THIS.
258
+ JSON.generate(params[:data], params[:options])
259
+ ```
260
+
261
+ Security vulnerability reports relying on attacker controlled parsing or generator options will be handled as regular bug fixes.
262
+
263
+ ## Development
264
+
265
+ ### Prerequisites
266
+
267
+ 1. Clone the repository
268
+ 2. Install dependencies with `bundle install`
269
+
270
+ ### Testing
271
+
272
+ The full test suite can be run with:
273
+
274
+ ```bash
275
+ bundle exec rake test
276
+ ```
277
+
278
+ ### Release
279
+
280
+ Update the `lib/json/version.rb` file.
281
+
282
+ ```
283
+ rbenv shell 2.6.5
284
+ rake build
285
+ gem push pkg/json-2.3.0.gem
286
+
287
+ rbenv shell jruby-9.2.9.0
288
+ rake build
289
+ gem push pkg/json-2.3.0-java.gem
290
+ ```
291
+
292
+ ## Author
293
+
294
+ Florian Frank <mailto:flori@ping.de>
295
+
296
+ ## License
297
+
298
+ Ruby License, see https://www.ruby-lang.org/en/about/license.txt.
299
+
300
+ ## Download
301
+
302
+ The latest version of this library can be downloaded at
303
+
304
+ * https://rubygems.org/gems/json
305
+
306
+ Online Documentation should be located at
307
+
308
+ * https://www.rubydoc.info/gems/json
@@ -0,0 +1,259 @@
1
+ #ifndef _FBUFFER_H_
2
+ #define _FBUFFER_H_
3
+
4
+ #include "../json.h"
5
+ #include "../vendor/jeaiii-ltoa.h"
6
+
7
+ enum fbuffer_type {
8
+ FBUFFER_HEAP_ALLOCATED = 0,
9
+ FBUFFER_STACK_ALLOCATED = 1,
10
+ };
11
+
12
+ typedef struct FBufferStruct {
13
+ enum fbuffer_type type;
14
+ size_t initial_length;
15
+ size_t len;
16
+ size_t capa;
17
+ #if JSON_DEBUG
18
+ size_t requested;
19
+ #endif
20
+ char *ptr;
21
+ VALUE io;
22
+ } FBuffer;
23
+
24
+ #define FBUFFER_STACK_SIZE 512
25
+ #define FBUFFER_IO_BUFFER_SIZE (16384 - 1)
26
+ #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
27
+
28
+ #define FBUFFER_PTR(fb) ((fb)->ptr)
29
+ #define FBUFFER_LEN(fb) ((fb)->len)
30
+ #define FBUFFER_CAPA(fb) ((fb)->capa)
31
+ #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
32
+
33
+ static void fbuffer_free(FBuffer *fb);
34
+ static void fbuffer_clear(FBuffer *fb);
35
+ static void fbuffer_append(FBuffer *fb, const char *newstr, size_t len);
36
+ static void fbuffer_append_long(FBuffer *fb, long number);
37
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr);
38
+ static VALUE fbuffer_finalize(FBuffer *fb);
39
+
40
+ static void fbuffer_init(FBuffer *fb, size_t initial_length, VALUE io, char *stack_buffer, size_t stack_buffer_size)
41
+ {
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 {
47
+ fb->type = FBUFFER_STACK_ALLOCATED;
48
+ fb->ptr = stack_buffer;
49
+ fb->capa = stack_buffer_size;
50
+ fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
51
+ }
52
+ #if JSON_DEBUG
53
+ fb->requested = 0;
54
+ #endif
55
+ }
56
+
57
+ static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
58
+ {
59
+ #if JSON_DEBUG
60
+ if (consumed > fb->requested) {
61
+ rb_bug("fbuffer: Out of bound write");
62
+ }
63
+ fb->requested = 0;
64
+ #endif
65
+ fb->len += consumed;
66
+ }
67
+
68
+ static void fbuffer_free(FBuffer *fb)
69
+ {
70
+ if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
71
+ JSON_SIZED_FREE_N(fb->ptr, fb->capa);
72
+ }
73
+ }
74
+
75
+ static void fbuffer_clear(FBuffer *fb)
76
+ {
77
+ fb->len = 0;
78
+ }
79
+
80
+ static void fbuffer_flush(FBuffer *fb)
81
+ {
82
+ rb_io_write(fb->io, rb_utf8_str_new(fb->ptr, fb->len));
83
+ fbuffer_clear(fb);
84
+ }
85
+
86
+ static void fbuffer_realloc(FBuffer *fb, size_t new_capa)
87
+ {
88
+ if (new_capa > fb->capa) {
89
+ if (fb->type == FBUFFER_STACK_ALLOCATED) {
90
+ const char *old_buffer = fb->ptr;
91
+ fb->ptr = ALLOC_N(char, new_capa);
92
+ fb->type = FBUFFER_HEAP_ALLOCATED;
93
+ MEMCPY(fb->ptr, old_buffer, char, fb->len);
94
+ } else {
95
+ JSON_SIZED_REALLOC_N(fb->ptr, char, new_capa, fb->capa);
96
+ }
97
+ fb->capa = new_capa;
98
+ }
99
+ }
100
+
101
+ static void fbuffer_do_inc_capa(FBuffer *fb, size_t requested)
102
+ {
103
+ if (RB_UNLIKELY(fb->io)) {
104
+ if (fb->capa != 0) {
105
+ fbuffer_flush(fb);
106
+ if (RB_LIKELY(requested < fb->capa)) {
107
+ return;
108
+ }
109
+ }
110
+ }
111
+
112
+ size_t new_capa = fb->capa ? fb->capa : fb->initial_length;
113
+ size_t needed_capa = requested + fb->len;
114
+
115
+ while (new_capa < needed_capa) {
116
+ new_capa *= 2;
117
+ }
118
+
119
+ fbuffer_realloc(fb, new_capa);
120
+ }
121
+
122
+ static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested)
123
+ {
124
+ #if JSON_DEBUG
125
+ fb->requested = requested;
126
+ #endif
127
+
128
+ if (RB_UNLIKELY(requested > fb->capa - fb->len)) {
129
+ fbuffer_do_inc_capa(fb, requested);
130
+ }
131
+ }
132
+
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)
149
+ {
150
+ if (len > 0) {
151
+ fbuffer_inc_capa(fb, len);
152
+ fbuffer_append_reserved(fb, newstr, len);
153
+ }
154
+ }
155
+
156
+ /* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
157
+ static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
158
+ {
159
+ #if JSON_DEBUG
160
+ if (fb->requested < 1) {
161
+ rb_bug("fbuffer: unreserved write");
162
+ }
163
+ fb->requested--;
164
+ #endif
165
+
166
+ fb->ptr[fb->len] = chr;
167
+ fb->len++;
168
+ }
169
+
170
+ static void fbuffer_append_str(FBuffer *fb, VALUE str)
171
+ {
172
+ const char *ptr;
173
+ size_t len;
174
+ RSTRING_GETMEM(str, ptr, len);
175
+
176
+ fbuffer_append(fb, ptr, len);
177
+ RB_GC_GUARD(str);
178
+ }
179
+
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);
195
+ }
196
+
197
+ static inline void fbuffer_append_char(FBuffer *fb, char newchr)
198
+ {
199
+ fbuffer_inc_capa(fb, 1);
200
+ *(fb->ptr + fb->len) = newchr;
201
+ fbuffer_consumed(fb, 1);
202
+ }
203
+
204
+ static inline char *fbuffer_cursor(FBuffer *fb)
205
+ {
206
+ return fb->ptr + fb->len;
207
+ }
208
+
209
+ static inline void fbuffer_advance_to(FBuffer *fb, char *end)
210
+ {
211
+ fbuffer_consumed(fb, (end - fb->ptr) - fb->len);
212
+ }
213
+
214
+ /*
215
+ * Appends the decimal string representation of \a number into the buffer.
216
+ */
217
+ static void fbuffer_append_long(FBuffer *fb, long number)
218
+ {
219
+ /*
220
+ * The jeaiii_ultoa() function produces digits left-to-right,
221
+ * allowing us to write directly into the buffer, but we don't know
222
+ * the number of resulting characters.
223
+ *
224
+ * We do know, however, that the `number` argument is always in the
225
+ * range 0xc000000000000000 to 0x3fffffffffffffff, or, in decimal,
226
+ * -4611686018427387904 to 4611686018427387903. The max number of chars
227
+ * generated is therefore 20 (including a potential sign character).
228
+ */
229
+
230
+ static const int MAX_CHARS_FOR_LONG = 20;
231
+
232
+ fbuffer_inc_capa(fb, MAX_CHARS_FOR_LONG);
233
+
234
+ if (number < 0) {
235
+ fbuffer_append_reserved_char(fb, '-');
236
+
237
+ /*
238
+ * Since number is always > LONG_MIN, `-number` will not overflow
239
+ * and is always the positive abs() value.
240
+ */
241
+ number = -number;
242
+ }
243
+
244
+ char *end = jeaiii_ultoa(fbuffer_cursor(fb), number);
245
+ fbuffer_advance_to(fb, end);
246
+ }
247
+
248
+ static VALUE fbuffer_finalize(FBuffer *fb)
249
+ {
250
+ if (fb->io) {
251
+ fbuffer_flush(fb);
252
+ rb_io_flush(fb->io);
253
+ return fb->io;
254
+ } else {
255
+ return rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
256
+ }
257
+ }
258
+
259
+ #endif // _FBUFFER_H_
@@ -0,0 +1,19 @@
1
+ require 'mkmf'
2
+
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
+ have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
9
+ have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
10
+
11
+ $defs << "-DJSON_GENERATOR"
12
+ $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
13
+
14
+ if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
15
+ load __dir__ + "/../simd/conf.rb"
16
+ end
17
+
18
+ create_makefile 'json/ext/generator'
19
+ end