Skip to content

Commit a24db1f

Browse files
committed
src: use simdjson
1 parent e665231 commit a24db1f

File tree

2 files changed

+107
-112
lines changed

2 files changed

+107
-112
lines changed

src/json_parser.cc

Lines changed: 104 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,156 @@
11
#include "json_parser.h"
2-
#include "node_errors.h"
3-
#include "node_v8_platform-inl.h"
4-
#include "util-inl.h"
2+
#include "debug_utils.h"
53

64
namespace node {
7-
using v8::Array;
8-
using v8::Context;
9-
using v8::Isolate;
10-
using v8::Local;
11-
using v8::Object;
12-
using v8::String;
13-
using v8::Value;
145

156
JSONParser::JSONParser() {}
167

178
bool JSONParser::Parse(const std::string& content) {
189
DCHECK(!parsed_);
1910

20-
Isolate* isolate = isolate_.get();
21-
v8::Locker locker(isolate);
22-
v8::Isolate::Scope isolate_scope(isolate);
23-
v8::HandleScope handle_scope(isolate);
24-
25-
Local<Context> context = Context::New(isolate);
26-
Context::Scope context_scope(context);
27-
28-
// It's not a real script, so don't print the source line.
29-
errors::PrinterTryCatch bootstrapCatch(
30-
isolate, errors::PrinterTryCatch::kDontPrintSourceLine);
31-
Local<Value> json_string_value;
32-
Local<Value> result_value;
33-
if (!ToV8Value(context, content).ToLocal(&json_string_value) ||
34-
!json_string_value->IsString() ||
35-
!v8::JSON::Parse(context, json_string_value.As<String>())
36-
.ToLocal(&result_value) ||
37-
!result_value->IsObject()) {
11+
json_content_ = content;
12+
size_t json_length = json_content_.size();
13+
json_content_.append(simdjson::SIMDJSON_PADDING, ' ');
14+
15+
simdjson::padded_string_view json_view(json_content_.data(),
16+
json_length,
17+
json_content_.size());
18+
19+
simdjson::ondemand::document document;
20+
simdjson::error_code error = parser_.iterate(json_view).get(document);
21+
22+
if (error != simdjson::SUCCESS) {
3823
return false;
3924
}
4025

41-
context_.Reset(isolate, context);
42-
content_.Reset(isolate, result_value.As<Object>());
43-
parsed_ = true;
26+
simdjson::ondemand::object obj;
27+
error = document.get_object().get(obj);
28+
if (error != simdjson::SUCCESS) {
29+
return false;
30+
}
4431

32+
parsed_ = true;
4533
return true;
4634
}
4735

4836
std::optional<std::string> JSONParser::GetTopLevelStringField(
4937
std::string_view field) {
50-
Isolate* isolate = isolate_.get();
51-
v8::Locker locker(isolate);
52-
v8::Isolate::Scope isolate_scope(isolate);
53-
v8::HandleScope handle_scope(isolate);
54-
55-
Local<Context> context = context_.Get(isolate);
56-
Context::Scope context_scope(context);
57-
58-
Local<Object> content_object = content_.Get(isolate);
59-
60-
Local<Value> value;
61-
// It's not a real script, so don't print the source line.
62-
errors::PrinterTryCatch bootstrapCatch(
63-
isolate, errors::PrinterTryCatch::kDontPrintSourceLine);
64-
Local<Value> field_local;
65-
if (!ToV8Value(context, field, isolate).ToLocal(&field_local)) {
38+
if (!parsed_) {
6639
return {};
6740
}
68-
if (!content_object->Get(context, field_local).ToLocal(&value) ||
69-
!value->IsString()) {
41+
42+
simdjson::padded_string_view json_view(json_content_.data(),
43+
json_content_.size() - simdjson::SIMDJSON_PADDING,
44+
json_content_.size());
45+
46+
simdjson::ondemand::document document;
47+
simdjson::error_code error = parser_.iterate(json_view).get(document);
48+
if (error != simdjson::SUCCESS) {
7049
return {};
7150
}
72-
Utf8Value utf8_value(isolate, value);
73-
return utf8_value.ToString();
51+
52+
simdjson::ondemand::object obj;
53+
error = document.get_object().get(obj);
54+
if (error != simdjson::SUCCESS) {
55+
return {};
56+
}
57+
58+
std::string_view result;
59+
error = obj[field].get_string().get(result);
60+
if (error != simdjson::SUCCESS) {
61+
return {};
62+
}
63+
64+
return std::string(result);
7465
}
7566

7667
std::optional<bool> JSONParser::GetTopLevelBoolField(std::string_view field) {
77-
Isolate* isolate = isolate_.get();
78-
v8::Locker locker(isolate);
79-
v8::Isolate::Scope isolate_scope(isolate);
80-
v8::HandleScope handle_scope(isolate);
81-
82-
Local<Context> context = context_.Get(isolate);
83-
Context::Scope context_scope(context);
84-
85-
Local<Object> content_object = content_.Get(isolate);
86-
Local<Value> value;
87-
bool has_field;
88-
// It's not a real script, so don't print the source line.
89-
errors::PrinterTryCatch bootstrapCatch(
90-
isolate, errors::PrinterTryCatch::kDontPrintSourceLine);
91-
Local<Value> field_local;
92-
if (!ToV8Value(context, field, isolate).ToLocal(&field_local)) {
68+
if (!parsed_) {
9369
return {};
9470
}
95-
if (!content_object->Has(context, field_local).To(&has_field)) {
71+
72+
simdjson::padded_string_view json_view(json_content_.data(),
73+
json_content_.size() - simdjson::SIMDJSON_PADDING,
74+
json_content_.size());
75+
76+
simdjson::ondemand::document document;
77+
simdjson::error_code error = parser_.iterate(json_view).get(document);
78+
if (error != simdjson::SUCCESS) {
9679
return {};
9780
}
98-
if (!has_field) {
81+
82+
simdjson::ondemand::object obj;
83+
error = document.get_object().get(obj);
84+
if (error != simdjson::SUCCESS) {
85+
return {};
86+
}
87+
88+
simdjson::ondemand::value val;
89+
error = obj[field].get(val);
90+
if (error != simdjson::SUCCESS) {
9991
return false;
10092
}
101-
if (!content_object->Get(context, field_local).ToLocal(&value) ||
102-
!value->IsBoolean()) {
93+
94+
bool result;
95+
error = val.get_bool().get(result);
96+
if (error != simdjson::SUCCESS) {
10397
return {};
10498
}
105-
return value->BooleanValue(isolate);
99+
100+
return result;
106101
}
107102

108103
std::optional<JSONParser::StringDict> JSONParser::GetTopLevelStringDict(
109104
std::string_view field) {
110-
Isolate* isolate = isolate_.get();
111-
v8::Locker locker(isolate);
112-
v8::Isolate::Scope isolate_scope(isolate);
113-
v8::HandleScope handle_scope(isolate);
114-
Local<Context> context = context_.Get(isolate);
115-
Local<Object> content_object = content_.Get(isolate);
116-
Local<Value> value;
117-
bool has_field;
118-
// It's not a real script, so don't print the source line.
119-
errors::PrinterTryCatch bootstrapCatch(
120-
isolate, errors::PrinterTryCatch::kDontPrintSourceLine);
121-
Local<Value> field_local;
122-
if (!ToV8Value(context, field, isolate).ToLocal(&field_local)) {
105+
if (!parsed_) {
123106
return std::nullopt;
124107
}
125-
if (!content_object->Has(context, field_local).To(&has_field)) {
108+
109+
simdjson::padded_string_view json_view(json_content_.data(),
110+
json_content_.size() - simdjson::SIMDJSON_PADDING,
111+
json_content_.size());
112+
113+
simdjson::ondemand::document document;
114+
simdjson::error_code error = parser_.iterate(json_view).get(document);
115+
if (error != simdjson::SUCCESS) {
126116
return std::nullopt;
127117
}
128-
if (!has_field) {
129-
return StringDict();
130-
}
131-
if (!content_object->Get(context, field_local).ToLocal(&value) ||
132-
!value->IsObject()) {
118+
119+
simdjson::ondemand::object obj;
120+
error = document.get_object().get(obj);
121+
if (error != simdjson::SUCCESS) {
133122
return std::nullopt;
134123
}
135-
Local<Object> dict = value.As<Object>();
136-
Local<Array> keys;
137-
if (!dict->GetOwnPropertyNames(context).ToLocal(&keys)) {
124+
125+
simdjson::ondemand::value val;
126+
error = obj[field].get(val);
127+
if (error != simdjson::SUCCESS) {
128+
return StringDict();
129+
}
130+
131+
simdjson::ondemand::object dict;
132+
error = val.get_object().get(dict);
133+
if (error != simdjson::SUCCESS) {
138134
return std::nullopt;
139135
}
140-
std::unordered_map<std::string, std::string> result;
141-
uint32_t length = keys->Length();
142-
for (uint32_t i = 0; i < length; ++i) {
143-
Local<Value> key;
144-
Local<Value> value;
145-
if (!keys->Get(context, i).ToLocal(&key) || !key->IsString())
136+
137+
StringDict result;
138+
for (auto field_value : dict) {
139+
std::string_view key_view;
140+
error = field_value.unescaped_key().get(key_view);
141+
if (error != simdjson::SUCCESS) {
146142
return StringDict();
147-
if (!dict->Get(context, key).ToLocal(&value) || !value->IsString())
143+
}
144+
145+
std::string_view value_view;
146+
error = field_value.value().get_string().get(value_view);
147+
if (error != simdjson::SUCCESS) {
148148
return StringDict();
149+
}
149150

150-
Utf8Value key_utf8(isolate, key);
151-
Utf8Value value_utf8(isolate, value);
152-
result.emplace(*key_utf8, *value_utf8);
151+
result.emplace(std::string(key_view), std::string(value_view));
153152
}
153+
154154
return result;
155155
}
156156

src/json_parser.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
#include <optional>
88
#include <string>
99
#include <unordered_map>
10-
#include "util.h"
11-
#include "v8.h"
10+
#include "simdjson.h"
1211

1312
namespace node {
1413
// This is intended to be used to get some top-level fields out of a JSON
@@ -25,12 +24,8 @@ class JSONParser {
2524
std::optional<StringDict> GetTopLevelStringDict(std::string_view field);
2625

2726
private:
28-
// We might want a lighter-weight JSON parser for this use case. But for now
29-
// using V8 is good enough.
30-
RAIIIsolateWithoutEntering isolate_;
31-
32-
v8::Global<v8::Context> context_;
33-
v8::Global<v8::Object> content_;
27+
simdjson::ondemand::parser parser_;
28+
std::string json_content_;
3429
bool parsed_ = false;
3530
};
3631
} // namespace node

0 commit comments

Comments
 (0)