Coverage Report

Created: 2025-07-23 16:39

/root/doris/be/src/util/jsonb_document.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Copyright (c) 2014, Facebook, Inc.
3
 *  All rights reserved.
4
 *
5
 *  This source code is licensed under the BSD-style license found in the
6
 *  LICENSE file in the root directory of this source tree. An additional grant
7
 *  of patent rights can be found in the PATENTS file in the same directory.
8
 *
9
 */
10
11
/*
12
 * This header defines JsonbDocument, JsonbKeyValue, and various value classes
13
 * which are derived from JsonbValue, and a forward iterator for container
14
 * values - essentially everything that is related to JSONB binary data
15
 * structures.
16
 *
17
 * Implementation notes:
18
 *
19
 * None of the classes in this header file can be instantiated directly (i.e.
20
 * you cannot create a JsonbKeyValue or JsonbValue object - all constructors
21
 * are declared non-public). We use the classes as wrappers on the packed JSONB
22
 * bytes (serialized), and cast the classes (types) to the underlying packed
23
 * byte array.
24
 *
25
 * For the same reason, we cannot define any JSONB value class to be virtual,
26
 * since we never call constructors, and will not instantiate vtbl and vptrs.
27
 *
28
 * Therefore, the classes are defined as packed structures (i.e. no data
29
 * alignment and padding), and the private member variables of the classes are
30
 * defined precisely in the same order as the JSONB spec. This ensures we
31
 * access the packed JSONB bytes correctly.
32
 *
33
 * The packed structures are highly optimized for in-place operations with low
34
 * overhead. The reads (and in-place writes) are performed directly on packed
35
 * bytes. There is no memory allocation at all at runtime.
36
 *
37
 * For updates/writes of values that will expand the original JSONB size, the
38
 * write will fail, and the caller needs to handle buffer increase.
39
 *
40
 * ** Iterator **
41
 * Both ObjectVal class and ArrayVal class have iterator type that you can use
42
 * to declare an iterator on a container object to go through the key-value
43
 * pairs or value list. The iterator has both non-const and const types.
44
 *
45
 * Note: iterators are forward direction only.
46
 *
47
 * ** Query **
48
 * Querying into containers is through the member functions find (for key/value
49
 * pairs) and get (for array elements), and is in streaming style. We don't
50
 * need to read/scan the whole JSONB packed bytes in order to return results.
51
 * Once the key/index is found, we will stop search.  You can use text to query
52
 * both objects and array (for array, text will be converted to integer index),
53
 * and use index to retrieve from array. Array index is 0-based.
54
 *
55
 * ** External dictionary **
56
 * During query processing, you can also pass a call-back function, so the
57
 * search will first try to check if the key string exists in the dictionary.
58
 * If so, search will be based on the id instead of the key string.
59
 * @author Tian Xia <tianx@fb.com>
60
 * 
61
 * this file is copied from 
62
 * https://github.com/facebook/mysql-5.6/blob/fb-mysql-5.6.35/fbson/FbsonDocument.h
63
 * and modified by Doris
64
 */
