Coverage Report

Created: 2025-09-15 19:48

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