Coverage Report

Created: 2025-07-23 20:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/util/jsonb_writer.h
Line
Count
Source
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 file defines JsonbWriterT (template) and JsonbWriter.
13
 *
14
 * JsonbWriterT is a template class which implements an JSONB serializer.
15
 * Users call various write functions of JsonbWriterT object to write values
16
 * directly to JSONB packed bytes. All write functions of value or key return
17
 * the number of bytes written to JSONB, or 0 if there is an error. To write an
18
 * object, an array, or a string, you must call writeStart[..] before writing
19
 * values or key, and call writeEnd[..] after finishing at the end.
20
 *
21
 * By default, an JsonbWriterT object creates an output stream buffer.
22
 * Alternatively, you can also pass any output stream object to a writer, as
23
 * long as the stream object implements some basic functions of std::ostream
24
 * (such as JsonbOutStream, see JsonbStream.h).
25
 *
26
 * JsonbWriter specializes JsonbWriterT with JsonbOutStream type (see
27
 * JsonbStream.h). So unless you want to provide own a different output stream
28
 * type, use JsonbParser object.
29
 *
30
 * @author Tian Xia <tianx@fb.com>
31
 * this file is copied from 
32
 * https://github.com/facebook/mysql-5.6/blob/fb-mysql-5.6.35/fbson/FbsonWriter.h
33
 * and modified by Doris
34
 */
35
36
#ifndef JSONB_JSONBWRITER_H
37
#define JSONB_JSONBWRITER_H
38
39
#include <cstdint>
40
#include <limits>
41
#include <stack>
42
#include <string>
43
44
#include "common/exception.h"
45
#include "common/status.h"
46
#include "jsonb_document.h"
47
#include "jsonb_stream.h"
48
#include "runtime/define_primitive_type.h"
49
#include "runtime/primitive_type.h"
50
#include "vec/core/types.h"
51
52
namespace doris {
53
54
using int128_t = __int128;
55
56
template <class OS_TYPE>
57
class JsonbWriterT {
58
    /// TODO: maybe we should not use a template class here
59
    static_assert(std::is_same_v<OS_TYPE, JsonbOutStream>);
60
61
public:
62
3.79k
    JsonbWriterT() : alloc_(true), hasHdr_(false), kvState_(WS_Value), str_pos_(0) {
63
3.79k
        os_ = new OS_TYPE();
64
3.79k
    }
65
66
    explicit JsonbWriterT(OS_TYPE& os)
67
            : os_(&os), alloc_(false), hasHdr_(false), kvState_(WS_Value), str_pos_(0) {}
68
69
3.79k
    ~JsonbWriterT() {
70
3.79k
        if (alloc_) {
71
3.79k
            delete os_;
72
3.79k
        }
73
3.79k
    }
74
75
0
    JsonbWriterT<OS_TYPE>& operator=(JsonbWriterT<OS_TYPE>&& other) {
76
0
        if (this != &other) {
77
0
            if (alloc_) {
78
0
                delete os_;
79
0
            }
80
0
            os_ = other.os_;
81
0
            other.os_ = nullptr;
82
0
            alloc_ = other.alloc_;
83
0
            other.alloc_ = false;
84
0
            hasHdr_ = other.hasHdr_;
85
0
            kvState_ = other.kvState_;
86
0
            str_pos_ = other.str_pos_;
87
0
            first_ = other.first_;
88
0
            stack_ = std::move(other.stack_);
89
0
        }
90
0
        return *this;
91
0
    }
92
93
5.17k
    void reset() {
94
5.17k
        os_->clear();
95
5.17k
        os_->seekp(0);
96
5.17k
        hasHdr_ = false;
97
5.17k
        kvState_ = WS_Value;
98
5.17k
        first_ = true;
99
5.17k
        for (; !stack_.empty(); stack_.pop()) {
100
0
            ;
101
0
        }
102
5.17k
    }
103
104
17
    bool writeKey(const char* key) { return writeKey(key, strlen(key)); }
105
106
    // write a key string (or key id if an external dict is provided)
107
6.48k
    bool writeKey(const char* key, uint8_t len) {
108
6.48k
        if (!stack_.empty() && verifyKeyState()) {
109
6.48k
            os_->put(len);
110
6.48k
            if (len == 0) {
111
                // NOTE: we use sMaxKeyId to represent an empty key
112
250
                JsonbKeyValue::keyid_type idx = JsonbKeyValue::sMaxKeyId;
113
250
                os_->write((char*)&idx, sizeof(JsonbKeyValue::keyid_type));
114
6.23k
            } else {
115
6.23k
                os_->write(key, len);
116
6.23k
            }
117
6.48k
            kvState_ = WS_Key;
118
6.48k
            return true;
119
6.48k
        }
120
121
1
        return false;
122
6.48k
    }
123
124
63
    bool writeValue(const JsonbValue* value) {
125
63
        if (!value) {
126
0
            return writeNull();
127
0
        }
128
129
63
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
130
63
            if (!writeFirstHeader()) {
131
0
                return false;
132
0
            }
133
63
            os_->write((char*)value, value->numPackedBytes());
134
63
            kvState_ = WS_Value;
135
63
            return true;
136
63
        }
137
0
        return false;
138
63
    }
139
140
    // write a key id
141
18.2k
    bool writeKey(JsonbKeyValue::keyid_type idx) {
142
18.2k
        if (!stack_.empty() && verifyKeyState()) {
143
16.8k
            os_->put(0);
144
16.8k
            os_->write((char*)&idx, sizeof(JsonbKeyValue::keyid_type));
145
16.8k
            kvState_ = WS_Key;
146
16.8k
            return true;
147
16.8k
        }
148
149
1.42k
        return false;
150
18.2k
    }
151
152
525k
    bool writeFirstHeader() {
153
525k
        if (first_ && stack_.empty()) {
154
753
            first_ = false;
155
            // if this is a new JSONB, write the header
156
753
            if (!hasHdr_) {
157
753
                writeHeader();
158
753
                return true;
159
753
            } else {
160
0
                return false;
161
0
            }
162
524k
        } else {
163
524k
            return true;
164
524k
        }
165
525k
    }
166
167
14.4k
    bool writeNull() {
168
14.4k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
169
14.4k
            if (!writeFirstHeader()) {
170
0
                return false;
171
0
            }
172
14.4k
            os_->put((JsonbTypeUnder)JsonbType::T_Null);
173
14.4k
            kvState_ = WS_Value;
174
14.4k
            return true;
175
14.4k
        }
176
177
0
        return false;
178
14.4k
    }