65
66
#ifndef JSONB_JSONBDOCUMENT_H
67
#define JSONB_JSONBDOCUMENT_H
68
69
#include <algorithm>
70
#include <cctype>
71
#include <charconv>
72
#include <limits>
73
#include <string>
74
#include <type_traits>
75
76
#include "common/compiler_util.h" // IWYU pragma: keep
77
#include "common/status.h"
78
79
// #include "util/string_parser.hpp"
80
81
namespace doris {
82
#if defined(__clang__)
83
#pragma clang diagnostic push
84
#pragma clang diagnostic ignored "-Wzero-length-array"
85
#endif
86
#pragma pack(push, 1)
87
88
389k
#define JSONB_VER 1
89
90
using int128_t = __int128;
91
92
// forward declaration
93
class JsonbValue;
94
class ObjectVal;
95
96
const int MaxNestingLevel = 100;
97
98
/*
99
 * JsonbType defines 10 primitive types and 2 container types, as described
100
 * below.
101
 *
102
 * primitive_value ::=
103
 *   0x00        //null value (0 byte)
104
 * | 0x01        //boolean true (0 byte)
105
 * | 0x02        //boolean false (0 byte)
106
 * | 0x03 int8   //char/int8 (1 byte)
107
 * | 0x04 int16  //int16 (2 bytes)
108
 * | 0x05 int32  //int32 (4 bytes)
109
 * | 0x06 int64  //int64 (8 bytes)
110
 * | 0x07 double //floating point (8 bytes)
111
 * | 0x08 string //variable length string
112
 * | 0x09 binary //variable length binary
113
 *
114
 * container ::=
115
 *   0x0A int32 key_value_list //object, int32 is the total bytes of the object
116
 * | 0x0B int32 value_list     //array, int32 is the total bytes of the array
117
 */
118
enum class JsonbType : char {
119
    T_Null = 0x00,
120
    T_True = 0x01,
121
    T_False = 0x02,
122
    T_Int8 = 0x03,
123
    T_Int16 = 0x04,
124
    T_Int32 = 0x05,
125
    T_Int64 = 0x06,
126
    T_Double = 0x07,
127
    T_String = 0x08,
128
    T_Binary = 0x09,
129
    T_Object = 0x0A,
130
    T_Array = 0x0B,
131
    T_Int128 = 0x0C,
132
    T_Float = 0x0D,
133
    NUM_TYPES,
134
};
135
136
//for parse json path
137
constexpr char SCOPE = '$';
138
constexpr char BEGIN_MEMBER = '.';
139
constexpr char BEGIN_ARRAY = '[';
140
constexpr char END_ARRAY = ']';
141
constexpr char DOUBLE_QUOTE = '"';
142
constexpr char WILDCARD = '*';
143
constexpr char MINUS = '-';
144
constexpr char LAST[] = "last";
145
constexpr char ESCAPE = '\\';
146
constexpr unsigned int MEMBER_CODE = 0;
147
constexpr unsigned int ARRAY_CODE = 1;
148
149
/*
150
 * JsonbDocument is the main object that accesses and queries JSONB packed
151
 * bytes. NOTE: JsonbDocument only allows object container as the top level
152
 * JSONB value. However, you can use the static method "createValue" to get any
153
 * JsonbValue object from the packed bytes.
154
 *
155
 * JsonbDocument object also dereferences to an object container value
156
 * (ObjectVal) once JSONB is loaded.
157
 *
158
 * ** Load **
159
 * JsonbDocument is usable after loading packed bytes (memory location) into
160
 * the object. We only need the header and first few bytes of the payload after
161
 * header to verify the JSONB.
162
 *
163
 * Note: creating an JsonbDocument (through createDocument) does not allocate
164
 * any memory. The document object is an efficient wrapper on the packed bytes
165
 * which is accessed directly.
166
 *
167
 * ** Query **
168
 * Query is through dereferencing into ObjectVal.
169
 */
170
class JsonbDocument {
171
public:
172
    // create an JsonbDocument object from JSONB packed bytes
173
    [[nodiscard]] static Status checkAndCreateDocument(const char* pb, size_t size,
174
                                                       JsonbDocument** doc);
175
176
    // create an JsonbValue from JSONB packed bytes
177
    static JsonbValue* createValue(const char* pb, uint32_t size);
178
179
0
    uint8_t version() const { return header_.ver_; }
180
181
24.6k
    JsonbValue* getValue() { return ((JsonbValue*)payload_); }
182
183
    void setValue(const JsonbValue* value);
184
185
    unsigned int numPackedBytes() const;
186
187
17.7k
    ObjectVal* operator->() { return ((ObjectVal*)payload_); }
188
189
0
    const ObjectVal* operator->() const { return ((const ObjectVal*)payload_); }
190
191
0
    bool operator==(const JsonbDocument& other) const {
192
0
        assert(false);
193
0
        return false;
194
0
    }
195
196
0
    bool operator!=(const JsonbDocument& other) const {
197
0
        assert(false);
198
0
        return false;
199
0
    }
200
201
0
    bool operator<=(const JsonbDocument& other) const {
202
0
        assert(false);
203
0
        return false;
204
0
    }
205
206
0
    bool operator>=(const JsonbDocument& other) const {
207
0
        assert(false);
208
0
        return false;
209
0
    }
210
211
0
    bool operator<(const JsonbDocument& other) const {
212
0
        assert(false);
213
0
        return false;
214
0
    }
215
216
0
    bool operator>(const JsonbDocument& other) const {
217
0
        assert(false);
218
0
        return false;
219
0
    }
220
221
private:
222
    /*
223
   * JsonbHeader class defines JSONB header (internal to JsonbDocument).
224
   *
225
   * Currently it only contains version information (1-byte). We may expand the
226
   * header to include checksum of the JSONB binary for more security.
227
   */
228
    struct JsonbHeader {
229
        uint8_t ver_;
230
    } header_;
231
232
    char payload_[0];
233
};
234
235
/// A simple input stream class for the JSON path parser.
236
class Stream {
237
public:
238
    /// Creates an input stream reading from a character string.
239
    /// @param string  the input string
240
    /// @param length  the length of the input string
241
846
    Stream(const char* string, size_t length) : m_position(string), m_end(string + length) {}
242
243
    /// Returns a pointer to the current position in the stream.
244
850
    const char* position() const { return m_position; }
245
246
    /// Returns a pointer to the position just after the end of the stream.
247
0
    const char* end() const { return m_end; }
248
249
    /// Returns the number of bytes remaining in the stream.
250
16.5k
    size_t remaining() const {
251
16.5k
        assert(m_position <= m_end);
252
0
        return m_end - m_position;
253
16.5k
    }
254
255
    /// Tells if the stream has been exhausted.
256
14.0k
    bool exhausted() const { return remaining() == 0; }
257
258
    /// Reads the next byte from the stream and moves the position forward.
259
846
    char read() {
260
846
        assert(!exhausted());
261
0
        return *m_position++;
262
846
    }
263
264
    /// Reads the next byte from the stream without moving the position forward.
265
6.94k
    char peek() const {
266
6.94k
        assert(!exhausted());
267
0
        return *m_position;
268
6.94k
    }
269
270
    /// Moves the position to the next non-whitespace character.
271
4.24k
    void skip_whitespace() {
272
4.24k
        m_position = std::find_if_not(m_position, m_end, [](char c) { return std::isspace(c); });
273
4.24k
    }
274
275
    /// Moves the position n bytes forward.
276
2.55k
    void skip(size_t n) {
277
2.55k
        assert(remaining() >= n);
278
0
        m_position += n;
279
2.55k
        skip_whitespace();
280
2.55k
    }
281
282
1.70k
    void clear_leg_ptr() { leg_ptr = nullptr; }
283
284
850
    void set_leg_ptr(char* ptr) {
285
850
        clear_leg_ptr();
286
850
        leg_ptr = ptr;
287
850
    }
288
289
1.15k
    char* get_leg_ptr() { return leg_ptr; }
290
291
850
    void clear_leg_len() { leg_len = 0; }
292
293
1.15k
    void add_leg_len() { leg_len++; }
294
295
1.70k
    unsigned int get_leg_len() const { return leg_len; }
296
297
0
    void remove_escapes() {
298
0
        int new_len = 0;
299
0
        for (int i = 0; i < leg_len; i++) {
  Branch (299:25): [True: 0, False: 0]
300
0
            if (leg_ptr[i] != '\\') {
  Branch (300:17): [True: 0, False: 0]
301
0
                leg_ptr[new_len++] = leg_ptr[i];
302
0
            }
303
0
        }
304
0
        leg_ptr[new_len] = '\0';
305
0
        leg_len = new_len;
306
0
    }
307
308
0
    void set_has_escapes(bool has) { has_escapes = has; }
309
310
308
    bool get_has_escapes() const { return has_escapes; }
311
312
private:
313
    /// The current position in the stream.
314
    const char* m_position = nullptr;
315
316
    /// The end of the stream.
317
    const char* const m_end;
318
319
    ///path leg ptr
320
    char* leg_ptr = nullptr;
321
322
    ///path leg len
323
    unsigned int leg_len;
324
325
    ///Whether to contain escape characters
326
    bool has_escapes = false;
327
};
328
329
struct leg_info {
330
    ///path leg ptr
331
    char* leg_ptr = nullptr;
332
333
    ///path leg len
334
    unsigned int leg_len;
335
336
    ///array_index
337
    int array_index;
338
339
    ///type: 0 is member 1 is array
340
    unsigned int type;
341
342
0
    bool to_string(std::string* str) const {
343
0
        if (type == MEMBER_CODE) {
  Branch (343:13): [True: 0, False: 0]
344
0
            str->push_back(BEGIN_MEMBER);
345
0
            str->append(leg_ptr, leg_len);
346
0
            return true;
347
0
        } else if (type == ARRAY_CODE) {
  Branch (347:20): [True: 0, False: 0]
348
0
            str->push_back(BEGIN_ARRAY);
349
0
            std::string int_str = std::to_string(array_index);
350
0
            str->append(int_str);
351
0
            str->push_back(END_ARRAY);
352
0
            return true;
353
0
        } else {
354
0
            return false;
355
0
        }
356
0
    }
357
};
358
359
class JsonbPath {
360
public:
361
    // parse json path
362
    static bool parsePath(Stream* stream, JsonbPath* path);
363
364
    static bool parse_array(Stream* stream, JsonbPath* path);
365
    static bool parse_member(Stream* stream, JsonbPath* path);
366
367
    //return true if json path valid else return false
368
    bool seek(const char* string, size_t length);
369
370
850
    void add_leg_to_leg_vector(std::unique_ptr<leg_info> leg) {
371
850
        leg_vector.emplace_back(leg.release());
372
850
    }
373
374
0
    void pop_leg_from_leg_vector() { leg_vector.pop_back(); }
375
376
0
    bool to_string(std::string* res) const {
377
0
        res->push_back(SCOPE);
378
0
        for (const auto& leg : leg_vector) {
  Branch (378:30): [True: 0, False: 0]
379
0
            auto valid = leg->to_string(res);
380
0
            if (!valid) {
  Branch (380:17): [True: 0, False: 0]
381
0
                return false;
382
0
            }
383
0
        }
384
0
        return true;
385
0
    }
386
387
1.05k
    size_t get_leg_vector_size() { return leg_vector.size(); }
388
389
2.39k
    leg_info* get_leg_from_leg_vector(size_t i) { return leg_vector[i].get(); }
390
391
0
    void clean() { leg_vector.clear(); }
392
393
private:
394
    std::vector<std::unique_ptr<leg_info>> leg_vector;
395
};
396
397
/*
398
 * JsonbFwdIteratorT implements JSONB's iterator template.
399
 *
400
 * Note: it is an FORWARD iterator only due to the design of JSONB format.
401
 */
402
template <class Iter_Type, class Cont_Type>
403
class JsonbFwdIteratorT {
404
public:
405
    using iterator = Iter_Type;
406
    using pointer = typename std::iterator_traits<Iter_Type>::pointer;
407
    using reference = typename std::iterator_traits<Iter_Type>::reference;
408
409
    explicit JsonbFwdIteratorT() : current_(nullptr) {}
410
1.13M
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
_ZN5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEC2ERKS3_
Line
Count
Source
410
499k
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
_ZN5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEC2ERKS3_
Line
Count
Source
410
621k
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
_ZN5doris17JsonbFwdIteratorTIPNS_13JsonbKeyValueENS_9ObjectValEEC2ERKS2_
Line
Count
Source
410
17.8k
    explicit JsonbFwdIteratorT(const iterator& i) : current_(i) {}
Unexecuted instantiation: _ZN5doris17JsonbFwdIteratorTIPNS_10JsonbValueENS_8ArrayValEEC2ERKS2_
411
412
    // allow non-const to const iterator conversion (same container type)
413
    template <class Iter_Ty>
414
    JsonbFwdIteratorT(const JsonbFwdIteratorT<Iter_Ty, Cont_Type>& rhs) : current_(rhs.base()) {}
415
416
8.57M
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPNS_13JsonbKeyValueENS_9ObjectValEEeqERKS4_
Line
Count
Source
416
14.6k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEeqERKS5_
Line
Count
Source
416
998k
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEeqERKS5_
Line
Count
Source
416
7.56M
    bool operator==(const JsonbFwdIteratorT& rhs) const { return (current_ == rhs.current_); }
Unexecuted instantiation: _ZNK5doris17JsonbFwdIteratorTIPNS_10JsonbValueENS_8ArrayValEEeqERKS4_
417
418
8.01M
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEneERKS5_
Line
Count
Source
418
749k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
_ZNK5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEneERKS5_
Line
Count
Source
418
7.25M
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
_ZNK5doris17JsonbFwdIteratorTIPNS_13JsonbKeyValueENS_9ObjectValEEneERKS4_
Line
Count
Source
418
14.6k
    bool operator!=(const JsonbFwdIteratorT& rhs) const { return !operator==(rhs); }
Unexecuted instantiation: _ZNK5doris17JsonbFwdIteratorTIPNS_10JsonbValueENS_8ArrayValEEneERKS4_
419
420
998k
    bool operator<(const JsonbFwdIteratorT& rhs) const { return (current_ < rhs.current_); }
421
422
    bool operator>(const JsonbFwdIteratorT& rhs) const { return !operator<(rhs); }
423
424
4.23M
    JsonbFwdIteratorT& operator++() {
425
4.23M
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
426
4.23M
        return *this;
427
4.23M
    }
_ZN5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEppEv
Line
Count
Source
424
749k
    JsonbFwdIteratorT& operator++() {
425
749k
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
426
749k
        return *this;
427
749k
    }
_ZN5doris17JsonbFwdIteratorTIPKNS_10JsonbValueENS_8ArrayValEEppEv
Line
Count
Source
424
3.47M
    JsonbFwdIteratorT& operator++() {
425
3.47M
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
426
3.47M
        return *this;
427
3.47M
    }
_ZN5doris17JsonbFwdIteratorTIPNS_13JsonbKeyValueENS_9ObjectValEEppEv
Line
Count
Source
424
11.4k
    JsonbFwdIteratorT& operator++() {
425
11.4k
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
426
11.4k
        return *this;
427
11.4k
    }
Unexecuted instantiation: _ZN5doris17JsonbFwdIteratorTIPNS_10JsonbValueENS_8ArrayValEEppEv
428
429
    JsonbFwdIteratorT operator++(int) {
430
        auto tmp = *this;
431
        current_ = (iterator)(((char*)current_) + current_->numPackedBytes());
432
        return tmp;
433
    }
434
435
3.47M
    explicit operator pointer() { return current_; }
436
437
0
    reference operator*() const { return *current_; }
438
439
2.98M
    pointer operator->() const { return current_; }
_ZNK5doris17JsonbFwdIteratorTIPNS_13JsonbKeyValueENS_9ObjectValEEptEv
Line
Count
Source
439
20.6k
    pointer operator->() const { return current_; }
_ZNK5doris17JsonbFwdIteratorTIPKNS_13JsonbKeyValueENS_9ObjectValEEptEv
Line
Count
Source
439
2.96M
    pointer operator->() const { return current_; }
440
441
0
    iterator base() const { return current_; }
442
443
private:
444
    iterator current_;
445
};
446
447
using hDictInsert = int (*)(const char*, unsigned int);
448
using hDictFind = int (*)(const char*, unsigned int);
449
450
using JsonbTypeUnder = std::underlying_type_t<JsonbType>;
451
452
/*
453
 * JsonbKeyValue class defines JSONB key type, as described below.
454
 *
455
 * key ::=
456
 *   0x00 int8    //1-byte dictionary id
457
 * | int8 (byte*) //int8 (>0) is the size of the key string
458
 *
459
 * value ::= primitive_value | container
460
 *
461
 * JsonbKeyValue can be either an id mapping to the key string in an external
462
 * dictionary, or it is the original key string. Whether to read an id or a
463
 * string is decided by the first byte (size_).
464
 *
465
 * Note: a key object must be followed by a value object. Therefore, a key
466
 * object implicitly refers to a key-value pair, and you can get the value
467
 * object right after the key object. The function numPackedBytes hence
468
 * indicates the total size of the key-value pair, so that we will be able go
469
 * to next pair from the key.
470
 *
471
 * ** Dictionary size **
472
 * By default, the dictionary size is 255 (1-byte). Users can define
473
 * "USE_LARGE_DICT" to increase the dictionary size to 655535 (2-byte).
474
 */
475
class JsonbKeyValue {
476
public:
477
    // now we use sMaxKeyId to represent an empty key
478
    static const int sMaxKeyId = 65535;
479
    using keyid_type = uint16_t;
480
481
    JsonbKeyValue() = delete;
482
483
    static const uint8_t sMaxKeyLen = 64;
484
485
    // size of the key. 0 indicates it is stored as id
486
1.46M
    uint8_t klen() const { return size_; }
487
488
    // get the key string. Note the string may not be null terminated.
489
717k
    const char* getKeyStr() const { return key_.str_; }
490
491
40.4k
    keyid_type getKeyId() const { return key_.id_; }
492
493
1.52M
    unsigned int keyPackedBytes() const {
494
1.52M
        return size_ ? (sizeof(size_) + size_) : (sizeof(size_) + sizeof(keyid_type));
  Branch (494:16): [True: 1.43M, False: 85.2k]
495
1.52M
    }
496
497
760k
    JsonbValue* value() const { return (JsonbValue*)(((char*)this) + keyPackedBytes()); }
498
499
    // size of the total packed bytes (key+value)
500
    unsigned int numPackedBytes() const;
501
502
private:
503
    uint8_t size_;
504
505
    union key_ {
506
        keyid_type id_;
507
        char str_[1];
508
    } key_;
509
};
510
511
/*
512
 * JsonbValue is the base class of all JSONB types. It contains only one member
513
 * variable - type info, which can be retrieved by member functions is[Type]()
514
 * or type().
515
 */
516
class JsonbValue {
517
public:
518
    static const uint32_t sMaxValueLen = 1 << 24; // 16M
519
520
3.12k
    bool isNull() const { return (type_ == JsonbType::T_Null); }
521
119
    bool isTrue() const { return (type_ == JsonbType::T_True); }
522
109
    bool isFalse() const { return (type_ == JsonbType::T_False); }
523
85
    bool isInt() const { return isInt8() || isInt16() || isInt32() || isInt64() || isInt128(); }
  Branch (523:33): [True: 6, False: 79]
  Branch (523:45): [True: 6, False: 73]
  Branch (523:58): [True: 6, False: 67]
  Branch (523:71): [True: 6, False: 61]
  Branch (523:84): [True: 0, False: 61]
524
337
    bool isInt8() const { return (type_ == JsonbType::T_Int8); }
525
299
    bool isInt16() const { return (type_ == JsonbType::T_Int16); }
526
271
    bool isInt32() const { return (type_ == JsonbType::T_Int32); }
527
201
    bool isInt64() const { return (type_ == JsonbType::T_Int64); }
528
140
    bool isDouble() const { return (type_ == JsonbType::T_Double); }
529
14
    bool isFloat() const { return (type_ == JsonbType::T_Float); }
530
965
    bool isString() const { return (type_ == JsonbType::T_String); }
531
3.14k
    bool isBinary() const { return (type_ == JsonbType::T_Binary); }
532
0
    bool isObject() const { return (type_ == JsonbType::T_Object); }
533
0
    bool isArray() const { return (type_ == JsonbType::T_Array); }
534
61
    bool isInt128() const { return (type_ == JsonbType::T_Int128); }
535
536
4.29M
    JsonbType type() const { return type_; }
537
538
0
    const char* typeName() const {
539
0
        switch (type_) {
540
0
        case JsonbType::T_Null:
  Branch (540:9): [True: 0, False: 0]
541
0
            return "null";
542
0
        case JsonbType::T_True:
  Branch (542:9): [True: 0, False: 0]
543
0
        case JsonbType::T_False:
  Branch (543:9): [True: 0, False: 0]
544
0
            return "bool";
545
0
        case JsonbType::T_Int8:
  Branch (545:9): [True: 0, False: 0]
546
0
        case JsonbType::T_Int16:
  Branch (546:9): [True: 0, False: 0]
547
0
        case JsonbType::T_Int32:
  Branch (547:9): [True: 0, False: 0]
548
0
            return "int";
549
0
        case JsonbType::T_Int64:
  Branch (549:9): [True: 0, False: 0]
550
0
            return "bigint";
551
0
        case JsonbType::T_Int128:
  Branch (551:9): [True: 0, False: 0]
552
0
            return "largeint";
553
0
        case JsonbType::T_Double:
  Branch (553:9): [True: 0, False: 0]
554
0
            return "double";
555
0
        case JsonbType::T_Float:
  Branch (555:9): [True: 0, False: 0]
556
0
            return "float";
557
0
        case JsonbType::T_String:
  Branch (557:9): [True: 0, False: 0]
558
0
            return "string";
559
0
        case JsonbType::T_Binary:
  Branch (559:9): [True: 0, False: 0]
560
0
            return "binary";
561
0
        case JsonbType::T_Object:
  Branch (561:9): [True: 0, False: 0]
562
0
            return "object";
563
0
        case JsonbType::T_Array:
  Branch (563:9): [True: 0, False: 0]
564
0
            return "array";
565
0
        default:
  Branch (565:9): [True: 0, False: 0]
566
0
            return "unknown";
567
0
        }
568
0
    }
569
570
    // size of the total packed bytes
571
    unsigned int numPackedBytes() const;
572
573
    // size of the value in bytes
574
    unsigned int size() const;
575
576
    //Get the number of jsonbvalue elements
577
    int length() const;
578
579
    //Whether to include the jsonbvalue rhs
580
    bool contains(JsonbValue* rhs) const;
581
582
    // get the raw byte array of the value
583
    const char* getValuePtr() const;
584
585
    // find the JSONB value by JsonbPath
586
    JsonbValue* findValue(JsonbPath& path, hDictFind handler);
587
    friend class JsonbDocument;
588
589
protected:
590
    JsonbType type_; // type info
591
592
    JsonbValue();
593
};
594
595
/*
596
 * NumerValT is the template class (derived from JsonbValue) of all number
597
 * types (integers and double).
598
 */
599
template <class T>
600
class NumberValT : public JsonbValue {
601
public:
602
1.61M
    T val() const { return num_; }
_ZNK5doris10NumberValTIaE3valEv
Line
Count
Source
602
518
    T val() const { return num_; }
_ZNK5doris10NumberValTIsE3valEv
Line
Count
Source
602
446
    T val() const { return num_; }
_ZNK5doris10NumberValTIiE3valEv
Line
Count
Source
602
3.49k
    T val() const { return num_; }
_ZNK5doris10NumberValTIlE3valEv
Line
Count
Source
602
846k
    T val() const { return num_; }
_ZNK5doris10NumberValTInE3valEv
Line
Count
Source
602
1.02k
    T val() const { return num_; }
_ZNK5doris10NumberValTIdE3valEv
Line
Count
Source
602
765k
    T val() const { return num_; }
Unexecuted instantiation: _ZNK5doris10NumberValTIfE3valEv
603
604
    unsigned int numPackedBytes() const { return sizeof(JsonbValue) + sizeof(T); }
605
606
    // catch all unknow specialization of the template class
607
    bool setVal(T value) { return false; }
608
609
private:
610
    T num_;
611
612
    NumberValT();
613
};
614
615
using JsonbInt8Val = NumberValT<int8_t>;
616
617
// override setVal for Int8Val
618
template <>
619
0
inline bool JsonbInt8Val::setVal(int8_t value) {
620
0
    if (!isInt8()) {
621
0
        return false;
622
0
    }
623
0
624
0
    num_ = value;
625
0
    return true;
626
0
}
627
628
using JsonbInt16Val = NumberValT<int16_t>;
629
630
// override setVal for Int16Val
631
template <>
632
0
inline bool JsonbInt16Val::setVal(int16_t value) {
633
0
    if (!isInt16()) {
634
0
        return false;
635
0
    }
636
0
637
0
    num_ = value;
638
0
    return true;
639
0
}
640
using JsonbInt32Val = NumberValT<int32_t>;
641
642
// override setVal for Int32Val
643
template <>
644
0
inline bool JsonbInt32Val::setVal(int32_t value) {
645
0
    if (!isInt32()) {
646
0
        return false;
647
0
    }
648
0
649
0
    num_ = value;
650
0
    return true;
651
0
}
652
653
using JsonbInt64Val = NumberValT<int64_t>;
654
655
// override setVal for Int64Val
656
template <>
657
0
inline bool JsonbInt64Val::setVal(int64_t value) {
658
0
    if (!isInt64()) {
659
0
        return false;
660
0
    }
661
0
662
0
    num_ = value;
663
0
    return true;
664
0
}
665
666
using JsonbInt128Val = NumberValT<int128_t>;
667
668
// override setVal for Int128Val
669
template <>
670
0
inline bool JsonbInt128Val::setVal(int128_t value) {
671
0
    if (!isInt128()) {
672
0
        return false;
673
0
    }
674
0
675
0
    num_ = value;
676
0
    return true;
677
0
}
678
679
using JsonbDoubleVal = NumberValT<double>;
680
681
// override setVal for DoubleVal
682
template <>
683
0
inline bool JsonbDoubleVal::setVal(double value) {
684
0
    if (!isDouble()) {
685
0
        return false;
686
0
    }
687
0
688
0
    num_ = value;
689
0
    return true;
690
0
}
691
692
using JsonbFloatVal = NumberValT<float>;
693
694
// override setVal for DoubleVal
695
template <>
696
0
inline bool JsonbFloatVal::setVal(float value) {
697
0
    if (!isFloat()) {
698
0
        return false;
699
0
    }
700
0
701
0
    num_ = value;
702
0
    return true;
703
0
}
704
705
// A class to get an integer
706
class JsonbIntVal : public JsonbValue {
707
public:
708
76
    int128_t val() const {
709
76
        switch (type_) {
710
30
        case JsonbType::T_Int8:
  Branch (710:9): [True: 30, False: 46]
711
30
            return ((JsonbInt8Val*)this)->val();
712
24
        case JsonbType::T_Int16:
  Branch (712:9): [True: 24, False: 52]
713
24
            return ((JsonbInt16Val*)this)->val();
714
12
        case JsonbType::T_Int32:
  Branch (714:9): [True: 12, False: 64]
715
12
            return ((JsonbInt32Val*)this)->val();
716
10
        case JsonbType::T_Int64:
  Branch (716:9): [True: 10, False: 66]
717
10
            return ((JsonbInt64Val*)this)->val();
718
0
        case JsonbType::T_Int128:
  Branch (718:9): [True: 0, False: 76]
719
0
            return ((JsonbInt128Val*)this)->val();
720
0
        default:
  Branch (720:9): [True: 0, False: 76]
721
0
            return 0;
722
76
        }
723
76
    }
724
0
    bool setVal(int128_t val) {
725
0
        switch (type_) {
726
0
        case JsonbType::T_Int8:
727
0
            if (val < std::numeric_limits<int8_t>::min() ||
728
0
                val > std::numeric_limits<int8_t>::max()) {
729
0
                return false;
730
0
            }
731
0
            return ((JsonbInt8Val*)this)->setVal((int8_t)val);
732
0
        case JsonbType::T_Int16:
733
0
            if (val < std::numeric_limits<int16_t>::min() ||
734
0
                val > std::numeric_limits<int16_t>::max()) {
735
0
                return false;
736
0
            }
737
0
            return ((JsonbInt16Val*)this)->setVal((int16_t)val);
738
0
        case JsonbType::T_Int32:
739
0
            if (val < std::numeric_limits<int32_t>::min() ||
740
0
                val > std::numeric_limits<int32_t>::max()) {
741
0
                return false;
742
0
            }
743
0
            return ((JsonbInt32Val*)this)->setVal((int32_t)val);
744
0
        case JsonbType::T_Int64:
745
0
            return ((JsonbInt64Val*)this)->setVal((int64_t)val);
746
0
        case JsonbType::T_Int128:
747
0
            return ((JsonbInt128Val*)this)->setVal(val);
748
0
        default:
749
0
            return false;
750
0
        }
751
0
    }
752
};
753
754
/*
755
 * BlobVal is the base class (derived from JsonbValue) for string and binary
756
 * types. The size_ indicates the total bytes of the payload_.
757
 */
758
class JsonbBlobVal : public JsonbValue {
759
public:
760
    // size of the blob payload only
761
3.17k
    unsigned int getBlobLen() const { return size_; }
762
763
    // return the blob as byte array
764
1.96M
    const char* getBlob() const { return payload_; }
765
766
    // size of the total packed bytes
767
1.96M
    unsigned int numPackedBytes() const { return sizeof(JsonbValue) + sizeof(size_) + size_; }
768
    friend class JsonbDocument;
769
770
protected:
771
    uint32_t size_;
772
    char payload_[0];
773
774
    // set new blob bytes
775
0
    bool internalSetVal(const char* blob, uint32_t blobSize) {
776
0
        // if we cannot fit the new blob, fail the operation
777
0
        if (blobSize > size_) {
778
0
            return false;
779
0
        }
780
0
781
0
        memcpy(payload_, blob, blobSize);
782
0
783
0
        // Set the reset of the bytes to 0.  Note we cannot change the size_ of the
784
0
        // current payload, as all values are packed.
785
0
        memset(payload_ + blobSize, 0, size_ - blobSize);
786
0
787
0
        return true;
788
0
    }
789
790
    JsonbBlobVal();
791
};
792
793
/*
794
 * Binary type
795
 */
796
class JsonbBinaryVal : public JsonbBlobVal {
797
public:
798
0
    bool setVal(const char* blob, uint32_t blobSize) {
799
0
        if (!isBinary()) {
800
0
            return false;
801
0
        }
802
0
803
0
        return internalSetVal(blob, blobSize);
804
0
    }
805
806
private:
807
    JsonbBinaryVal();
808
};
809
810
/*
811
 * String type
812
 * Note: JSONB string may not be a c-string (NULL-terminated)
813
 */
814
class JsonbStringVal : public JsonbBlobVal {
815
public:
816
0
    bool setVal(const char* str, uint32_t blobSize) {
817
0
        if (!isString()) {
818
0
            return false;
819
0
        }
820
0
821
0
        return internalSetVal(str, blobSize);
822
0
    }
823
    /*
824
    This function return the actual size of a string. Since for
825
    a string, it can be null-terminated with null paddings or it
826
    can take all the space in the payload_ without null in the end.
827
    So we need to check it to get the true actual length of a string.
828
  */
829
1.95M
    size_t length() {
830
        // It's an empty string
831
1.95M
        if (0 == size_) {
  Branch (831:13): [True: 143k, False: 1.81M]
832
143k
            return size_;
833
143k
        }
834
        // The string stored takes all the spaces in payload_
835
1.81M
        if (payload_[size_ - 1] != 0) {
  Branch (835:13): [True: 1.81M, False: 0]
836
1.81M
            return size_;
837
1.81M
        }
838
        // It's shorter than the size of payload_
839
0
        return strnlen(payload_, size_);
840
1.81M
    }
841
    // convert the string (case insensitive) to a boolean value
842
    // "false": 0
843
    // "true": 1
844
    // all other strings: -1
845
0
    int getBoolVal() {
846
0
        if (size_ == 4 && tolower(payload_[0]) == 't' && tolower(payload_[1]) == 'r' &&
847
0
            tolower(payload_[2]) == 'u' && tolower(payload_[3]) == 'e') {
848
0
            return 1;
849
0
        } else if (size_ == 5 && tolower(payload_[0]) == 'f' && tolower(payload_[1]) == 'a' &&
850
0
                   tolower(payload_[2]) == 'l' && tolower(payload_[3]) == 's' &&
851
0
                   tolower(payload_[4]) == 'e') {
852
0
            return 0;
853
0
        } else {
854
0
            return -1;
855
0
        }
856
0
    }
857
858
private:
859
    JsonbStringVal();
860
};
861
862
/*
863
 * ContainerVal is the base class (derived from JsonbValue) for object and
864
 * array types. The size_ indicates the total bytes of the payload_.
865
 */
866
class ContainerVal : public JsonbValue {
867
public:
868
    // size of the container payload only
869
10
    unsigned int getContainerSize() const { return size_; }
870
871
    // return the container payload as byte array
872
0
    const char* getPayload() const { return payload_; }
873
874
    // size of the total packed bytes
875
564k
    unsigned int numPackedBytes() const { return sizeof(JsonbValue) + sizeof(size_) + size_; }
876
    friend class JsonbDocument;
877
878
protected:
879
    uint32_t size_;
880
    char payload_[0];
881
882
    ContainerVal();
883
};
884
885
/*
886
 * Object type
887
 */
888
class ObjectVal : public ContainerVal {
889
public:
890
    using value_type = JsonbKeyValue;
891
    using pointer = value_type*;
892
    using const_pointer = const value_type*;
893
    using iterator = JsonbFwdIteratorT<pointer, ObjectVal>;
894
    using const_iterator = JsonbFwdIteratorT<const_pointer, ObjectVal>;
895
896
0
    const_iterator search(const char* key, hDictFind handler = nullptr) const {
897
0
        return const_cast<ObjectVal*>(this)->search(key, handler);
898
0
    }
899
900
0
    const_iterator search(const char* key, unsigned int klen, hDictFind handler = nullptr) const {
901
0
        return const_cast<ObjectVal*>(this)->search(key, klen, handler);
902
0
    }
903
904
0
    const_iterator search(int key_id) const { return const_cast<ObjectVal*>(this)->search(key_id); }
905
0
    iterator search(const char* key, hDictFind handler = nullptr) {
906
0
        if (!key) {
907
0
            return end();
908
0
        }
909
0
        return search(key, (unsigned int)strlen(key), handler);
910
0
    }
911
912
51
    iterator search(const char* key, unsigned int klen, hDictFind handler = nullptr) {
913
51
        if (!key || !klen) {
  Branch (913:13): [True: 0, False: 51]
  Branch (913:21): [True: 0, False: 51]
914
0
            return end();
915
0
        }
916
917
51
        int key_id = -1;
918
51
        if (handler && (key_id = handler(key, klen)) >= 0) {
  Branch (918:13): [True: 0, False: 51]
  Branch (918:24): [True: 0, False: 0]
919
0
            return search(key_id);
920
0
        }
921
51
        return internalSearch(key, klen);
922
51
    }
923
924
0
    iterator search(int key_id) {
925
0
        if (key_id < 0 || key_id > JsonbKeyValue::sMaxKeyId) {
  Branch (925:13): [True: 0, False: 0]
  Branch (925:27): [True: 0, False: 0]
926
0
            return end();
927
0
        }
928
929
0
        const char* pch = payload_;
930
0
        const char* fence = payload_ + size_;
931
932
0
        while (pch < fence) {
  Branch (932:16): [True: 0, False: 0]
933
0
            auto* pkey = (JsonbKeyValue*)(pch);
934
0
            if (!pkey->klen() && key_id == pkey->getKeyId()) {
  Branch (934:17): [True: 0, False: 0]
  Branch (934:34): [True: 0, False: 0]
935
0
                return iterator(pkey);
936
0
            }
937
0
            pch += pkey->numPackedBytes();
938
0
        }
939
940
0
        assert(pch == fence);
941
0
        return end();
942
0
    }
943
944
    // Get number of elements in object
945
0
    int numElem() const {
946
0
        const char* pch = payload_;
947
0
        const char* fence = payload_ + size_;
948
949
0
        unsigned int num = 0;
950
0
        while (pch < fence) {
  Branch (950:16): [True: 0, False: 0]
951
0
            auto* pkey = (JsonbKeyValue*)(pch);
952
0
            ++num;
953
0
            pch += pkey->numPackedBytes();
954
0
        }
955
956
0
        assert(pch == fence);
957
958
0
        return num;
959
0
    }
960
961
0
    JsonbKeyValue* getJsonbKeyValue(unsigned int i) const {
962
0
        const char* pch = payload_;
963
0
        const char* fence = payload_ + size_;
964
965
0
        unsigned int num = 0;
966
0
        while (pch < fence) {
  Branch (966:16): [True: 0, False: 0]
967
0
            auto* pkey = (JsonbKeyValue*)(pch);
968
0
            if (num == i) {
  Branch (968:17): [True: 0, False: 0]
969
0
                return pkey;
970
0
            }
971
0
            ++num;
972
0
            pch += pkey->numPackedBytes();
973
0
        }
974
975
0
        assert(pch == fence);
976
977
0
        return nullptr;
978
0
    }
979
980
0
    JsonbValue* find(const char* key, hDictFind handler = nullptr) const {
981
0
        return const_cast<ObjectVal*>(this)->find(key, handler);
982
0
    }
983
984
0
    JsonbValue* find(const char* key, unsigned int klen, hDictFind handler = nullptr) const {
985
0
        return const_cast<ObjectVal*>(this)->find(key, klen, handler);
986
0
    }
987
0
    JsonbValue* find(int key_id) const { return const_cast<ObjectVal*>(this)->find(key_id); }
988
989
    // find the JSONB value by a key string (null terminated)
990
0
    JsonbValue* find(const char* key, hDictFind handler = nullptr) {
991
0
        if (!key) {
992
0
            return nullptr;
993
0
        }
994
0
        return find(key, (unsigned int)strlen(key), handler);
995
0
    }
996
997
    // find the JSONB value by a key string (with length)
998
51
    JsonbValue* find(const char* key, unsigned int klen, hDictFind handler = nullptr) {
999
51
        iterator kv = search(key, klen, handler);
1000
51
        if (end() == kv) {
  Branch (1000:13): [True: 18, False: 33]
1001
18
            return nullptr;
1002
18
        }
1003
33
        return kv->value();
1004
51
    }
1005
1006
    // find the JSONB value by a key dictionary ID
1007
0
    JsonbValue* find(int key_id) {
1008
0
        iterator kv = search(key_id);
1009
0
        if (end() == kv) {
1010
0
            return nullptr;
1011
0
        }
1012
0
        return kv->value();
1013
0
    }
1014
1015
3.18k
    iterator begin() { return iterator((pointer)payload_); }
1016
1017
249k
    const_iterator begin() const { return const_iterator((pointer)payload_); }
1018
1019
14.6k
    iterator end() { return iterator((pointer)(payload_ + size_)); }
1020
1021
249k
    const_iterator end() const { return const_iterator((pointer)(payload_ + size_)); }
1022
1023
private:
1024
51
    iterator internalSearch(const char* key, unsigned int klen) {
1025
51
        const char* pch = payload_;
1026
51
        const char* fence = payload_ + size_;
1027
1028
57
        while (pch < fence) {
  Branch (1028:16): [True: 39, False: 18]
1029
39
            auto* pkey = (JsonbKeyValue*)(pch);
1030
39
            if (klen == pkey->klen() && strncmp(key, pkey->getKeyStr(), klen) == 0) {
  Branch (1030:17): [True: 39, False: 0]
  Branch (1030:41): [True: 33, False: 6]
1031
33
                return iterator(pkey);
1032
33
            }
1033
6
            pch += pkey->numPackedBytes();
1034
6
        }
1035
1036
18
        assert(pch == fence);
1037
1038
0
        return end();
1039
51
    }
1040
1041
private:
1042
    ObjectVal();
1043
};
1044
1045
/*
1046
 * Array type
1047
 */
1048
class ArrayVal : public ContainerVal {
1049
public:
1050
    using value_type = JsonbValue;
1051
    using pointer = value_type*;
1052
    using const_pointer = const value_type*;
1053
    using iterator = JsonbFwdIteratorT<pointer, ArrayVal>;
1054
    using const_iterator = JsonbFwdIteratorT<const_pointer, ArrayVal>;
1055
1056
    // get the JSONB value at index
1057
231
    JsonbValue* get(int idx) const {
1058
231
        if (idx < 0) {
  Branch (1058:13): [True: 0, False: 231]
1059
0
            return nullptr;
1060
0
        }
1061
1062
231
        const char* pch = payload_;
1063
231
        const char* fence = payload_ + size_;
1064
1065
564
        while (pch < fence && idx-- > 0) {
  Branch (1065:16): [True: 501, False: 63]
  Branch (1065:31): [True: 333, False: 168]
1066
333
            pch += ((JsonbValue*)pch)->numPackedBytes();
1067
333
        }
1068
231
        if (idx > 0 || pch == fence) {
  Branch (1068:13): [True: 9, False: 222]
  Branch (1068:24): [True: 54, False: 168]
1069
63
            return nullptr;
1070
63
        }
1071
1072
168
        return (JsonbValue*)pch;
1073
231
    }
1074
1075
    // Get number of elements in array
1076
0
    int numElem() const {
1077
0
        const char* pch = payload_;
1078
0
        const char* fence = payload_ + size_;
1079
1080
0
        unsigned int num = 0;
1081
0
        while (pch < fence) {
  Branch (1081:16): [True: 0, False: 0]
1082
0
            ++num;
1083
0
            pch += ((JsonbValue*)pch)->numPackedBytes();
1084
0
        }
1085
1086
0
        assert(pch == fence);
1087
1088
0
        return num;
1089
0
    }
1090
1091
0
    iterator begin() { return iterator((pointer)payload_); }
1092
1093
310k
    const_iterator begin() const { return const_iterator((pointer)payload_); }
1094
1095
0
    iterator end() { return iterator((pointer)(payload_ + size_)); }
1096
1097
310k
    const_iterator end() const { return const_iterator((pointer)(payload_ + size_)); }
1098
1099
private:
1100
    ArrayVal();
1101
};
1102
1103
inline Status JsonbDocument::checkAndCreateDocument(const char* pb, size_t size,
1104
26.9k
                                                    JsonbDocument** doc) {
1105
26.9k
    *doc = nullptr;
1106
26.9k
    if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) {
  Branch (1106:9): [True: 0, False: 26.9k]
  Branch (1106:16): [True: 30, False: 26.9k]
1107
30
        return Status::InvalidArgument("Invalid JSONB document: too small size({}) or null pointer",
1108
30
                                       size);
1109
30
    }
1110
1111
26.9k
    auto* doc_ptr = (JsonbDocument*)pb;
1112
26.9k
    if (doc_ptr->header_.ver_ != JSONB_VER) {
Line
Count
Source
88
26.9k
#define JSONB_VER 1
  Branch (1112:9): [True: 2, False: 26.9k]
1113
2
        return Status::InvalidArgument("Invalid JSONB document: invalid version({})",
1114
2
                                       doc_ptr->header_.ver_);
1115
2
    }
1116
1117
26.9k
    auto* val = (JsonbValue*)doc_ptr->payload_;
1118
26.9k
    if (val->type() < JsonbType::T_Null || val->type() >= JsonbType::NUM_TYPES ||
  Branch (1118:9): [True: 0, False: 26.9k]
  Branch (1118:44): [True: 0, False: 26.9k]
1119
26.9k
        size != sizeof(JsonbHeader) + val->numPackedBytes()) {
  Branch (1119:9): [True: 0, False: 26.9k]
1120
0
        return Status::InvalidArgument("Invalid JSONB document: invalid type({}) or size({})",
1121
0
                                       static_cast<JsonbTypeUnder>(val->type()), size);
1122
0
    }
1123
1124
26.9k
    *doc = doc_ptr;
1125
26.9k
    return Status::OK();
1126
26.9k
}
1127
0
inline void JsonbDocument::setValue(const JsonbValue* value) {
1128
0
    memcpy(payload_, value, value->numPackedBytes());
1129
0
}
1130
1131
21
inline JsonbValue* JsonbDocument::createValue(const char* pb, uint32_t size) {
1132
21
    if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) {
  Branch (1132:9): [True: 0, False: 21]
  Branch (1132:16): [True: 0, False: 21]
1133
0
        return nullptr;
1134
0
    }
