rapidjson 0.2.0 → 0.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4824f0636d8f801de840ebf32bd639258ce1e21a063228beaabd2b4ad6e1760a
4
- data.tar.gz: 04bdbf36fdfd8b2ef289d8ba6e68b9d34c731cd1ffae61c154dd276ed56dc35e
3
+ metadata.gz: 722ff2bcb2ebfc8ab861d5066e53e938933bd03d2e7f4bca7662233fa0a8a314
4
+ data.tar.gz: 59d25e68af12d81bc3b5517a88de320a76a72c6b5d7cc9d26758084bd604b9fe
5
5
  SHA512:
6
- metadata.gz: 74f3d0a620d505b0aa55601830f294794e8a938ee087d9fcc228fc6a83452c2b255b1ddf9c0b3aea1d086808259e6f75744fcd6fb9528361090d2bea9d35a612
7
- data.tar.gz: cff30c2bafab60f467ee59cf8a63691f93dd2de1fb5f07573e54a1303f3f279f9100ec9e1c6991cf5c9e874c25df3f6dd52b3e549aef3e510d0d068ce50f9877
6
+ metadata.gz: 4eea208e695986e0e312c3794ba44852057f86a8159c4d862518482d263f2d13ef94fff481c38e2d7a79f881a13cef08e65eff4d49ded5c85378891bc79dab85
7
+ data.tar.gz: cafbbb2e33c4adecdfac50d1fc0bb34e3c1b019828af29714b0005a8a24955c3914c79e7a9690161589597b3df12928d6adddad8887014fd48fb36b58525f25d
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  (Maybe) Ruby's fastest JSON library! Built using the [RapidJSON C++ library](https://rapidjson.org/)
4
4
 
5
+ No monkey patches, ActiveSupport integration, `json` gem emulation.
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -42,6 +44,58 @@ RapidJSON.pretty_encode(json_string)
42
44
  # }