179
180
20.7k
    bool writeBool(bool b) {
181
20.7k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
182
20.7k
            if (!writeFirstHeader()) {
183
0
                return false;
184
0
            }
185
20.7k
            if (b) {
186
10.3k
                os_->put((JsonbTypeUnder)JsonbType::T_True);
187
10.3k
            } else {
188
10.3k
                os_->put((JsonbTypeUnder)JsonbType::T_False);
189
10.3k
            }
190
191
20.7k
            kvState_ = WS_Value;
192
20.7k
            return true;
193
20.7k
        }
194
195
0
        return false;
196
20.7k
    }
197
198
    // This function is a helper. It will make use of smallest space to
199
    // write an int
200
2
    bool writeInt(int64_t val) {
201
2
        if (val >= std::numeric_limits<int8_t>::min() &&
202
2
            val <= std::numeric_limits<int8_t>::max()) {
203
1
            return writeInt8((int8_t)val);
204
1
        } else if (val >= std::numeric_limits<int16_t>::min() &&
205
1
                   val <= std::numeric_limits<int16_t>::max()) {
206
1
            return writeInt16((int16_t)val);
207
1
        } else if (val >= std::numeric_limits<int32_t>::min() &&
208
0
                   val <= std::numeric_limits<int32_t>::max()) {
209
0
            return writeInt32((int32_t)val);
210
0
        } else {
211
0
            return writeInt64(val);
212
0
        }
213
2
    }
214
215
48.8k
    bool writeInt8(int8_t v) {
216
48.8k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
217
48.8k
            if (!writeFirstHeader()) {
218
0
                return false;
219
0
            }
220
48.8k
            os_->put((JsonbTypeUnder)JsonbType::T_Int8);
221
48.8k
            os_->put(v);
222
48.8k
            kvState_ = WS_Value;
223
48.8k
            return true;
224
48.8k
        }
225
226
0
        return false;
227
48.8k
    }
228
229
184
    bool writeInt16(int16_t v) {
230
184
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
231
184
            if (!writeFirstHeader()) {
232
0
                return false;
233
0
            }
234
184
            os_->put((JsonbTypeUnder)JsonbType::T_Int16);
235
184
            os_->write((char*)&v, sizeof(int16_t));
236
184
            kvState_ = WS_Value;
237
184
            return true;
238
184
        }