1135
1136
21
    auto* doc = (JsonbDocument*)pb;
1137
21
    if (doc->header_.ver_ != JSONB_VER) {
Line
Count
Source
88
21
#define JSONB_VER 1
  Branch (1137:9): [True: 0, False: 21]
1138
0
        return nullptr;
1139
0
    }
1140
1141
21
    auto* val = (JsonbValue*)doc->payload_;
1142
21
    if (size != sizeof(JsonbHeader) + val->numPackedBytes()) {
  Branch (1142:9): [True: 0, False: 21]
1143
0
        return nullptr;
1144
0
    }
1145
1146
21
    return val;
1147
21
}
1148
1149
0
inline unsigned int JsonbDocument::numPackedBytes() const {
1150
0
    return ((const JsonbValue*)payload_)->numPackedBytes() + sizeof(header_);
1151
0
}
1152
1153
760k
inline unsigned int JsonbKeyValue::numPackedBytes() const {
1154
760k
    unsigned int ks = keyPackedBytes();
1155
760k
    auto* val = (JsonbValue*)(((char*)this) + ks);
1156
760k
    return ks + val->numPackedBytes();
1157
760k
}
1158
1159
// Poor man's "virtual" function JsonbValue::numPackedBytes
1160
4.25M
inline unsigned int JsonbValue::numPackedBytes() const {
1161
4.25M
    switch (type_) {
1162
91.3k
    case JsonbType::T_Null:
  Branch (1162:5): [True: 91.3k, False: 4.16M]
1163
102k
    case JsonbType::T_True:
  Branch (1163:5): [True: 10.8k, False: 4.24M]
1164
112k
    case JsonbType::T_False: {
  Branch (1164:5): [True: 10.8k, False: 4.24M]
1165
112k
        return sizeof(type_);
1166
102k
    }
1167
1168
628
    case JsonbType::T_Int8: {
  Branch (1168:5): [True: 628, False: 4.25M]
1169
628
        return sizeof(type_) + sizeof(int8_t);
1170
102k
    }
1171
480
    case JsonbType::T_Int16: {
  Branch (1171:5): [True: 480, False: 4.25M]
1172
480
        return sizeof(type_) + sizeof(int16_t);
1173
102k
    }
1174
3.53k
    case JsonbType::T_Int32: {
  Branch (1174:5): [True: 3.53k, False: 4.25M]
1175
3.53k
        return sizeof(type_) + sizeof(int32_t);
1176
102k
    }
1177
846k
    case JsonbType::T_Int64: {
  Branch (1177:5): [True: 846k, False: 3.41M]
1178
846k
        return sizeof(type_) + sizeof(int64_t);
1179
102k
    }
1180
765k
    case JsonbType::T_Double: {
  Branch (1180:5): [True: 765k, False: 3.49M]
1181
765k
        return sizeof(type_) + sizeof(double);
1182
102k
    }
1183
0
    case JsonbType::T_Float: {
  Branch (1183:5): [True: 0, False: 4.25M]
1184
0
        return sizeof(type_) + sizeof(float);
1185
102k
    }
1186
1.02k
    case JsonbType::T_Int128: {
  Branch (1186:5): [True: 1.02k, False: 4.25M]
1187
1.02k
        return sizeof(type_) + sizeof(int128_t);
1188
102k
    }
1189
1.96M
    case JsonbType::T_String:
  Branch (1189:5): [True: 1.96M, False: 2.29M]
1190
1.96M
    case JsonbType::T_Binary: {
  Branch (1190:5): [True: 4.44k, False: 4.25M]
1191
1.96M
        return ((JsonbBlobVal*)(this))->numPackedBytes();
1192
1.96M
    }
1193
1194
253k
    case JsonbType::T_Object:
  Branch (1194:5): [True: 253k, False: 4.00M]
1195
564k
    case JsonbType::T_Array: {
  Branch (1195:5): [True: 311k, False: 3.94M]
1196
564k
        return ((ContainerVal*)(this))->numPackedBytes();
1197
253k
    }
1198
0
    default:
  Branch (1198:5): [True: 0, False: 4.25M]
1199
0
        return 0;
1200
4.25M
    }
1201
4.25M
}
1202
1203
55
inline unsigned int JsonbValue::size() const {
1204
55
    switch (type_) {
1205
14
    case JsonbType::T_Int8: {
  Branch (1205:5): [True: 14, False: 41]
1206
14
        return sizeof(int8_t);
1207
0
    }
1208
2
    case JsonbType::T_Int16: {
  Branch (1208:5): [True: 2, False: 53]
1209
2
        return sizeof(int16_t);
1210
0
    }
1211
1
    case JsonbType::T_Int32: {
  Branch (1211:5): [True: 1, False: 54]
1212
1
        return sizeof(int32_t);
1213
0
    }
1214
1
    case JsonbType::T_Int64: {
  Branch (1214:5): [True: 1, False: 54]
1215
1
        return sizeof(int64_t);
1216
0
    }
1217
3
    case JsonbType::T_Double: {
  Branch (1217:5): [True: 3, False: 52]
1218
3
        return sizeof(double);
1219
0
    }
1220
0
    case JsonbType::T_Float: {
  Branch (1220:5): [True: 0, False: 55]
1221
0
        return sizeof(float);
1222
0
    }
1223
0
    case JsonbType::T_Int128: {
  Branch (1223:5): [True: 0, False: 55]
1224
0
        return sizeof(int128_t);
1225
0
    }
1226
18
    case JsonbType::T_String:
  Branch (1226:5): [True: 18, False: 37]
1227
18
    case JsonbType::T_Binary: {
  Branch (1227:5): [True: 0, False: 55]
1228
18
        return ((JsonbBlobVal*)(this))->getBlobLen();
1229
18
    }
1230
1231
5
    case JsonbType::T_Object:
  Branch (1231:5): [True: 5, False: 50]
1232
10
    case JsonbType::T_Array: {
  Branch (1232:5): [True: 5, False: 50]
1233
10
        return ((ContainerVal*)(this))->getContainerSize();
1234
5
    }
1235
2
    case JsonbType::T_Null:
  Branch (1235:5): [True: 2, False: 53]
1236
4
    case JsonbType::T_True:
  Branch (1236:5): [True: 2, False: 53]
1237
6
    case JsonbType::T_False:
  Branch (1237:5): [True: 2, False: 53]
1238
6
    default:
  Branch (1238:5): [True: 0, False: 55]
1239
6
        return 0;
1240
55
    }
1241
55
}
1242
1243
0
inline int JsonbValue::length() const {
1244
0
    switch (type_) {
1245
0
    case JsonbType::T_Int8:
  Branch (1245:5): [True: 0, False: 0]
1246
0
    case JsonbType::T_Int16:
  Branch (1246:5): [True: 0, False: 0]
1247
0
    case JsonbType::T_Int32:
  Branch (1247:5): [True: 0, False: 0]
1248
0
    case JsonbType::T_Int64:
  Branch (1248:5): [True: 0, False: 0]
1249
0
    case JsonbType::T_Double:
  Branch (1249:5): [True: 0, False: 0]
1250
0
    case JsonbType::T_Float:
  Branch (1250:5): [True: 0, False: 0]
1251
0
    case JsonbType::T_Int128:
  Branch (1251:5): [True: 0, False: 0]
1252
0
    case JsonbType::T_String:
  Branch (1252:5): [True: 0, False: 0]
1253
0
    case JsonbType::T_Binary:
  Branch (1253:5): [True: 0, False: 0]
1254
0
    case JsonbType::T_Null:
  Branch (1254:5): [True: 0, False: 0]
1255
0
    case JsonbType::T_True:
  Branch (1255:5): [True: 0, False: 0]
1256
0
    case JsonbType::T_False: {
  Branch (1256:5): [True: 0, False: 0]
1257
0
        return 1;
1258
0
    }
1259
0
    case JsonbType::T_Object: {
  Branch (1259:5): [True: 0, False: 0]
1260
0
        return ((ObjectVal*)this)->numElem();
1261
0
    }
1262
0
    case JsonbType::T_Array: {
  Branch (1262:5): [True: 0, False: 0]
1263
0
        return ((ArrayVal*)this)->numElem();
1264
0
    }
1265
0
    default:
  Branch (1265:5): [True: 0, False: 0]
1266
0
        return 0;
1267
0
    }
1268
0
}
1269
1270
0
inline bool JsonbValue::contains(JsonbValue* rhs) const {
1271
0
    switch (type_) {
1272
0
    case JsonbType::T_Int8:
  Branch (1272:5): [True: 0, False: 0]
1273
0
    case JsonbType::T_Int16:
  Branch (1273:5): [True: 0, False: 0]
1274
0
    case JsonbType::T_Int32:
  Branch (1274:5): [True: 0, False: 0]
1275
0
    case JsonbType::T_Int64:
  Branch (1275:5): [True: 0, False: 0]
1276
0
    case JsonbType::T_Int128: {
  Branch (1276:5): [True: 0, False: 0]
1277
0
        return ((JsonbIntVal*)(this))->val() == ((JsonbIntVal*)(rhs))->val();
1278
0
    }
1279
0
    case JsonbType::T_Double: {
  Branch (1279:5): [True: 0, False: 0]
1280
0
        if (rhs->isDouble()) {
  Branch (1280:13): [True: 0, False: 0]
1281
0
            return ((JsonbDoubleVal*)(this))->val() == ((JsonbDoubleVal*)(rhs))->val();
1282
0
        }
1283
0
        return false;
1284
0
    }
1285
0
    case JsonbType::T_Float: {
  Branch (1285:5): [True: 0, False: 0]
1286
0
        if (rhs->isDouble()) {
  Branch (1286:13): [True: 0, False: 0]
1287
0
            return ((JsonbFloatVal*)(this))->val() == ((JsonbFloatVal*)(rhs))->val();
1288
0
        }
1289
0
        return false;
1290
0
    }
1291
0
    case JsonbType::T_String:
  Branch (1291:5): [True: 0, False: 0]
1292
0
    case JsonbType::T_Binary: {
  Branch (1292:5): [True: 0, False: 0]
1293
0
        if (rhs->isString()) {
  Branch (1293:13): [True: 0, False: 0]
1294
0
            auto* str_value1 = (JsonbStringVal*)this;
1295
0
            auto* str_value2 = (JsonbStringVal*)rhs;
1296
0
            return str_value1->length() == str_value2->length() &&
  Branch (1296:20): [True: 0, False: 0]
1297
0
                   std::memcmp(str_value1->getBlob(), str_value2->getBlob(),
  Branch (1297:20): [True: 0, False: 0]
1298
0
                               str_value1->length()) == 0;
1299
0
        }
1300
0
        return false;
1301
0
    }
1302
0
    case JsonbType::T_Array: {
  Branch (1302:5): [True: 0, False: 0]
1303
0
        int lhs_num = ((ArrayVal*)this)->numElem();
1304
0
        if (rhs->isArray()) {
  Branch (1304:13): [True: 0, False: 0]
1305
0
            int rhs_num = ((ArrayVal*)rhs)->numElem();
1306
0
            if (rhs_num > lhs_num) {
  Branch (1306:17): [True: 0, False: 0]
1307
0
                return false;
1308
0
            }
1309
0
            int contains_num = 0;
1310
0
            for (int i = 0; i < lhs_num; ++i) {
  Branch (1310:29): [True: 0, False: 0]
1311
0
                for (int j = 0; j < rhs_num; ++j) {
  Branch (1311:33): [True: 0, False: 0]
1312
0
                    if (((ArrayVal*)this)->get(i)->contains(((ArrayVal*)rhs)->get(j))) {
  Branch (1312:25): [True: 0, False: 0]
1313
0
                        contains_num++;
1314
0
                        break;
1315
0
                    }
1316
0
                }
1317
0
            }
1318
0
            return contains_num == rhs_num;
1319
0
        }
1320
0
        for (int i = 0; i < lhs_num; ++i) {
  Branch (1320:25): [True: 0, False: 0]
1321
0
            if (((ArrayVal*)this)->get(i)->contains(rhs)) {
  Branch (1321:17): [True: 0, False: 0]
1322
0
                return true;
1323
0
            }
1324
0
        }
1325
0
        return false;
1326
0
    }
1327
0
    case JsonbType::T_Object: {
  Branch (1327:5): [True: 0, False: 0]
1328
0
        if (rhs->isObject()) {
  Branch (1328:13): [True: 0, False: 0]
1329
0
            const auto* obj_value1 = (ObjectVal*)this;
1330
0
            const auto* obj_value2 = (ObjectVal*)rhs;
1331
0
            for (int i = 0; i < obj_value2->numElem(); ++i) {
  Branch (1331:29): [True: 0, False: 0]
1332
0
                JsonbKeyValue* key = obj_value2->getJsonbKeyValue(i);
1333
0
                JsonbValue* value = obj_value1->find(key->getKeyStr(), key->klen());
1334
0
                if (value == nullptr || !value->contains(key->value())) {
  Branch (1334:21): [True: 0, False: 0]
  Branch (1334:41): [True: 0, False: 0]
1335
0
                    return false;
1336
0
                }
1337
0
            }
1338
0
            return true;
1339
0
        }
1340
0
        return false;
1341
0
    }
1342
0
    case JsonbType::T_Null: {
  Branch (1342:5): [True: 0, False: 0]
1343
0
        return rhs->isNull();
1344
0
    }
1345
0
    case JsonbType::T_True: {
  Branch (1345:5): [True: 0, False: 0]
1346
0
        return rhs->isTrue();
1347
0
    }
1348
0
    case JsonbType::T_False: {
  Branch (1348:5): [True: 0, False: 0]
1349
0
        return rhs->isFalse();
1350
0
    }
1351
0
    default:
  Branch (1351:5): [True: 0, False: 0]
1352
0
        return false;
1353
0
    }
1354
0
}
1355
1356
0
inline const char* JsonbValue::getValuePtr() const {
1357
0
    switch (type_) {
1358
0
    case JsonbType::T_Int8:
1359
0
    case JsonbType::T_Int16:
1360
0
    case JsonbType::T_Int32:
1361
0
    case JsonbType::T_Int64:
1362
0
    case JsonbType::T_Double:
1363
0
    case JsonbType::T_Float:
1364
0
    case JsonbType::T_Int128:
1365
0
        return ((char*)this) + sizeof(JsonbType);
1366
0
1367
0
    case JsonbType::T_String:
1368
0
    case JsonbType::T_Binary:
1369
0
        return ((JsonbBlobVal*)(this))->getBlob();
1370
0
1371
0
    case JsonbType::T_Object:
1372
0
    case JsonbType::T_Array:
1373
0
        return ((ContainerVal*)(this))->getPayload();
1374
0
1375
0
    case JsonbType::T_Null:
1376
0
    case JsonbType::T_True:
1377
0
    case JsonbType::T_False:
1378
0
    default:
1379
0
        return nullptr;
1380
0
    }
1381
0
}
1382
1383
846
inline bool JsonbPath::seek(const char* key_path, size_t kp_len) {
1384
    //path invalid
1385
846
    if (!key_path || kp_len == 0) {
  Branch (1385:9): [True: 0, False: 846]
  Branch (1385:22): [True: 0, False: 846]
1386
0
        return false;
1387
0
    }
1388
846
    Stream stream(key_path, kp_len);
1389
846
    stream.skip_whitespace();
1390
846
    if (stream.exhausted() || stream.read() != SCOPE) {
  Branch (1390:9): [True: 0, False: 846]
  Branch (1390:31): [True: 0, False: 846]
1391
        //path invalid
1392
0
        return false;
1393
0
    }
1394
1395
1.69k
    while (!stream.exhausted()) {
  Branch (1395:12): [True: 850, False: 846]
1396
850
        stream.skip_whitespace();
1397
850
        stream.clear_leg_ptr();
1398
850
        stream.clear_leg_len();
1399
1400
850
        if (!JsonbPath::parsePath(&stream, this)) {
  Branch (1400:13): [True: 0, False: 850]
1401
            //path invalid
1402
0
            return false;
1403
0
        }
1404
850
    }
1405
846
    return true;
1406
846
}
1407
1408
816
inline JsonbValue* JsonbValue::findValue(JsonbPath& path, hDictFind handler) {
1409
816
    JsonbValue* pval = this;
1410
1.05k
    for (size_t i = 0; i < path.get_leg_vector_size(); ++i) {
  Branch (1410:24): [True: 732, False: 321]
1411
732
        switch (path.get_leg_from_leg_vector(i)->type) {
  Branch (1411:17): [True: 0, False: 732]
1412
204
        case MEMBER_CODE: {
  Branch (1412:9): [True: 204, False: 528]
1413
204
            if (LIKELY(pval->type_ == JsonbType::T_Object)) {
1414
51
                if (path.get_leg_from_leg_vector(i)->leg_len == 1 &&
  Branch (1414:21): [True: 0, False: 51]
1415
51
                    *path.get_leg_from_leg_vector(i)->leg_ptr == WILDCARD) {
  Branch (1415:21): [True: 0, False: 0]
1416
0
                    continue;
1417
0
                }
1418
1419
51
                pval = ((ObjectVal*)pval)
1420
51
                               ->find(path.get_leg_from_leg_vector(i)->leg_ptr,
1421
51
                                      path.get_leg_from_leg_vector(i)->leg_len, handler);
1422
1423
51
                if (!pval) {
  Branch (1423:21): [True: 18, False: 33]
1424
18
                    return nullptr;
1425
18
                }
1426
33
                continue;
1427
153
            } else {
1428
153
                return nullptr;
1429
153
            }
1430
204
        }
1431
528
        case ARRAY_CODE: {
  Branch (1431:9): [True: 528, False: 204]
1432
528
            if (path.get_leg_from_leg_vector(i)->leg_len == 1 &&
  Branch (1432:17): [True: 0, False: 528]
1433
528
                *path.get_leg_from_leg_vector(i)->leg_ptr == WILDCARD) {
  Branch (1433:17): [True: 0, False: 0]
1434
0
                if (LIKELY(pval->type_ == JsonbType::T_Array)) {
1435
0
                    continue;
1436
0
                } else {
1437
0
                    return nullptr;
1438
0
                }
1439
0
            }
1440
1441
528
            if (pval->type_ == JsonbType::T_Object &&
  Branch (1441:17): [True: 54, False: 474]
1442
528
                path.get_leg_from_leg_vector(i)->array_index == 0) {
  Branch (1442:17): [True: 36, False: 18]
1443
36
                continue;
1444
36
            }
1445
1446
492
            if (pval->type_ != JsonbType::T_Array ||
  Branch (1446:17): [True: 261, False: 231]
1447
492
                path.get_leg_from_leg_vector(i)->leg_ptr != nullptr ||
  Branch (1447:17): [True: 0, False: 231]
1448
492
                path.get_leg_from_leg_vector(i)->leg_len != 0) {
  Branch (1448:17): [True: 0, False: 231]
1449
261
                return nullptr;
1450
261
            }
1451
1452
231
            if (path.get_leg_from_leg_vector(i)->array_index >= 0) {
  Branch (1452:17): [True: 231, False: 0]
1453
231
                pval = ((ArrayVal*)pval)->get(path.get_leg_from_leg_vector(i)->array_index);
1454
231
            } else {
1455
0
                pval = ((ArrayVal*)pval)
1456
0
                               ->get(((ArrayVal*)pval)->numElem() +
1457
0
                                     path.get_leg_from_leg_vector(i)->array_index);
1458
0
            }
1459
1460
231
            if (!pval) {
  Branch (1460:17): [True: 63, False: 168]
1461
63
                return nullptr;
1462
63
            }
1463
168
            continue;
1464
231
        }
1465
732
        }
1466
732
    }
1467
321
    return pval;
1468
816
}
1469
1470
850
inline bool JsonbPath::parsePath(Stream* stream, JsonbPath* path) {
1471
    // $[0]
1472
850
    if (stream->peek() == BEGIN_ARRAY) {
  Branch (1472:9): [True: 542, False: 308]
1473
542
        return parse_array(stream, path);
1474
542
    }
1475
    // $.a or $.[0]
1476
308
    else if (stream->peek() == BEGIN_MEMBER) {
  Branch (1476:14): [True: 308, False: 0]
1477
        // advance past the .
1478
308
        stream->skip(1);
1479
1480
308
        if (stream->exhausted()) {
  Branch (1480:13): [True: 0, False: 308]
1481
0
            return false;
1482
0
        }
1483
1484
        // $.[0]
1485
308
        if (stream->peek() == BEGIN_ARRAY) {
  Branch (1485:13): [True: 0, False: 308]
1486
0
            return parse_array(stream, path);
1487
0
        }
1488
        // $.a
1489
308
        else {
1490
308
            return parse_member(stream, path);
1491
308
        }
1492
308
    } else {
1493
0
        return false; //invalid json path
1494
0
    }
1495
850
}
1496
1497
542
inline bool JsonbPath::parse_array(Stream* stream, JsonbPath* path) {
1498
542
    assert(stream->peek() == BEGIN_ARRAY);
1499
0
    stream->skip(1);
1500
542
    if (stream->exhausted()) {
  Branch (1500:9): [True: 0, False: 542]
1501
0
        return false;
1502
0
    }
1503
1504
542
    if (stream->peek() == WILDCARD) {
  Branch (1504:9): [True: 0, False: 542]
1505
0
        stream->set_leg_ptr(const_cast<char*>(stream->position()));
1506
0
        stream->add_leg_len();
1507
0
        stream->skip(1);
1508
0
        if (stream->exhausted()) {
  Branch (1508:13): [True: 0, False: 0]
1509
0
            return false;
1510
0
        }
1511
1512
0
        if (stream->peek() == END_ARRAY) {
  Branch (1512:13): [True: 0, False: 0]
1513
0
            std::unique_ptr<leg_info> leg(
1514
0
                    new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, ARRAY_CODE));
1515
0
            path->add_leg_to_leg_vector(std::move(leg));
1516
0
            stream->skip(1);
1517
0
            return true;
1518
0
        } else {
1519
0
            return false;
1520
0
        }
1521
0
    }