43
45
  ```
44
46
 
47
+ By default the encoder is "strict" and will raise an exception
48
+
49
+ ## ActiveSupport
50
+
51
+ RapidJSON provides a drop-in replacement ActiveSupport encoder, with very good compatibility.
52
+ Add the following to an initializer to opt-in.
53
+
54
+ ```
55
+ # config/initializers/rapidjson.rb
56
+
57
+ ActiveSupport::JSON::Encoding.json_encoder = RapidJSON::ActiveSupportEncoder
58
+ ```
59
+
60
+ This makes `model.to_json` ~15x faster, and `nested_hash.to_json` ~27x faster (compred using Rails 7.0)
61
+
62
+ ## JSON gem compatibility
63
+
64
+ Contrary to some other JSON libraries, `RapidJSON` doesn't provice a monkey patch to entirely replace the stdlib JSON gem.
65
+
66
+ However it does provide a module that behave like the stdlib JSON gem and that can be used to monkey patch existing code.
67
+
68
+ ```ruby
69
+ module SomeLibrary
70
+ def do_stuff(payload)
71
+ JSON.parse(payload)
72
+ end
73
+ end
74
+ ```
75
+
76
+ ```ruby
77
+ SomeLibrary::JSON = RapidJSON::JSONGem
78
+ ```
79
+
80
+ Note that this module only use `RapidJSON` when it's certain it is safe to do so. If the JSON gem is called with
81
+ some options that `RapidJSON` doesn't support, it automatically fallbacks to calling the JSON gem.
82
+
83
+ ## Advanced usage
84
+
85
+ By default RapidJSON will only encode "JSON-ready" types: `Hash`, `Array`, `Integer`, `Float`, `String`, `Symbol`, `true`, `false`, and `nil`.
86
+
87
+ RapidJSON::Coder can be initialized with a block which allows the behaviour to be customized. This is how the ActiveSupport encoder and JSON compatibility above are implemented! Just using Ruby :heart:.
88
+
89
+ ```
90
+ RapidJSON::Coder.new do |object, is_key|
91
+ object.to_s # Convert any unknown object to string
92
+ end
93
+ ```
94
+
95
+ The block is called only for unrecognized types. The return value is expected to be a "JSON ready" type which will then be encoded.
96
+
97
+ One additional special type is `RapidJSON::Fragment`, which is interpreted as an existing JSON-encoded string. This can be used to efficiently embed an existing JSON document, or to provide compatibility.
98
+
45
99
  ## Performance
46
100
 
47
101
  Your current JSON parser/encoder is probably fine.
@@ -88,27 +142,6 @@ I spent a week working on YAJL/yajl-ruby, and though I really liked the library,
88
142
 
89
143
  However, if you're happy with your current Ruby JSON library (including `json`) you should keep using it. They're all very good.
90
144
 
91
- ## JSON gem compatibility
92
-
93
- Contrary to some other JSON libraries, `RapidJSON` doesn't provice a monkey patch to entirely replace the stdlib JSON gem.
94
-
95
- However it does provide a module that behave like the stdlib JSON gem and that can be used to monkey patch existing code.
96
-
97
- ```ruby
98
- module SomeLibrary
99
- def do_stuff(payload)
100
- JSON.parse(payload)
101
- end
102
- end
103
- ```
104
-
105
- ```ruby
106
- SomeLibrary::JSON = RapidJSON::JSONGem
107
- ```
108
-
109
- Note that this module only use `RapidJSON` when it's certain it is safe to do so. If the JSON gem is called with
110
- some options that `RapidJSON` doesn't support, it automatically fallbacks to calling the JSON gem.
111
-
112
145
  ## Development
113
146
 
114
147
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -12,9 +12,16 @@ class RubyStringBuffer {
12
12
  mem = RSTRING_PTR(ruby_string);
13
13
  }
14
14
 
15
- void Reserve(size_t size) {
16
- if (capacity - used < size) {
17
- resize(capacity * 2);
15
+ void Reserve(size_t want) {
16
+ if (capacity - used < want) {
17
+ size_t new_capacity = capacity;
18
+ while (new_capacity - used < want) {
19
+ if (new_capacity >= SIZE_MAX / 2) {
20
+ ruby_malloc_size_overflow(capacity, 2);
21
+ }
22
+ new_capacity <<= 1;
23
+ }
24
+ resize(new_capacity);
18
25
  }
19
26
  }
20
27
 
@@ -0,0 +1,90 @@
1
+ #include "ruby.h"
2
+ #include "ruby/encoding.h"
3
+
4
+ /* strlen("\\u2029") == 6 */
5
+ #define ESCAPE_JSON_MAX_LEN 6
6
+
7
+ static inline long
8
+ json_escaped_length(VALUE str)
9
+ {
10
+ const long len = RSTRING_LEN(str);
11
+ if (len >= LONG_MAX / ESCAPE_JSON_MAX_LEN) {
12
+ ruby_malloc_size_overflow(len, ESCAPE_JSON_MAX_LEN);
13
+ }
14
+ return len * ESCAPE_JSON_MAX_LEN;
15
+ }
16
+
17
+ static VALUE
18
+ escape_json(VALUE self, VALUE str)
19
+ {
20
+ if (!RB_TYPE_P(str, T_STRING)) {
21
+ str = rb_convert_type(str, T_STRING, "String", "to_s");
22
+ }
23
+
24
+ rb_encoding *enc = rb_enc_get(str);
25
+ if (enc != rb_utf8_encoding() && enc != rb_usascii_encoding()) {
26
+ rb_raise(rb_eEncCompatError, "input string must be UTF-8 or ASCII");
27
+ }
28
+
29
+ const char *cstr = RSTRING_PTR(str);
30
+ const unsigned long str_len = RSTRING_LEN(str);
31
+ const char *end = cstr + RSTRING_LEN(str);
32
+
33
+ size_t initial_match = strcspn(cstr, "&<>\xe2");
34
+ if (initial_match == str_len) {
35
+ return str;
36
+ }
37
+
38
+ VALUE escaped = rb_str_buf_new(json_escaped_length(str));
39
+ rb_str_resize(escaped, json_escaped_length(str));
40
+ char *buf = RSTRING_PTR(escaped);
41
+ char *dest = buf;
42
+
43
+ memcpy(dest, cstr, initial_match);
44
+ cstr += initial_match;
45
+ dest += initial_match;
46
+
47
+ while (cstr < end) {
48
+ const char c = *cstr++;
49
+
50
+ #define JSON_ESCAPE_CONCAT(s) do { \
51
+ memcpy(dest, ("\\u" s), strlen(s) + 2); \
52
+ dest += strlen(s) + 2; \
53
+ } while (0)
54
+
55
+ if (0) {
56
+ }
57
+ else if (c == '&') {
58
+ JSON_ESCAPE_CONCAT("0026");
59
+ }
60
+ else if (c == '>') {
61
+ JSON_ESCAPE_CONCAT("003e");
62
+ }
63
+ else if (c == '<') {
64
+ JSON_ESCAPE_CONCAT("003c");
65
+ }
66
+ else if (c == '\xe2' && cstr[0] == '\x80' && cstr[1] == '\xa8') {
67
+ JSON_ESCAPE_CONCAT("2028");
68
+ cstr += 2;
69
+ }
70
+ else if (c == '\xe2' && cstr[0] == '\x80' && cstr[1] == '\xa9') {
71
+ JSON_ESCAPE_CONCAT("2029");
72
+ cstr += 2;
73
+ }
74
+ else {
75
+ *dest++ = c;
76
+ }
77
+
78
+ initial_match = strcspn(cstr, "&<>\xe2");
79
+ memcpy(dest, cstr, initial_match);
80
+ cstr += initial_match;
81
+ dest += initial_match;
82
+
83
+ #undef JSON_ESCAPE_CONCAT
84
+ }
85
+
86
+ rb_str_resize(escaped, dest - buf);
87
+ rb_enc_associate(escaped, rb_enc_get(str));
88
+
89
+ return escaped;
90
+ }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RapidJSON
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rapidjson
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Hawthorn
@@ -27,6 +27,7 @@ files:
27
27
  - ext/rapidjson/cext.hh
28
28
  - ext/rapidjson/encoder.hh
29
29
  - ext/rapidjson/extconf.rb
30
+ - ext/rapidjson/json_escape.h
30
31
  - ext/rapidjson/parser.hh
31
32
  - ext/rapidjson/rapidjson/include/rapidjson/allocators.h
32
33
  - ext/rapidjson/rapidjson/include/rapidjson/cursorstreamwrapper.h