Line data Source code
1 : /**
2 : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_DATA_SPDATADECODEJSON_H_
25 : #define STAPPLER_DATA_SPDATADECODEJSON_H_
26 :
27 : #include "SPDataValue.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::data::json {
30 :
31 5091150 : inline StringView decodeNumber(StringView &r, bool &isFloat) {
32 5091150 : auto tmp = r;
33 5091150 : if (r.is('-')) {
34 16275 : ++ r;
35 : }
36 5091150 : r.skipChars<StringView::CharGroup<CharGroupId::Numbers>>();
37 5091150 : if (r.is('.')) {
38 29100 : isFloat = true;
39 29100 : ++ r;
40 29100 : r.skipChars<StringView::CharGroup<CharGroupId::Numbers>>();
41 : }
42 5091150 : if (r.is('E') || r.is('e')) {
43 7275 : isFloat = true;
44 7275 : ++ r;
45 7275 : if (r.is('+') || r.is('-')) {
46 7225 : ++ r;
47 : }
48 7275 : r.skipChars<StringView::CharGroup<CharGroupId::Numbers>>();
49 : }
50 :
51 5091150 : return StringView(tmp.data(), tmp.size() - r.size());
52 : }
53 :
54 : template <typename Interface>
55 : struct Decoder : public Interface::AllocBaseType {
56 : using InterfaceType = Interface;
57 : using ValueType = ValueTemplate<Interface>;
58 : using StringType = typename InterfaceType::StringType;
59 :
60 : enum BackType {
61 : BackIsArray,
62 : BackIsDict,
63 : BackIsEmpty
64 : };
65 :
66 17775 : Decoder(StringView &r, bool v) : validate(v), backType(BackIsEmpty), r(r), back(nullptr) {
67 17775 : stack.reserve(10);
68 17775 : }
69 :
70 : inline void parseBufferString(StringType &ref);
71 : inline void parseJsonNumber(ValueType &ref) SPINLINE;
72 :
73 : inline void parseValue(ValueType ¤t);
74 : void parseJson(ValueType &val);
75 :
76 15252800 : inline void push(BackType t, ValueType *v) {
77 15252800 : ++ r;
78 15252800 : back = v;
79 15252800 : stack.push_back(v);
80 15252800 : backType = t;
81 15252800 : }
82 :
83 15252800 : inline void pop() {
84 15252800 : r ++;
85 15252800 : stack.pop_back();
86 15252800 : if (stack.empty()) {
87 15925 : back = nullptr;
88 15925 : backType = BackIsEmpty;
89 : } else {
90 15236875 : back = stack.back();
91 15236875 : backType = (back->isArray())?BackIsArray:BackIsDict;
92 : }
93 15252800 : }
94 :
95 : bool validate;
96 : bool stop = false;
97 : BackType backType;
98 : StringView r;
99 : ValueType *back;
100 : StringType buf;
101 : typename InterfaceType::template ArrayType<ValueType *> stack;
102 : };
103 :
104 : template <typename Interface>
105 108472250 : inline void Decoder<Interface>::parseBufferString(StringType &ref) {
106 : #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
107 : static const char escape[256] = {
108 : Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0, 0, 0,'/',
109 : Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
110 : 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
111 : 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 : Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
113 : };
114 : #undef Z16
115 108472250 : if (r.is('"')) { r ++; }
116 108472250 : auto s = r.readUntil<StringView::Chars<'\\', '"'>>();
117 108472250 : ref.assign(s.data(), s.size());
118 109777650 : while (!r.empty() && !r.is('"')) {
119 1305400 : if (r.is('\\')) {
120 1305400 : ++ r;
121 1305400 : if (r.is('u')) {
122 0 : ++ r;
123 0 : if (r >= 4) {
124 0 : unicode::utf8Encode(ref, char16_t(base16::hexToChar(r[0], r[1]) << 8 | base16::hexToChar(r[2], r[3]) ));
125 0 : r += 4;
126 : } else {
127 0 : r.clear();
128 : }
129 : } else {
130 1305400 : ref.push_back(escape[(uint8_t)r[0]]);
131 1305400 : ++ r;
132 : }
133 : }
134 1305400 : auto s = r.readUntil<StringView::Chars<'\\', '"'>>();
135 1305400 : ref.append(s.data(), s.size());
136 : }
137 108472250 : if (r.is('"')) { ++ r; }
138 108472250 : }
139 :
140 : template <typename Interface>
141 : inline void Decoder<Interface>::parseJsonNumber(ValueType &result) {
142 5090500 : bool isFloat = false;
143 5090500 : auto value = decodeNumber(r, isFloat);
144 5090500 : if (value.empty()) {
145 0 : return;
146 : } else {
147 5090500 : if (isFloat) {
148 58250 : value.readDouble().unwrap([&] (double v) {
149 29125 : result._type = ValueType::Type::DOUBLE;
150 29125 : result.doubleVal = v;
151 : });
152 : } else {
153 10122750 : value.readInteger().unwrap([&] (int64_t v) {
154 5061375 : result._type = ValueType::Type::INTEGER;
155 5061375 : result.intVal = v;
156 : });
157 : }
158 : }
159 : }
160 :
161 : template <typename Interface>
162 71959100 : inline void Decoder<Interface>::parseValue(ValueType ¤t) {
163 71959100 : switch(r[0]) {
164 42758575 : case '"':
165 42758575 : current._type = ValueType::Type::CHARSTRING;
166 42758575 : parseBufferString(buf);
167 42758575 : current.strVal = new StringType(std::move(buf));
168 42758575 : break;
169 2665150 : case 't':
170 2665150 : current._type = ValueType::Type::BOOLEAN;
171 2665150 : current.boolVal = true;
172 2665150 : r += 4;
173 2665150 : break;
174 6171175 : case 'f':
175 6171175 : current._type = ValueType::Type::BOOLEAN;
176 6171175 : current.boolVal = false;
177 6171175 : r += 5;
178 6171175 : break;
179 5090500 : case '0': case '1': case '2': case '3': case '4': case '5':
180 : case '6': case '7': case '8': case '9': case '+': case '-':
181 : parseJsonNumber(current);
182 5090500 : break;
183 3639700 : case '[':
184 3639700 : current._type = ValueType::Type::ARRAY;
185 3851325 : current.arrayVal = new typename ValueType::ArrayType();
186 : //current.arrayVal->reserve(10);
187 3639700 : push(BackIsArray, ¤t);
188 3639700 : break;
189 11613100 : case '{':
190 11613100 : current._type = ValueType::Type::DICTIONARY;
191 12149975 : current.dictVal = new typename ValueType::DictionaryType();
192 11613100 : push(BackIsDict, ¤t);
193 11613100 : break;
194 20900 : case 'n':
195 20900 : if (r.is("nan")) {
196 0 : current._type = ValueType::Type::DOUBLE;
197 0 : current.doubleVal = nan();
198 0 : r += 3;
199 : } else {
200 20900 : r += 4;
201 : }
202 20900 : break;
203 0 : default:
204 0 : r.skipUntil<StringView::Chars<'"', 't', 'f', 'n', '+', '-', '[', '{', ']', '}'>, StringView::Range<'0', '9'>>();
205 0 : break;
206 : }
207 71959100 : }
208 :
209 : template <typename Interface>
210 87211900 : void Decoder<Interface>::parseJson(ValueType &val) {
211 : do {
212 87211900 : switch (backType) {
213 9867350 : case BackIsArray:
214 9867350 : r.skipChars<StringView::Chars<' ', '\n', '\r', '\t', ','>>();
215 9867350 : if (!r.is(']')) {
216 6227650 : back->arrayVal->emplace_back(ValueType::Type::EMPTY);
217 6227650 : parseValue(back->arrayVal->back());
218 : } else {
219 3639700 : back->arrayVal->shrink_to_fit();
220 3639700 : pop();
221 : }
222 9867350 : break;
223 77326775 : case BackIsDict:
224 77326775 : r.skipUntil<StringView::Chars<'"', '}'>>();
225 77326775 : if (!r.is('}')) {
226 65713675 : parseBufferString(buf);
227 65713675 : if (validate) {
228 0 : auto tmp = r.readChars<StringView::Chars<':', ' ', '\n', '\r', '\t'>>();
229 0 : tmp.template skipUntil<StringView::Chars<':'>>();
230 0 : if (!tmp.is(':')) {
231 0 : stop = true;
232 0 : return;
233 : }
234 : } else {
235 65713675 : r.skipChars<StringView::Chars<':', ' ', '\n', '\r', '\t'>>();
236 : }
237 65713675 : parseValue(back->dictVal->emplace(std::move(buf), ValueType::Type::EMPTY).first->second);
238 : } else {
239 11613100 : pop();
240 : }
241 77326775 : break;
242 17775 : case BackIsEmpty:
243 17775 : parseValue(val);
244 17775 : break;
245 : }
246 87211900 : } while (!r.empty() && !stack.empty() && !stop);
247 : }
248 :
249 : template <typename Interface>
250 17825 : auto read(StringView &n, bool validate = false) -> ValueTemplate<Interface> {
251 17825 : auto r = n;
252 17825 : if (r.empty() || r == "null") {
253 50 : return ValueTemplate<Interface>();
254 : }
255 :
256 17775 : r.skipChars<StringView::Chars<' ', '\n', '\r', '\t'>>();
257 17775 : Decoder<Interface> dec(r, validate);
258 17775 : ValueTemplate<Interface> ret;
259 17775 : dec.parseJson(ret);
260 17775 : n = dec.r;
261 17775 : return ret;
262 17775 : }
263 :
264 : template <typename Interface>
265 17825 : auto read(const StringView &r) -> ValueTemplate<Interface> {
266 17825 : StringView tmp(r);
267 35650 : return read<Interface>(tmp);
268 : }
269 :
270 : }
271 :
272 : #endif /* STAPPLER_DATA_SPDATADECODEJSON_H_ */
|