1522
1523
542
    stream->set_leg_ptr(const_cast<char*>(stream->position()));
1524
1525
1.08k
    for (; !stream->exhausted() && stream->peek() != END_ARRAY; stream->skip(1)) {
  Branch (1525:12): [True: 1.08k, False: 0]
  Branch (1525:36): [True: 542, False: 542]
1526
542
        stream->add_leg_len();
1527
542
    }
1528
1529
542
    if (stream->exhausted() || stream->peek() != END_ARRAY) {
  Branch (1529:9): [True: 0, False: 542]
  Branch (1529:32): [True: 0, False: 542]
1530
0
        return false;
1531
542
    } else {
1532
542
        stream->skip(1);
1533
542
    }
1534
1535
    //parse array index to int
1536
1537
542
    std::string_view idx_string(stream->get_leg_ptr(), stream->get_leg_len());
1538
542
    int index = 0;
1539
1540
542
    if (stream->get_leg_len() >= 4 &&
  Branch (1540:9): [True: 0, False: 542]
1541
542
        std::equal(LAST, LAST + 4, stream->get_leg_ptr(),
  Branch (1541:9): [True: 0, False: 0]
1542
0
                   [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); })) {
1543
0
        auto pos = idx_string.find(MINUS);
1544
1545
0
        if (pos != std::string::npos) {
  Branch (1545:13): [True: 0, False: 0]
1546
0
            idx_string = idx_string.substr(pos + 1);
1547
1548
0
            auto result = std::from_chars(idx_string.data(), idx_string.data() + idx_string.size(),
1549
0
                                          index);
1550
0
            if (result.ec != std::errc()) {
  Branch (1550:17): [True: 0, False: 0]
1551
0
                return false;
1552
0
            }
1553
1554
0
        } else if (stream->get_leg_len() > 4) {
  Branch (1554:20): [True: 0, False: 0]
1555
0
            return false;
1556
0
        }
1557
1558
0
        std::unique_ptr<leg_info> leg(new leg_info(nullptr, 0, -index - 1, ARRAY_CODE));
1559
0
        path->add_leg_to_leg_vector(std::move(leg));
1560
1561
0
        return true;
1562
0
    }