239
240
0
        return false;
241
184
    }
242
243
3.48k
    bool writeInt32(int32_t v) {
244
3.48k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
245
3.48k
            if (!writeFirstHeader()) {
246
0
                return false;
247
0
            }
248
3.48k
            os_->put((JsonbTypeUnder)JsonbType::T_Int32);
249
3.48k
            os_->write((char*)&v, sizeof(int32_t));
250
3.48k
            kvState_ = WS_Value;
251
3.48k
            return true;
252
3.48k
        }
253
254
0
        return false;
255
3.48k
    }
256
257
62.8k
    bool writeInt64(int64_t v) {
258
62.8k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
259
62.8k
            if (!writeFirstHeader()) {
260
0
                return false;
261
0
            }
262
62.8k
            os_->put((JsonbTypeUnder)JsonbType::T_Int64);
263
62.8k
            os_->write((char*)&v, sizeof(int64_t));
264
62.8k
            kvState_ = WS_Value;
265
62.8k
            return true;
266
62.8k
        }
267
268
0
        return false;
269
62.8k
    }
270
271
4.17k
    bool writeInt128(int128_t v) {
272
4.17k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
273
4.17k
            if (!writeFirstHeader()) {
274
0
                return false;
275
0
            }
276
4.17k
            os_->put((JsonbTypeUnder)JsonbType::T_Int128);
277
4.17k
            os_->write((char*)&v, sizeof(int128_t));
278
4.17k
            kvState_ = WS_Value;
279
4.17k
            return true;
280
4.17k
        }
281
282
0
        return false;
283
4.17k
    }
284
285
115k
    bool writeDouble(double v) {
286
115k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
287
115k
            if (!writeFirstHeader()) {
288
0
                return false;
289
0
            }
290
115k
            os_->put((JsonbTypeUnder)JsonbType::T_Double);
291
115k
            os_->write((char*)&v, sizeof(double));
292
115k
            kvState_ = WS_Value;
293
115k
            return true;
294
115k
        }
295
296
0
        return false;
297
115k
    }
298
299
19
    bool writeFloat(float v) {
300
19
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
301
19
            if (!writeFirstHeader()) {
302
0
                return false;
303
0
            }
304
19
            os_->put((JsonbTypeUnder)JsonbType::T_Float);
305
19
            os_->write((char*)&v, sizeof(float));
306
19
            kvState_ = WS_Value;
307
19
            return true;
308
19
        }
309
310
0
        return false;
311
19
    }
312
313
    template <JsonbDecimalType T>
314
9
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
315
9
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
316
9
            if (!writeFirstHeader()) {
317
0
                return false;
318
0
            }
319
320
9
            if constexpr (std::same_as<T, vectorized::Decimal256>) {
321
2
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal256);
322
3
            } else if constexpr (std::same_as<T, vectorized::Decimal128V3>) {
323
3
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal128);
324
3
            } else if constexpr (std::same_as<T, vectorized::Decimal64>) {
325
2
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal64);
326
2
            } else {
327
2
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal32);
328
2
            }
329
330
9
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
331
9
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
332
9
            os_->write((char*)(&(v.value)), sizeof(v.value));
333
9
            kvState_ = WS_Value;
334
9
            return true;
335
9
        }
336
337
0
        return false;
338
9
    }
_ZN5doris12JsonbWriterTINS_14JsonbOutStreamEE12writeDecimalITk16JsonbDecimalTypeNS_10vectorized7DecimalIiEEEEbRKT_jj
Line
Count
Source
314
2
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
315
2
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
316
2
            if (!writeFirstHeader()) {
317
0
                return false;
318
0
            }
319
320
            if constexpr (std::same_as<T, vectorized::Decimal256>) {
321
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal256);
322
            } else if constexpr (std::same_as<T, vectorized::Decimal128V3>) {
323
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal128);
324
            } else if constexpr (std::same_as<T, vectorized::Decimal64>) {
325
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal64);
326
2
            } else {
327
2
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal32);
328
2
            }
329
330
2
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
331
2
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
332
2
            os_->write((char*)(&(v.value)), sizeof(v.value));
333
2
            kvState_ = WS_Value;
334
2
            return true;
335
2
        }
336
337
0
        return false;
338
2
    }
