simdjson 4.1.0
Ridiculously Fast JSON
Loading...
Searching...
No Matches
raw_json_string-inl.h
1#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
2
3#ifndef SIMDJSON_CONDITIONAL_INCLUDE
4#define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
5#include "simdjson/generic/ondemand/base.h"
6#include "simdjson/generic/ondemand/raw_json_string.h"
7#include "simdjson/generic/ondemand/json_iterator-inl.h"
8#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
9#endif // SIMDJSON_CONDITIONAL_INCLUDE
10
11namespace simdjson {
12
13namespace SIMDJSON_IMPLEMENTATION {
14namespace ondemand {
15
16simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
17
18simdjson_inline const char * raw_json_string::raw() const noexcept {
19 return reinterpret_cast<const char *>(buf);
20}
21
22simdjson_inline char raw_json_string::operator[](size_t i) const noexcept {
23 return reinterpret_cast<const char *>(buf)[i];
24}
25
26simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
27 size_t pos{0};
28 while(pos < target.size()) {
29 pos = target.find('"', pos);
30 if(pos == std::string_view::npos) { return true; }
31 if(pos != 0 && target[pos-1] != '\\') { return false; }
32 if(pos > 1 && target[pos-2] == '\\') {
33 size_t backslash_count{2};
34 for(size_t i = 3; i <= pos; i++) {
35 if(target[pos-i] == '\\') { backslash_count++; }
36 else { break; }
37 }
38 if(backslash_count % 2 == 0) { return false; }
39 }
40 pos++;
41 }
42 return true;
43}
44
45simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
46 size_t pos{0};
47 while(target[pos]) {
48 const char * result = strchr(target+pos, '"');
49 if(result == nullptr) { return true; }
50 pos = result - target;
51 if(pos != 0 && target[pos-1] != '\\') { return false; }
52 if(pos > 1 && target[pos-2] == '\\') {
53 size_t backslash_count{2};
54 for(size_t i = 3; i <= pos; i++) {
55 if(target[pos-i] == '\\') { backslash_count++; }
56 else { break; }
57 }
58 if(backslash_count % 2 == 0) { return false; }
59 }
60 pos++;
61 }
62 return true;
63}
64
65
66simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
67 // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
68 return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
69}
70
71simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
72 // Assumptions: does not contain unescaped quote characters("), and
73 // the raw content is quote terminated within a valid JSON string.
74 if(target.size() <= SIMDJSON_PADDING) {
75 return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
76 }
77 const char * r{raw()};
78 size_t pos{0};
79 for(;pos < target.size();pos++) {
80 if(r[pos] != target[pos]) { return false; }
81 }
82 if(r[pos] != '"') { return false; }
83 return true;
84}
85
86simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
87 const char * r{raw()};
88 size_t pos{0};
89 bool escaping{false};
90 for(;pos < target.size();pos++) {
91 if(r[pos] != target[pos]) { return false; }
92 // if target is a compile-time constant and it is free from
93 // quotes, then the next part could get optimized away through
94 // inlining.
95 if((target[pos] == '"') && !escaping) {
96 // We have reached the end of the raw_json_string but
97 // the target is not done.
98 return false;
99 } else if(target[pos] == '\\') {
100 escaping = !escaping;
101 } else {
102 escaping = false;
103 }
104 }
105 if(r[pos] != '"') { return false; }
106 return true;
107}
108
109
110simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
111 // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
112 // the raw content is quote terminated within a valid JSON string.
113 const char * r{raw()};
114 size_t pos{0};
115 for(;target[pos];pos++) {
116 if(r[pos] != target[pos]) { return false; }
117 }
118 if(r[pos] != '"') { return false; }
119 return true;
120}
121
122simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
123 // Assumptions: does not contain unescaped quote characters, and
124 // the raw content is quote terminated within a valid JSON string.
125 const char * r{raw()};
126 size_t pos{0};
127 bool escaping{false};
128 for(;target[pos];pos++) {
129 if(r[pos] != target[pos]) { return false; }
130 // if target is a compile-time constant and it is free from
131 // quotes, then the next part could get optimized away through
132 // inlining.
133 if((target[pos] == '"') && !escaping) {
134 // We have reached the end of the raw_json_string but
135 // the target is not done.
136 return false;
137 } else if(target[pos] == '\\') {
138 escaping = !escaping;
139 } else {
140 escaping = false;
141 }
142 }
143 if(r[pos] != '"') { return false; }
144 return true;
145}
146
147simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
148 return a.unsafe_is_equal(c);
149}
150
151simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
152 return a == c;
153}
154
155simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
156 return !(a == c);
157}
158
159simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
160 return !(a == c);
161}
162
163
164simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
165 return iter.unescape(*this, allow_replacement);
166}
167
168simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
169 return iter.unescape_wobbly(*this);
170}
171
172simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
173 bool in_escape = false;
174 const char *s = str.raw();
175 while (true) {
176 switch (*s) {
177 case '\\': in_escape = !in_escape; break;
178 case '"': if (in_escape) { in_escape = false; } else { return out; } break;
179 default: if (in_escape) { in_escape = false; }
180 }
181 out << *s;
182 s++;
183 }
184}
185
186} // namespace ondemand
187} // namespace SIMDJSON_IMPLEMENTATION
188} // namespace simdjson
189
190namespace simdjson {
191
192simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string &&value) noexcept
193 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>(value)) {}
194simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
195 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>(error) {}
196
197simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::raw() const noexcept {
198 if (error()) { return error(); }
199 return first.raw();
200}
201simdjson_inline char simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::operator[](size_t i) const noexcept {
202 if (error()) { return error(); }
203 return first[i];
204}
205simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::unescape(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
206 if (error()) { return error(); }
207 return first.unescape(iter, allow_replacement);
208}
209simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::unescape_wobbly(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &iter) const noexcept {
210 if (error()) { return error(); }
211 return first.unescape_wobbly(iter);
212}
213} // namespace simdjson
214
215#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
A string escaped per JSON rules, terminated with quote (").
simdjson_inline bool is_equal(std::string_view target) const noexcept
This compares the current instance to the std::string_view target: returns true if they are byte-by-b...
static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept
Returns true if target is free from unescaped quote.
simdjson_inline raw_json_string() noexcept=default
Create a new invalid raw_json_string.
simdjson_inline const char * raw() const noexcept
Get the raw pointer to the beginning of the string in the JSON (just after the ").
simdjson_inline char operator[](size_t i) const noexcept
Get the character at index i.
simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept
This compares the current instance to the std::string_view target: returns true if they are byte-by-b...
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept
Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user i...
The top level simdjson namespace, containing everything the library provides.
Definition base.h:8
error_code
All possible errors returned by simdjson.
Definition error.h:19
constexpr size_t SIMDJSON_PADDING
The amount of padding needed in a buffer to parse JSON.
Definition base.h:33