1563
1564
542
    auto result = std::from_chars(idx_string.data(), idx_string.data() + idx_string.size(), index);
1565
1566
542
    if (result.ec != std::errc()) {
  Branch (1566:9): [True: 0, False: 542]
1567
0
        return false;
1568
0
    }
1569
1570
542
    std::unique_ptr<leg_info> leg(new leg_info(nullptr, 0, index, ARRAY_CODE));
1571
542
    path->add_leg_to_leg_vector(std::move(leg));
1572
1573
542
    return true;
1574
542
}
1575
1576
308
inline bool JsonbPath::parse_member(Stream* stream, JsonbPath* path) {
1577
308
    if (stream->exhausted()) {
  Branch (1577:9): [True: 0, False: 308]
1578
0
        return false;
1579
0
    }
1580
1581
308
    if (stream->peek() == WILDCARD) {
  Branch (1581:9): [True: 0, False: 308]
1582
0
        stream->set_leg_ptr(const_cast<char*>(stream->position()));
1583
0
        stream->add_leg_len();
1584
0
        stream->skip(1);
1585
0
        std::unique_ptr<leg_info> leg(
1586
0
                new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, MEMBER_CODE));
1587
0
        path->add_leg_to_leg_vector(std::move(leg));
1588
0
        return true;
1589
0
    }
