Coverage Report

Created: 2026-09-29 12:58

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