_ZN5doris12JsonbWriterTINS_14JsonbOutStreamEE12writeDecimalITk16JsonbDecimalTypeNS_10vectorized7DecimalIlEEEEbRKT_jj
Line
Count
Source
314
2
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
315
2
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
316
2
            if (!writeFirstHeader()) {
317
0
                return false;
318
0
            }
319
320
            if constexpr (std::same_as<T, vectorized::Decimal256>) {
321
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal256);
322
            } else if constexpr (std::same_as<T, vectorized::Decimal128V3>) {
323
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal128);
324
2
            } else if constexpr (std::same_as<T, vectorized::Decimal64>) {
325
2
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal64);
326
            } else {
327
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal32);
328
            }
329
330
2
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
331
2
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
332
2
            os_->write((char*)(&(v.value)), sizeof(v.value));
333
2
            kvState_ = WS_Value;
334
2
            return true;
335
2
        }
336
337
0
        return false;
338
2
    }
_ZN5doris12JsonbWriterTINS_14JsonbOutStreamEE12writeDecimalITk16JsonbDecimalTypeNS_10vectorized12Decimal128V3EEEbRKT_jj
Line
Count
Source
314
3
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
315
3
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
316
3
            if (!writeFirstHeader()) {
317
0
                return false;
318
0
            }
319
320
            if constexpr (std::same_as<T, vectorized::Decimal256>) {
321
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal256);
322
3
            } else if constexpr (std::same_as<T, vectorized::Decimal128V3>) {
323
3
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal128);
324
            } else if constexpr (std::same_as<T, vectorized::Decimal64>) {
325
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal64);
326
            } else {
327
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal32);
328
            }
329
330
3
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
331
3
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
332
3
            os_->write((char*)(&(v.value)), sizeof(v.value));
333
3
            kvState_ = WS_Value;
334
3
            return true;
335
3
        }
336
337
0
        return false;
338
3
    }
_ZN5doris12JsonbWriterTINS_14JsonbOutStreamEE12writeDecimalITk16JsonbDecimalTypeNS_10vectorized7DecimalIN4wide7integerILm256EiEEEEEEbRKT_jj
Line
Count
Source
314
2
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
315
2
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
316
2
            if (!writeFirstHeader()) {
317
0
                return false;
318
0
            }
319
320
2
            if constexpr (std::same_as<T, vectorized::Decimal256>) {
321
2
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal256);
322
            } else if constexpr (std::same_as<T, vectorized::Decimal128V3>) {
323
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal128);
324
            } else if constexpr (std::same_as<T, vectorized::Decimal64>) {
325
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal64);
326
            } else {
327
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal32);
328
            }
329
330
2
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
331
2
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
332
2
            os_->write((char*)(&(v.value)), sizeof(v.value));
333
2
            kvState_ = WS_Value;
334
2
            return true;
335
2
        }
336
337
0
        return false;
338
2
    }
339
340
    // must call writeStartString before writing a string val
341
250k
    bool writeStartString() {
342
250k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
343
250k
            if (!writeFirstHeader()) return 0;
344
250k
            os_->put((JsonbTypeUnder)JsonbType::T_String);
345
250k
            str_pos_ = os_->tellp();
346
347
            // fill the size bytes with 0 for now
348
250k
            uint32_t size = 0;
349
250k
            os_->write((char*)&size, sizeof(uint32_t));
350
351
250k
            kvState_ = WS_String;
352
250k
            return true;
353
250k
        }
354
355
0
        return false;
356
250k
    }
357
358
    // finish writing a string val
359
250k
    bool writeEndString() {
360
250k
        if (kvState_ == WS_String) {
361
250k
            std::streampos cur_pos = os_->tellp();
362
250k
            int32_t size = (int32_t)(cur_pos - str_pos_ - sizeof(uint32_t));
363
250k
            assert(size >= 0);
364
365
250k
            os_->seekp(str_pos_);
366
250k
            os_->write((char*)&size, sizeof(uint32_t));
367
250k
            os_->seekp(cur_pos);
368
369
250k
            kvState_ = WS_Value;
370
250k
            return true;
371
250k
        }
372
373
0
        return false;
374
250k
    }
375
376
    // TODO: here changed length to uint64_t, as some api also need changed, But the thirdparty api is uint_32t
377
    // need consider a better way to handle case.
378
239k
    bool writeString(const char* str, uint64_t len) {
379
239k
        if (kvState_ == WS_String) {
380
239k
            os_->write(str, len);
381
239k
            return true;
382
239k
        }
383
384
5
        return false;
385
239k
    }