1590
1591
308
    stream->set_leg_ptr(const_cast<char*>(stream->position()));
1592
1593
308
    const char* left_quotation_marks = nullptr;
1594
308
    const char* right_quotation_marks = nullptr;
1595
1596
924
    for (; !stream->exhausted(); stream->skip(1)) {
  Branch (1596:12): [True: 616, False: 308]
1597
616
        if (stream->peek() == ESCAPE) {
  Branch (1597:13): [True: 0, False: 616]
1598
0
            stream->add_leg_len();
1599
0
            stream->skip(1);
1600
0
            stream->add_leg_len();
1601
0
            stream->set_has_escapes(true);
1602
0
            if (stream->exhausted()) {
  Branch (1602:17): [True: 0, False: 0]
1603
0
                return false;
1604
0
            }
1605
0
            continue;
1606
616
        } else if (stream->peek() == DOUBLE_QUOTE) {
  Branch (1606:20): [True: 0, False: 616]
1607
0
            if (left_quotation_marks == nullptr) {
  Branch (1607:17): [True: 0, False: 0]
1608
0
                left_quotation_marks = stream->position();
1609
0
                stream->set_leg_ptr(const_cast<char*>(++left_quotation_marks));
1610
0
                continue;
1611
0
            } else {
1612
0
                right_quotation_marks = stream->position();
1613
0
                stream->skip(1);
1614
0
                break;
1615
0
            }
1616
616
        } else if (stream->peek() == BEGIN_MEMBER || stream->peek() == BEGIN_ARRAY) {
  Branch (1616:20): [True: 0, False: 616]
  Branch (1616:54): [True: 0, False: 616]
1617
0
            if (left_quotation_marks == nullptr) {
  Branch (1617:17): [True: 0, False: 0]
1618
0
                break;
1619
0
            }
1620
0
        }
1621
1622
616
        stream->add_leg_len();
1623
616
    }
1624
1625
308
    if ((left_quotation_marks != nullptr && right_quotation_marks == nullptr) ||
  Branch (1625:10): [True: 0, False: 308]
  Branch (1625:45): [True: 0, False: 0]
1626
308
        stream->get_leg_ptr() == nullptr || stream->get_leg_len() == 0) {
  Branch (1626:9): [True: 0, False: 308]
  Branch (1626:45): [True: 0, False: 308]
1627
0
        return false; //invalid json path
1628
0
    }
1629
1630
308
    if (stream->get_has_escapes()) {
  Branch (1630:9): [True: 0, False: 308]
1631
0
        stream->remove_escapes();
1632
0
    }
1633
1634
308
    std::unique_ptr<leg_info> leg(
1635
308
            new leg_info(stream->get_leg_ptr(), stream->get_leg_len(), 0, MEMBER_CODE));
1636
308
    path->add_leg_to_leg_vector(std::move(leg));
1637
1638
308
    return true;
1639
308
}
1640
1641
#pragma pack(pop)
1642
#if defined(__clang__)
1643
#pragma clang diagnostic pop
1644
#endif
1645
} // namespace doris
1646
1647
#endif // JSONB_JSONBDOCUMENT_H