Coverage Report

Created: 2026-05-18 00:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/json/simd_json_parser.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
// This file is copied from
18
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Common/JSONParsers/SimdJSONParser.h
19
// and modified by Doris
20
21
#pragma once
22
23
#include <simdjson.h>
24
25
#include <cassert>
26
#include <string>
27
#include <string_view>
28
#include <type_traits>
29
#include <utility>
30
#include <variant>
31
#include <vector>
32
33
#include "core/types.h"
34
35
namespace doris {
36
37
/// This class can be used as an argument for the template class FunctionJSON.
38
/// It provides ability to parse JSONs using simdjson library.
39
class SimdJSONParser {
40
    struct Node {
41
        enum class Type {
42
            INT64,
43
            UINT64,
44
            DOUBLE,
45
            STRING,
46
            ARRAY,
47
            OBJECT,
48
            BOOL,
49
            NULL_VALUE,
50
        };
51
52
        Type type = Type::NULL_VALUE;
53
        Int64 int64_value = 0;
54
        UInt64 uint64_value = 0;
55
        double double_value = 0;
56
        bool bool_value = false;
57
        std::string string_value;
58
        std::string raw_number;
59
        std::vector<Node> array_values;
60
        std::vector<std::string> object_keys;
61
        std::vector<Node> object_values;
62
    };
63
64
public:
65
    class Array;
66
    class Object;
67
    /// References an element in a JSON document, representing a JSON null, boolean, string, number,
68
    /// array or object.
69
    class Element {
70
    public:
71
80.6k
        ALWAYS_INLINE Element() {} /// NOLINT
72
        ALWAYS_INLINE explicit Element(const simdjson::dom::element& element_)
73
3.15M
                : dom_element(element_) {}                                 /// NOLINT
74
34
        ALWAYS_INLINE explicit Element(const Node* node_) : node(node_) {} /// NOLINT
75
1.86M
        ALWAYS_INLINE bool isInt64() const {
76
1.86M
            return node ? node->type == Node::Type::INT64
77
1.86M
                        : dom_element.type() == simdjson::dom::element_type::INT64;
78
1.86M
        }
79
1.06M
        ALWAYS_INLINE bool isUInt64() const {
80
1.06M
            return node ? node->type == Node::Type::UINT64
81
1.06M
                        : dom_element.type() == simdjson::dom::element_type::UINT64;
82
1.06M
        }
83
1.06M
        ALWAYS_INLINE bool isDouble() const {
84
1.06M
            return node ? node->type == Node::Type::DOUBLE
85
1.06M
                        : dom_element.type() == simdjson::dom::element_type::DOUBLE;
86
1.06M
        }
87
944k
        ALWAYS_INLINE bool isString() const {
88
944k
            return node ? node->type == Node::Type::STRING
89
944k
                        : dom_element.type() == simdjson::dom::element_type::STRING;
90
944k
        }
91
3.14M
        ALWAYS_INLINE bool isArray() const {
92
3.14M
            return node ? node->type == Node::Type::ARRAY
93
3.14M
                        : dom_element.type() == simdjson::dom::element_type::ARRAY;
94
3.14M
        }
95
3.21M
        ALWAYS_INLINE bool isObject() const {
96
3.21M
            return node ? node->type == Node::Type::OBJECT
97
3.21M
                        : dom_element.type() == simdjson::dom::element_type::OBJECT;
98
3.21M
        }
99
1.88M
        ALWAYS_INLINE bool isBool() const {
100
1.88M
            return node ? node->type == Node::Type::BOOL
101
1.88M
                        : dom_element.type() == simdjson::dom::element_type::BOOLEAN;
102
1.88M
        }
103
12.0k
        ALWAYS_INLINE bool isNull() const {
104
12.0k
            return node ? node->type == Node::Type::NULL_VALUE
105
12.0k
                        : dom_element.type() == simdjson::dom::element_type::NULL_VALUE;
106
12.0k
        }
107
803k
        ALWAYS_INLINE Int64 getInt64() const {
108
803k
            return node ? node->int64_value : dom_element.get_int64().value_unsafe();
109
803k
        }
110
116k
        ALWAYS_INLINE double getDouble() const {
111
116k
            return node ? node->double_value : dom_element.get_double().value_unsafe();
112
116k
        }
113
20.7k
        ALWAYS_INLINE bool getBool() const {
114
20.7k
            return node ? node->bool_value : dom_element.get_bool().value_unsafe();
115
20.7k
        }
116
932k
        ALWAYS_INLINE std::string_view getString() const {
117
932k
            return node ? std::string_view(node->string_value)
118
932k
                        : dom_element.get_string().value_unsafe();
119
932k
        }
120
21
        ALWAYS_INLINE UInt64 getUInt64() const {
121
21
            return node ? node->uint64_value : dom_element.get_uint64().value_unsafe();
122
21
        }
123
14
        ALWAYS_INLINE std::string_view getRawNumber() const {
124
14
            assert(node != nullptr);
125
14
            return node->raw_number;
126
14
        }
127
        ALWAYS_INLINE Array getArray() const;
128
        ALWAYS_INLINE Object getObject() const;
129
130
    private:
131
        simdjson::dom::element dom_element;
132
        const Node* node = nullptr;
133
    };
134
    /// References an array in a JSON document.
135
    class Array {
136
    public:
137
        class Iterator {
138
        public:
139
            using DomIterator = simdjson::dom::array::iterator;
140
            using NodeIterator = std::vector<Node>::const_iterator;
141
1.96M
            ALWAYS_INLINE explicit Iterator(const DomIterator& it_) : it(it_) {} /// NOLINT
142
14
            ALWAYS_INLINE explicit Iterator(NodeIterator it_) : it(it_) {}       /// NOLINT
143
1.64M
            ALWAYS_INLINE Element operator*() const {
144
1.64M
                if (const auto* node_it = std::get_if<NodeIterator>(&it)) {
145
6
                    return Element(&**node_it);
146
6
                }
147
1.64M
                return Element(*std::get<DomIterator>(it));
148
1.64M
            }
149
1.64M
            ALWAYS_INLINE Iterator& operator++() {
150
1.64M
                if (auto* node_it = std::get_if<NodeIterator>(&it)) {
151
6
                    ++(*node_it);
152
1.64M
                } else {
153
1.64M
                    ++std::get<DomIterator>(it);
154
1.64M
                }
155
1.64M
                return *this;
156
1.64M
            }
157
1.80M
            ALWAYS_INLINE friend bool operator!=(const Iterator& left, const Iterator& right) {
158
1.80M
                if (const auto* left_node_it = std::get_if<NodeIterator>(&left.it)) {
159
10
                    return *left_node_it != std::get<NodeIterator>(right.it);
160
10
                }
161
1.80M
                return std::get<DomIterator>(left.it) != std::get<DomIterator>(right.it);
162
1.80M
            }
163
164
        private:
165
            std::variant<DomIterator, NodeIterator> it;
166
        };
167
        ALWAYS_INLINE explicit Array(const simdjson::dom::array& array_)
168
160k
                : dom_array(array_) {}                                                   /// NOLINT
169
4
        ALWAYS_INLINE explicit Array(const std::vector<Node>* array_) : array(array_) {} /// NOLINT
170
160k
        ALWAYS_INLINE Iterator begin() const {
171
160k
            return array ? Iterator(array->begin()) : Iterator(dom_array.begin());
172
160k
        }
173
1.80M
        ALWAYS_INLINE Iterator end() const {
174
1.80M
            return array ? Iterator(array->end()) : Iterator(dom_array.end());
175
1.80M
        }
176
55.1k
        ALWAYS_INLINE size_t size() const { return array ? array->size() : dom_array.size(); }
177
0
        ALWAYS_INLINE Element operator[](size_t index) const {
178
0
            assert(index < size());
179
0
            return array ? Element(&(*array)[index]) : Element(dom_array.at(index).value_unsafe());
180
0
        }
181
182
    private:
183
        simdjson::dom::array dom_array;
184
        const std::vector<Node>* array = nullptr;
185
    };
186
    using KeyValuePair = std::pair<std::string_view, Element>;
187
    /// References an object in a JSON document.
188
    class Object {
189
    public:
190
        class Iterator {
191
        public:
192
            using DomIterator = simdjson::dom::object::iterator;
193
            ALWAYS_INLINE explicit Iterator(const std::vector<std::string>* keys_,
194
                                            const std::vector<Node>* values_, size_t index_)
195
26
                    : it(index_), keys(keys_), values(values_) {}                /// NOLINT
196
1.71M
            ALWAYS_INLINE explicit Iterator(const DomIterator& it_) : it(it_) {} /// NOLINT
197
1.42M
            ALWAYS_INLINE KeyValuePair operator*() const {
198
1.42M
                if (const auto* index = std::get_if<size_t>(&it)) {
199
14
                    return {(*keys)[*index], Element(&(*values)[*index])};
200
14
                }
201
1.42M
                const auto& res = *std::get<DomIterator>(it);
202
1.42M
                return {res.key, Element(res.value)};
203
1.42M
            }
204
1.42M
            ALWAYS_INLINE Iterator& operator++() {
205
1.42M
                if (auto* index = std::get_if<size_t>(&it)) {
206
14
                    ++(*index);
207
1.42M
                } else {
208
1.42M
                    ++std::get<DomIterator>(it);
209
1.42M
                }
210
1.42M
                return *this;
211
1.42M
            }
212
0
            ALWAYS_INLINE Iterator operator++(int) {
213
0
                auto res = *this;
214
0
                ++(*this);
215
0
                return res;
216
0
            } /// NOLINT
217
1.57M
            ALWAYS_INLINE friend bool operator!=(const Iterator& left, const Iterator& right) {
218
1.57M
                if (const auto* left_index = std::get_if<size_t>(&left.it)) {
219
20
                    return *left_index != std::get<size_t>(right.it);
220
20
                }
221
1.57M
                return std::get<DomIterator>(left.it) != std::get<DomIterator>(right.it);
222
1.57M
            }
223
0
            ALWAYS_INLINE friend bool operator==(const Iterator& left, const Iterator& right) {
224
0
                return !(left != right);
225
0
            }
226
227
        private:
228
            std::variant<DomIterator, size_t> it;
229
            const std::vector<std::string>* keys = nullptr;
230
            const std::vector<Node>* values = nullptr;
231
        };
232
        ALWAYS_INLINE explicit Object(const simdjson::dom::object& object_)
233
146k
                : dom_object(object_) {} /// NOLINT
234
        ALWAYS_INLINE explicit Object(const std::vector<std::string>* keys_,
235
                                      const std::vector<Node>* values_)
236
6
                : keys(keys_), values(values_) {} /// NOLINT
237
146k
        ALWAYS_INLINE Iterator begin() const {
238
146k
            return values ? Iterator(keys, values, 0) : Iterator(dom_object.begin());
239
146k
        }
240
1.57M
        ALWAYS_INLINE Iterator end() const {
241
1.57M
            return values ? Iterator(keys, values, size()) : Iterator(dom_object.end());
242
1.57M
        }
243
289k
        ALWAYS_INLINE size_t size() const { return values ? values->size() : dom_object.size(); }
244
        /// Optional: Provides access to an object's element by index.
245
0
        KeyValuePair operator[](size_t index) const {
246
0
            assert(index < size());
247
0
            if (values) {
248
0
                return {(*keys)[index], Element(&(*values)[index])};
249
0
            }
250
0
            auto it = dom_object.begin();
251
0
            while (index--) {
252
0
                ++it;
253
0
            }
254
0
            const auto& res = *it;
255
0
            return {res.key, Element(res.value)};
256
0
        }
257
258
    private:
259
        simdjson::dom::object dom_object;
260
        const std::vector<std::string>* keys = nullptr;
261
        const std::vector<Node>* values = nullptr;
262
    };
263
    /// Parses a JSON document, returns the reference to its root element if succeeded.
264
80.6k
    bool parse(const char* data, size_t size, Element& result, bool preserve_raw_numbers = false) {
265
80.6k
        if (!preserve_raw_numbers) {
266
80.6k
            auto document = dom_parser.parse(data, size);
267
80.6k
            if (document.error()) {
268
15
                return false;
269
15
            }
270
80.6k
            result = Element(document.value_unsafe());
271
80.6k
            return true;
272
80.6k
        }
273
274
14
        return parse_ondemand(data, size, result);
275
80.6k
    }
276
277
private:
278
14
    bool parse_ondemand(const char* data, size_t size, Element& result) {
279
14
        simdjson::padded_string padded_json(data, size);
280
14
        simdjson::ondemand::document document;
281
14
        auto error = ondemand_parser.iterate(padded_json).get(document);
282
14
        if (error) {
283
0
            return false;
284
0
        }
285
14
        root = Node();
286
14
        if (!build_node(document, &root)) {
287
0
            return false;
288
0
        }
289
14
        result = Element(&root);
290
14
        return true;
291
14
    }
292
293
17
    static std::string_view trim_raw_number(std::string_view raw_number) {
294
42
        auto is_space = [](char ch) { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; };
295
17
        while (!raw_number.empty() && is_space(raw_number.front())) {
296
0
            raw_number.remove_prefix(1);
297
0
        }
298
25
        while (!raw_number.empty() && is_space(raw_number.back())) {
299
8
            raw_number.remove_suffix(1);
300
8
        }
301
17
        return raw_number;
302
17
    }
303
304
    template <typename RawNumber>
305
17
    static bool assign_raw_number(RawNumber&& raw_number, std::string* out) {
306
17
        if constexpr (std::is_same_v<std::decay_t<RawNumber>, std::string_view>) {
307
12
            *out = std::string(trim_raw_number(raw_number));
308
12
            return true;
309
12
        } else {
310
5
            std::string_view raw_number_view;
311
5
            auto error = std::move(raw_number).get(raw_number_view);
312
5
            if (error) {
313
0
                return false;
314
0
            }
315
5
            *out = std::string(trim_raw_number(raw_number_view));
316
5
            return true;
317
5
        }
318
17
    }
_ZN5doris14SimdJSONParser17assign_raw_numberISt17basic_string_viewIcSt11char_traitsIcEEEEbOT_PNSt7__cxx1112basic_stringIcS4_SaIcEEE
Line
Count
Source
305
12
    static bool assign_raw_number(RawNumber&& raw_number, std::string* out) {
306
12
        if constexpr (std::is_same_v<std::decay_t<RawNumber>, std::string_view>) {
307
12
            *out = std::string(trim_raw_number(raw_number));
308
12
            return true;
309
        } else {
310
            std::string_view raw_number_view;
311
            auto error = std::move(raw_number).get(raw_number_view);
312
            if (error) {
313
                return false;
314
            }
315
            *out = std::string(trim_raw_number(raw_number_view));
316
            return true;
317
        }
318
12
    }
_ZN5doris14SimdJSONParser17assign_raw_numberIN8simdjson15simdjson_resultISt17basic_string_viewIcSt11char_traitsIcEEEEEEbOT_PNSt7__cxx1112basic_stringIcS6_SaIcEEE
Line
Count
Source
305
5
    static bool assign_raw_number(RawNumber&& raw_number, std::string* out) {
306
        if constexpr (std::is_same_v<std::decay_t<RawNumber>, std::string_view>) {
307
            *out = std::string(trim_raw_number(raw_number));
308
            return true;
309
5
        } else {
310
5
            std::string_view raw_number_view;
311
5
            auto error = std::move(raw_number).get(raw_number_view);
312
5
            if (error) {
313
0
                return false;
314
0
            }
315
5
            *out = std::string(trim_raw_number(raw_number_view));
316
5
            return true;
317
5
        }
318
5
    }
319
320
    template <typename Value>
321
2
    bool build_array_node(Value& value, Node* out) {
322
2
        simdjson::ondemand::array array;
323
2
        auto error = value.get_array().get(array);
324
2
        if (error) {
325
0
            return false;
326
0
        }
327
2
        out->type = Node::Type::ARRAY;
328
3
        for (auto element_result : array) {
329
3
            simdjson::ondemand::value element;
330
3
            error = std::move(element_result).get(element);
331
3
            if (error) {
332
0
                return false;
333
0
            }
334
3
            Node element_node;
335
3
            if (!build_node(element, &element_node)) {
336
0
                return false;
337
0
            }
338
3
            out->array_values.push_back(std::move(element_node));
339
3
        }
340
2
        return true;
341
2
    }
Unexecuted instantiation: _ZN5doris14SimdJSONParser16build_array_nodeIN8simdjson8fallback8ondemand8documentEEEbRT_PNS0_4NodeE
_ZN5doris14SimdJSONParser16build_array_nodeIN8simdjson8fallback8ondemand5valueEEEbRT_PNS0_4NodeE
Line
Count
Source
321
2
    bool build_array_node(Value& value, Node* out) {
322
2
        simdjson::ondemand::array array;
323
2
        auto error = value.get_array().get(array);
324
2
        if (error) {
325
0
            return false;
326
0
        }
327
2
        out->type = Node::Type::ARRAY;
328
3
        for (auto element_result : array) {
329
3
            simdjson::ondemand::value element;
330
3
            error = std::move(element_result).get(element);
331
3
            if (error) {
332
0
                return false;
333
0
            }
334
3
            Node element_node;
335
3
            if (!build_node(element, &element_node)) {
336
0
                return false;
337
0
            }
338
3
            out->array_values.push_back(std::move(element_node));
339
3
        }
340
2
        return true;
341
2
    }
342
343
    template <typename Value>
344
6
    bool build_object_node(Value& value, Node* out) {
345
6
        simdjson::ondemand::object object;
346
6
        auto error = value.get_object().get(object);
347
6
        if (error) {
348
0
            return false;
349
0
        }
350
6
        out->type = Node::Type::OBJECT;
351
14
        for (auto field_result : object) {
352
14
            simdjson::ondemand::field field;
353
14
            error = std::move(field_result).get(field);
354
14
            if (error) {
355
0
                return false;
356
0
            }
357
14
            std::string_view key;
358
14
            error = field.unescaped_key().get(key);
359
14
            if (error) {
360
0
                return false;
361
0
            }
362
14
            std::string key_copy(key);
363
14
            simdjson::ondemand::value field_value = field.value();
364
14
            Node field_node;
365
14
            if (!build_node(field_value, &field_node)) {
366
0
                return false;
367
0
            }
368
14
            out->object_keys.push_back(std::move(key_copy));
369
14
            out->object_values.push_back(std::move(field_node));
370
14
        }
371
6
        return true;
372
6
    }
_ZN5doris14SimdJSONParser17build_object_nodeIN8simdjson8fallback8ondemand5valueEEEbRT_PNS0_4NodeE
Line
Count
Source
344
1
    bool build_object_node(Value& value, Node* out) {
345
1
        simdjson::ondemand::object object;
346
1
        auto error = value.get_object().get(object);
347
1
        if (error) {
348
0
            return false;
349
0
        }
350
1
        out->type = Node::Type::OBJECT;
351
2
        for (auto field_result : object) {
352
2
            simdjson::ondemand::field field;
353
2
            error = std::move(field_result).get(field);
354
2
            if (error) {
355
0
                return false;
356
0
            }
357
2
            std::string_view key;
358
2
            error = field.unescaped_key().get(key);
359
2
            if (error) {
360
0
                return false;
361
0
            }
362
2
            std::string key_copy(key);
363
2
            simdjson::ondemand::value field_value = field.value();
364
2
            Node field_node;
365
2
            if (!build_node(field_value, &field_node)) {
366
0
                return false;
367
0
            }
368
2
            out->object_keys.push_back(std::move(key_copy));
369
2
            out->object_values.push_back(std::move(field_node));
370
2
        }
371
1
        return true;
372
1
    }
_ZN5doris14SimdJSONParser17build_object_nodeIN8simdjson8fallback8ondemand8documentEEEbRT_PNS0_4NodeE
Line
Count
Source
344
5
    bool build_object_node(Value& value, Node* out) {
345
5
        simdjson::ondemand::object object;
346
5
        auto error = value.get_object().get(object);
347
5
        if (error) {
348
0
            return false;
349
0
        }
350
5
        out->type = Node::Type::OBJECT;
351
12
        for (auto field_result : object) {
352
12
            simdjson::ondemand::field field;
353
12
            error = std::move(field_result).get(field);
354
12
            if (error) {
355
0
                return false;
356
0
            }
357
12
            std::string_view key;
358
12
            error = field.unescaped_key().get(key);
359
12
            if (error) {
360
0
                return false;
361
0
            }
362
12
            std::string key_copy(key);
363
12
            simdjson::ondemand::value field_value = field.value();
364
12
            Node field_node;
365
12
            if (!build_node(field_value, &field_node)) {
366
0
                return false;
367
0
            }
368
12
            out->object_keys.push_back(std::move(key_copy));
369
12
            out->object_values.push_back(std::move(field_node));
370
12
        }
371
5
        return true;
372
5
    }
373
374
    template <typename Value>
375
19
    bool build_number_node(Value& value, Node* out) {
376
19
        simdjson::ondemand::number_type number_type;
377
19
        auto error = value.get_number_type().get(number_type);
378
19
        if (error) {
379
0
            return false;
380
0
        }
381
19
        switch (number_type) {
382
0
        case simdjson::ondemand::number_type::signed_integer:
383
0
            out->type = Node::Type::INT64;
384
0
            error = value.get_int64().get(out->int64_value);
385
0
            return !error;
386
2
        case simdjson::ondemand::number_type::unsigned_integer:
387
2
            out->type = Node::Type::UINT64;
388
2
            error = value.get_uint64().get(out->uint64_value);
389
2
            return !error;
390
15
        case simdjson::ondemand::number_type::floating_point_number:
391
15
            if (!assign_raw_number(value.raw_json_token(), &out->raw_number)) {
392
0
                return false;
393
0
            }
394
15
            out->type = Node::Type::DOUBLE;
395
15
            error = value.get_double().get(out->double_value);
396
15
            return !error;
397
2
        case simdjson::ondemand::number_type::big_integer:
398
2
            if (!assign_raw_number(value.raw_json_token(), &out->raw_number)) {
399
0
                return false;
400
0
            }
401
2
            out->type = Node::Type::STRING;
402
2
            out->string_value = out->raw_number;
403
2
            return true;
404
19
        }
405
0
        return false;
406
19
    }
_ZN5doris14SimdJSONParser17build_number_nodeIN8simdjson8fallback8ondemand5valueEEEbRT_PNS0_4NodeE
Line
Count
Source
375
13
    bool build_number_node(Value& value, Node* out) {
376
13
        simdjson::ondemand::number_type number_type;
377
13
        auto error = value.get_number_type().get(number_type);
378
13
        if (error) {
379
0
            return false;
380
0
        }
381
13
        switch (number_type) {
382
0
        case simdjson::ondemand::number_type::signed_integer:
383
0
            out->type = Node::Type::INT64;
384
0
            error = value.get_int64().get(out->int64_value);
385
0
            return !error;
386
1
        case simdjson::ondemand::number_type::unsigned_integer:
387
1
            out->type = Node::Type::UINT64;
388
1
            error = value.get_uint64().get(out->uint64_value);
389
1
            return !error;
390
11
        case simdjson::ondemand::number_type::floating_point_number:
391
11
            if (!assign_raw_number(value.raw_json_token(), &out->raw_number)) {
392
0
                return false;
393
0
            }
394
11
            out->type = Node::Type::DOUBLE;
395
11
            error = value.get_double().get(out->double_value);
396
11
            return !error;
397
1
        case simdjson::ondemand::number_type::big_integer:
398
1
            if (!assign_raw_number(value.raw_json_token(), &out->raw_number)) {
399
0
                return false;
400
0
            }
401
1
            out->type = Node::Type::STRING;
402
1
            out->string_value = out->raw_number;
403
1
            return true;
404
13
        }
405
0
        return false;
406
13
    }
_ZN5doris14SimdJSONParser17build_number_nodeIN8simdjson8fallback8ondemand8documentEEEbRT_PNS0_4NodeE
Line
Count
Source
375
6
    bool build_number_node(Value& value, Node* out) {
376
6
        simdjson::ondemand::number_type number_type;
377
6
        auto error = value.get_number_type().get(number_type);
378
6
        if (error) {
379
0
            return false;
380
0
        }
381
6
        switch (number_type) {
382
0
        case simdjson::ondemand::number_type::signed_integer:
383
0
            out->type = Node::Type::INT64;
384
0
            error = value.get_int64().get(out->int64_value);
385
0
            return !error;
386
1
        case simdjson::ondemand::number_type::unsigned_integer:
387
1
            out->type = Node::Type::UINT64;
388
1
            error = value.get_uint64().get(out->uint64_value);
389
1
            return !error;
390
4
        case simdjson::ondemand::number_type::floating_point_number:
391
4
            if (!assign_raw_number(value.raw_json_token(), &out->raw_number)) {
392
0
                return false;
393
0
            }
394
4
            out->type = Node::Type::DOUBLE;
395
4
            error = value.get_double().get(out->double_value);
396
4
            return !error;
397
1
        case simdjson::ondemand::number_type::big_integer:
398
1
            if (!assign_raw_number(value.raw_json_token(), &out->raw_number)) {
399
0
                return false;
400
0
            }
401
1
            out->type = Node::Type::STRING;
402
1
            out->string_value = out->raw_number;
403
1
            return true;
404
6
        }
405
0
        return false;
406
6
    }
407
408
    template <typename Value>
409
2
    bool build_string_node(Value& value, Node* out) {
410
2
        std::string_view str;
411
2
        auto error = value.get_string().get(str);
412
2
        if (error) {
413
0
            return false;
414
0
        }
415
2
        out->type = Node::Type::STRING;
416
2
        out->string_value = std::string(str);
417
2
        return true;
418
2
    }
_ZN5doris14SimdJSONParser17build_string_nodeIN8simdjson8fallback8ondemand5valueEEEbRT_PNS0_4NodeE
Line
Count
Source
409
1
    bool build_string_node(Value& value, Node* out) {
410
1
        std::string_view str;
411
1
        auto error = value.get_string().get(str);
412
1
        if (error) {
413
0
            return false;
414
0
        }
415
1
        out->type = Node::Type::STRING;
416
1
        out->string_value = std::string(str);
417
1
        return true;
418
1
    }
_ZN5doris14SimdJSONParser17build_string_nodeIN8simdjson8fallback8ondemand8documentEEEbRT_PNS0_4NodeE
Line
Count
Source
409
1
    bool build_string_node(Value& value, Node* out) {
410
1
        std::string_view str;
411
1
        auto error = value.get_string().get(str);
412
1
        if (error) {
413
0
            return false;
414
0
        }
415
1
        out->type = Node::Type::STRING;
416
1
        out->string_value = std::string(str);
417
1
        return true;
418
1
    }
419
420
    template <typename Value>
421
31
    bool build_node(Value& value, Node* out) {
422
31
        simdjson::ondemand::json_type type;
423
31
        auto error = value.type().get(type);
424
31
        if (error) {
425
0
            return false;
426
0
        }
427
31
        switch (type) {
428
2
        case simdjson::ondemand::json_type::array:
429
2
            return build_array_node(value, out);
430
6
        case simdjson::ondemand::json_type::object:
431
6
            return build_object_node(value, out);
432
19
        case simdjson::ondemand::json_type::number:
433
19
            return build_number_node(value, out);
434
2
        case simdjson::ondemand::json_type::string: {
435
2
            return build_string_node(value, out);
436
0
        }
437
1
        case simdjson::ondemand::json_type::boolean:
438
1
            out->type = Node::Type::BOOL;
439
1
            error = value.get_bool().get(out->bool_value);
440
1
            return !error;
441
1
        case simdjson::ondemand::json_type::null:
442
1
            out->type = Node::Type::NULL_VALUE;
443
1
            return true;
444
31
        }
445
0
        return false;
446
31
    }
_ZN5doris14SimdJSONParser10build_nodeIN8simdjson8fallback8ondemand8documentEEEbRT_PNS0_4NodeE
Line
Count
Source
421
14
    bool build_node(Value& value, Node* out) {
422
14
        simdjson::ondemand::json_type type;
423
14
        auto error = value.type().get(type);
424
14
        if (error) {
425
0
            return false;
426
0
        }
427
14
        switch (type) {
428
0
        case simdjson::ondemand::json_type::array:
429
0
            return build_array_node(value, out);
430
5
        case simdjson::ondemand::json_type::object:
431
5
            return build_object_node(value, out);
432
6
        case simdjson::ondemand::json_type::number:
433
6
            return build_number_node(value, out);
434
1
        case simdjson::ondemand::json_type::string: {
435
1
            return build_string_node(value, out);
436
0
        }
437
1
        case simdjson::ondemand::json_type::boolean:
438
1
            out->type = Node::Type::BOOL;
439
1
            error = value.get_bool().get(out->bool_value);
440
1
            return !error;
441
1
        case simdjson::ondemand::json_type::null:
442
1
            out->type = Node::Type::NULL_VALUE;
443
1
            return true;
444
14
        }
445
0
        return false;
446
14
    }
_ZN5doris14SimdJSONParser10build_nodeIN8simdjson8fallback8ondemand5valueEEEbRT_PNS0_4NodeE
Line
Count
Source
421
17
    bool build_node(Value& value, Node* out) {
422
17
        simdjson::ondemand::json_type type;
423
17
        auto error = value.type().get(type);
424
17
        if (error) {
425
0
            return false;
426
0
        }
427
17
        switch (type) {
428
2
        case simdjson::ondemand::json_type::array:
429
2
            return build_array_node(value, out);
430
1
        case simdjson::ondemand::json_type::object:
431
1
            return build_object_node(value, out);
432
13
        case simdjson::ondemand::json_type::number:
433
13
            return build_number_node(value, out);
434
1
        case simdjson::ondemand::json_type::string: {
435
1
            return build_string_node(value, out);
436
0
        }
437
0
        case simdjson::ondemand::json_type::boolean:
438
0
            out->type = Node::Type::BOOL;
439
0
            error = value.get_bool().get(out->bool_value);
440
0
            return !error;
441
0
        case simdjson::ondemand::json_type::null:
442
0
            out->type = Node::Type::NULL_VALUE;
443
0
            return true;
444
17
        }
445
0
        return false;
446
17
    }
447
448
    simdjson::dom::parser dom_parser;
449
    simdjson::ondemand::parser ondemand_parser;
450
    Node root;
451
};
452
160k
inline ALWAYS_INLINE SimdJSONParser::Array SimdJSONParser::Element::getArray() const {
453
160k
    return node ? Array(&node->array_values) : Array(dom_element.get_array().value_unsafe());
454
160k
}
455
146k
inline ALWAYS_INLINE SimdJSONParser::Object SimdJSONParser::Element::getObject() const {
456
146k
    return node ? Object(&node->object_keys, &node->object_values)
457
146k
                : Object(dom_element.get_object().value_unsafe());
458
146k
}
459
460
} // namespace doris