386
387
19
    bool writeString(const std::string& str) { return writeString(str.c_str(), str.size()); }
388
    bool writeString(char ch) {
389
        if (kvState_ == WS_String) {
390
            os_->put(ch);
391
            return true;
392
        }
393
394
        return false;
395
    }
396
397
    // must call writeStartBinary before writing a binary val
398
4.36k
    bool writeStartBinary() {
399
4.36k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
400
4.36k
            if (!writeFirstHeader()) return 0;
401
4.36k
            os_->put((JsonbTypeUnder)JsonbType::T_Binary);
402
4.36k
            str_pos_ = os_->tellp();
403
404
            // fill the size bytes with 0 for now
405
4.36k
            uint32_t size = 0;
406
4.36k
            os_->write((char*)&size, sizeof(uint32_t));
407
408
4.36k
            kvState_ = WS_Binary;
409
4.36k
            return true;
410
4.36k
        }
411
412
0
        return false;
413
4.36k
    }
414
415
    // finish writing a binary val
416
4.36k
    bool writeEndBinary() {
417
4.36k
        if (kvState_ == WS_Binary) {
418
4.36k
            std::streampos cur_pos = os_->tellp();
419
4.36k
            int32_t size = (int32_t)(cur_pos - str_pos_ - sizeof(uint32_t));
420
4.36k
            assert(size >= 0);
421
422
4.36k
            os_->seekp(str_pos_);
423
4.36k
            os_->write((char*)&size, sizeof(uint32_t));
424
4.36k
            os_->seekp(cur_pos);
425
426
4.36k
            kvState_ = WS_Value;
427
4.36k
            return true;
428
4.36k
        }
429
430
0
        return false;
431
4.36k
    }
432
433
4.36k
    bool writeBinary(const char* bin, uint64_t len) {
434
4.36k
        if (kvState_ == WS_Binary) {
435
4.36k
            os_->write(bin, len);
436
4.36k
            return true;
437
4.36k
        }
438
439
0
        return false;
440
4.36k
    }
441
442
    // must call writeStartObject before writing an object val
443
4.16k
    bool writeStartObject() {
444
4.16k
        if (stack_.empty() || verifyValueState()) {
445
4.16k
            if (stack_.empty()) {
446
                // if this is a new JSONB, write the header
447
1.49k
                if (!hasHdr_) {
448
1.49k
                    writeHeader();
449
1.49k
                } else
450
0
                    return false;
451
1.49k
            }
452
453
            // check if the object exceeds the maximum nesting level
454
4.16k
            if (stack_.size() >= MaxNestingLevel) return false;
455
456
4.16k
            os_->put((JsonbTypeUnder)JsonbType::T_Object);
457
            // save the size position
458
4.16k
            stack_.push(WriteInfo({WS_Object, os_->tellp()}));
459
460
            // fill the size bytes with 0 for now
461
4.16k
            uint32_t size = 0;
462
4.16k
            os_->write((char*)&size, sizeof(uint32_t));
463
464
4.16k
            kvState_ = WS_Value;
465
4.16k
            return true;
466
4.16k
        }
467
468
0
        return false;
469
4.16k
    }
470
471
    // finish writing an object val
472
3.80k
    bool writeEndObject() {
473
3.80k
        if (!stack_.empty() && stack_.top().state == WS_Object && kvState_ == WS_Value) {
474
3.80k
            WriteInfo& ci = stack_.top();
475
3.80k
            std::streampos cur_pos = os_->tellp();
476
3.80k
            auto size = (int32_t)(cur_pos - ci.sz_pos - sizeof(uint32_t));
477
3.80k
            assert(size >= 0);
478
479
3.80k
            os_->seekp(ci.sz_pos);
480
3.80k
            os_->write((char*)&size, sizeof(uint32_t));
481
3.80k
            os_->seekp(cur_pos);
482
3.80k
            stack_.pop();
483
484
3.80k
            return true;
485
3.80k
        }
486
487
1
        return false;
488
3.80k
    }
489
490
    // must call writeStartArray before writing an array val
491
51.8k
    bool writeStartArray() {
492
51.8k
        if (stack_.empty() || verifyValueState()) {
493
51.8k
            if (stack_.empty()) {
494
                // if this is a new JSONB, write the header
495
1.56k
                if (!hasHdr_) {
496
1.56k
                    writeHeader();
497
1.56k
                } else {
498
0
                    return false;
499
0
                }
500
1.56k
            }
501
502
            // check if the array exceeds the maximum nesting level
503
51.8k
            if (stack_.size() >= MaxNestingLevel) {
504
0
                return false;
505
0
            }
506
507
51.8k
            os_->put((JsonbTypeUnder)JsonbType::T_Array);
508
            // save the size position
509
51.8k
            stack_.push(WriteInfo({WS_Array, os_->tellp()}));
510
511
            // fill the size bytes with 0 for now
512
51.8k
            uint32_t size = 0;
513
51.8k
            os_->write((char*)&size, sizeof(uint32_t));
514
515
51.8k
            kvState_ = WS_Value;
516
51.8k
            return true;
517
51.8k
        }
518
519
0
        return false;
520
51.8k
    }
521
522
    // finish writing an array val
523
51.6k
    bool writeEndArray() {
524
51.6k
        if (!stack_.empty() && stack_.top().state == WS_Array && kvState_ == WS_Value) {
525
51.6k
            WriteInfo& ci = stack_.top();
526
51.6k
            std::streampos cur_pos = os_->tellp();
527
51.6k
            auto size = (int32_t)(cur_pos - ci.sz_pos - sizeof(uint32_t));
528
51.6k
            assert(size >= 0);
529
530
51.6k
            os_->seekp(ci.sz_pos);
531
51.6k
            os_->write((char*)&size, sizeof(uint32_t));
532
51.6k
            os_->seekp(cur_pos);
533
51.6k
            stack_.pop();
534
535
51.6k
            return true;
536
51.6k
        }
537
538
0
        return false;
539
51.6k
    }
540
541
7.05k
    OS_TYPE* getOutput() { return os_; }
542
1
    JsonbDocument* getDocument() {
543
1
        JsonbDocument* doc = nullptr;
544
1
        THROW_IF_ERROR(JsonbDocument::checkAndCreateDocument(getOutput()->getBuffer(),
545
1
                                                             getOutput()->getSize(), &doc));
546
1
        return doc;
547
1
    }
548
549
    JsonbValue* getValue() {
550
        return JsonbDocument::createValue(getOutput()->getBuffer(), getOutput()->getSize());
551
    }
552
553
    bool writeEnd() {
554
        while (!stack_.empty()) {
555
            bool ok = false;
556
            switch (stack_.top().state) {
557
            case WS_Array:
558
                ok = writeEndArray();
559
                break;
560
            case WS_Object:
561
                ok = writeEndObject();
562
                break;
563
            case WS_String:
564
                ok = writeEndString();
565
                break;
566
            case WS_Binary:
567
                ok = writeEndBinary();
568
                break;
569
            default:
570
                ok = false;
571
                break;
572
            }
573
            if (!ok) {
574
                return false;
575
            }
576
        }
577
        return true;
578
    }
579
580
private:
581
    // verify we are in the right state before writing a value
582
577k
    bool verifyValueState() {
583
577k
        assert(!stack_.empty());
584
        // The document can only be an Object or an Array which follows
585
        // the standard.
586
577k
        return (stack_.top().state == WS_Object && kvState_ == WS_Key) ||
587
577k
               (stack_.top().state == WS_Array && kvState_ == WS_Value);
588
577k
    }
589
590
    // verify we are in the right state before writing a key
591
24.7k
    bool verifyKeyState() {
592
24.7k
        assert(!stack_.empty());
593
24.7k
        return stack_.top().state == WS_Object && kvState_ == WS_Value;
594
24.7k
    }
595
596
3.81k
    void writeHeader() {
597
3.81k
        os_->put(JSONB_VER);
598
3.81k
        hasHdr_ = true;
599
3.81k
    }
600
601
    enum WriteState {
602
        WS_NONE,
603
        WS_Array,
604
        WS_Object,
605
        WS_Key,
606
        WS_Value,
607
        WS_String,
608
        WS_Binary,
609
    };
610
611
    struct WriteInfo {
612
        WriteState state;
613
        std::streampos sz_pos;
614
    };
615
616
    OS_TYPE* os_ = nullptr;
617
    bool alloc_;
618
    bool hasHdr_;
619
    WriteState kvState_; // key or value state
620
    std::streampos str_pos_;
621
    std::stack<WriteInfo> stack_;
622
    bool first_ = true;
623
};
624
625
using JsonbWriter = JsonbWriterT<JsonbOutStream>;
626
627
} // namespace doris
628
629
#endif // JSONB_JSONBWRITER_H