Coverage Report

Created: 2026-05-20 11:46

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
3.37M
    JsonbWriterT() : alloc_(true), hasHdr_(false), kvState_(WS_Value), str_pos_(0) {
62
3.37M
        os_ = new OS_TYPE();
63
3.37M
    }
64
65
    explicit JsonbWriterT(OS_TYPE& os)
66
            : os_(&os), alloc_(false), hasHdr_(false), kvState_(WS_Value), str_pos_(0) {}
67
68
3.36M
    ~JsonbWriterT() {
69
3.36M
        if (alloc_) {
70
3.36M
            delete os_;
71
3.36M
        }
72
3.36M
    }
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
329k
    void reset() {
93
329k
        os_->clear();
94
329k
        os_->seekp(0);
95
329k
        hasHdr_ = false;
96
329k
        kvState_ = WS_Value;
97
329k
        first_ = true;
98
329k
        for (; !stack_.empty(); stack_.pop()) {
99
9
            ;
100
9
        }
101
329k
    }
102
103
    // write a key string (or key id if an external dict is provided)
104
809k
    bool writeKey(const char* key, uint8_t len) {
105
809k
        if (!stack_.empty() && verifyKeyState()) {
106
809k
            os_->put(len);
107
809k
            if (len == 0) {
108
                // NOTE: we use sMaxKeyId to represent an empty key
109
456
                JsonbKeyValue::keyid_type idx = JsonbKeyValue::sMaxKeyId;
110
456
                os_->write((char*)&idx, sizeof(JsonbKeyValue::keyid_type));
111
809k
            } else {
112
809k
                os_->write(key, len);
113
809k
            }
114
809k
            kvState_ = WS_Key;
115
809k
            return true;
116
809k
        }
117
118
18.4E
        return false;
119
809k
    }
120
121
27.3k
    bool writeValue(const JsonbValue* value) {
122
27.3k
        if (!value) {
123
11
            return writeNull();
124
11
        }
125
126
27.3k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
127
27.3k
            if (!writeFirstHeader()) {
128
0
                return false;
129
0
            }
130
27.3k
            os_->write((char*)value, value->numPackedBytes());
131
27.3k
            kvState_ = WS_Value;
132
27.3k
            return true;
133
27.3k
        }
134
0
        return false;
135
27.3k
    }
136
137
117k
    bool writeValueSimple(const JsonbValue* value) {
138
18.4E
        DCHECK(value) << "value should not be nullptr";
139
18.4E
        DCHECK(first_) << "only called at the beginning";
140
18.4E
        DCHECK(stack_.empty()) << "only called at the beginning";
141
18.4E
        DCHECK(!hasHdr_) << "only called at the beginning";
142
117k
        first_ = false;
143
117k
        writeHeader();
144
117k
        os_->write((char*)value, value->numPackedBytes());
145
117k
        kvState_ = WS_Value;
146
117k
        return true;
147
117k
    }
148
149
    // write a key id
150
42.8M
    bool writeKey(JsonbKeyValue::keyid_type idx) {
151
43.2M
        if (!stack_.empty() && verifyKeyState()) {
152
23.6M
            os_->put(0);
153
23.6M
            os_->write((char*)&idx, sizeof(JsonbKeyValue::keyid_type));
154
23.6M
            kvState_ = WS_Key;
155
23.6M
            return true;
156
23.6M
        }
157
158
19.2M
        return false;
159
42.8M
    }
160
161
27.0M
    bool writeFirstHeader() {
162
27.0M
        if (first_ && stack_.empty()) {
163
1.18M
            first_ = false;
164
            // if this is a new JSONB, write the header
165
1.18M
            if (!hasHdr_) {
166
1.18M
                writeHeader();
167
1.18M
                return true;
168
1.18M
            } else {
169
0
                return false;
170
0
            }
171
25.8M
        } else {
172
25.8M
            return true;
173
25.8M
        }
174
27.0M
    }
175
176
37.0k
    bool writeNull() {
177
37.0k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
178
37.0k
            if (!writeFirstHeader()) {
179
0
                return false;
180
0
            }
181
37.0k
            os_->put((JsonbTypeUnder)JsonbType::T_Null);
182
37.0k
            kvState_ = WS_Value;
183
37.0k
            return true;
184
37.0k
        }
185
186
18.4E
        return false;
187
37.0k
    }
188
189
167k
    bool writeBool(bool b) {
190
167k
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
191
167k
            if (!writeFirstHeader()) {
192
0
                return false;
193
0
            }
194
167k
            if (b) {
195
117k
                os_->put((JsonbTypeUnder)JsonbType::T_True);
196
117k
            } else {
197
49.8k
                os_->put((JsonbTypeUnder)JsonbType::T_False);
198
49.8k
            }
199
200
167k
            kvState_ = WS_Value;
201
167k
            return true;
202
167k
        }
203
204
1
        return false;
205
167k
    }
206
207
    // This function is a helper. It will make use of smallest space to
208
    // write an int
209
    bool writeInt(int64_t val) {
210
        if (val >= std::numeric_limits<int8_t>::min() &&
211
            val <= std::numeric_limits<int8_t>::max()) {
212
            return writeInt8((int8_t)val);
213
        } else if (val >= std::numeric_limits<int16_t>::min() &&
214
                   val <= std::numeric_limits<int16_t>::max()) {
215
            return writeInt16((int16_t)val);
216
        } else if (val >= std::numeric_limits<int32_t>::min() &&
217
                   val <= std::numeric_limits<int32_t>::max()) {
218
            return writeInt32((int32_t)val);
219
        } else {
220
            return writeInt64(val);
221
        }
222
    }
223
224
3.24M
    bool writeInt8(int8_t v) {
225
3.25M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
226
3.25M
            if (!writeFirstHeader()) {
227
0
                return false;
228
0
            }
229
3.25M
            os_->put((JsonbTypeUnder)JsonbType::T_Int8);
230
3.25M
            os_->put(v);
231
3.25M
            kvState_ = WS_Value;
232
3.25M
            return true;
233
3.25M
        }
234
235
18.4E
        return false;
236
3.24M
    }
237
238
1.24M
    bool writeInt16(int16_t v) {
239
1.24M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
240
1.24M
            if (!writeFirstHeader()) {
241
0
                return false;
242
0
            }
243
1.24M
            os_->put((JsonbTypeUnder)JsonbType::T_Int16);
244
1.24M
            os_->write((char*)&v, sizeof(int16_t));
245
1.24M
            kvState_ = WS_Value;
246
1.24M
            return true;
247
1.24M
        }
248
249
18.4E
        return false;
250
1.24M
    }
251
252
2.80M
    bool writeInt32(int32_t v) {
253
2.80M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
254
2.80M
            if (!writeFirstHeader()) {
255
0
                return false;
256
0
            }
257
2.80M
            os_->put((JsonbTypeUnder)JsonbType::T_Int32);
258
2.80M
            os_->write((char*)&v, sizeof(int32_t));
259
2.80M
            kvState_ = WS_Value;
260
2.80M
            return true;
261
2.80M
        }
262
263
18.4E
        return false;
264
2.80M
    }
265
266
7.60M
    bool writeInt64(int64_t v) {
267
7.63M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
268
7.63M
            if (!writeFirstHeader()) {
269
0
                return false;
270
0
            }
271
7.63M
            os_->put((JsonbTypeUnder)JsonbType::T_Int64);
272
7.63M
            os_->write((char*)&v, sizeof(int64_t));
273
7.63M
            kvState_ = WS_Value;
274
7.63M
            return true;
275
7.63M
        }
276
277
18.4E
        return false;
278
7.60M
    }
279
280
4.30M
    bool writeInt128(int128_t v) {
281
4.30M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
282
4.30M
            if (!writeFirstHeader()) {
283
0
                return false;
284
0
            }
285
4.30M
            os_->put((JsonbTypeUnder)JsonbType::T_Int128);
286
4.30M
            os_->write((char*)&v, sizeof(int128_t));
287
4.30M
            kvState_ = WS_Value;
288
4.30M
            return true;
289
4.30M
        }
290
291
18.4E
        return false;
292
4.30M
    }
293
294
1.49M
    bool writeDouble(double v) {
295
1.49M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
296
1.49M
            if (!writeFirstHeader()) {
297
0
                return false;
298
0
            }
299
1.49M
            os_->put((JsonbTypeUnder)JsonbType::T_Double);
300
1.49M
            os_->write((char*)&v, sizeof(double));
301
1.49M
            kvState_ = WS_Value;
302
1.49M
            return true;
303
1.49M
        }
304
305
18.4E
        return false;
306
1.49M
    }
307
308
1.19M
    bool writeFloat(float v) {
309
1.19M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
310
1.19M
            if (!writeFirstHeader()) {
311
0
                return false;
312
0
            }
313
1.19M
            os_->put((JsonbTypeUnder)JsonbType::T_Float);
314
1.19M
            os_->write((char*)&v, sizeof(float));
315
1.19M
            kvState_ = WS_Value;
316
1.19M
            return true;
317
1.19M
        }
318
319
18.4E
        return false;
320
1.19M
    }
321
322
    template <JsonbDecimalType T>
323
114
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
324
114
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
325
114
            if (!writeFirstHeader()) {
326
0
                return false;
327
0
            }
328
329
114
            if constexpr (std::same_as<T, Decimal256>) {
330
6
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal256);
331
31
            } else if constexpr (std::same_as<T, Decimal128V3>) {
332
31
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal128);
333
39
            } else if constexpr (std::same_as<T, Decimal64>) {
334
39
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal64);
335
39
            } else {
336
38
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal32);
337
38
            }
338
339
114
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
340
114
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
341
114
            os_->write((char*)(&(v.value)), sizeof(v.value));
342
114
            kvState_ = WS_Value;
343
114
            return true;
344
114
        }
345
346
0
        return false;
347
114
    }
_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
39
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
324
39
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
325
39
            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
39
            } else if constexpr (std::same_as<T, Decimal64>) {
334
39
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal64);
335
            } else {
336
                os_->put((JsonbTypeUnder)JsonbType::T_Decimal32);
337
            }
338
339
39
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
340
39
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
341
39
            os_->write((char*)(&(v.value)), sizeof(v.value));
342
39
            kvState_ = WS_Value;
343
39
            return true;
344
39
        }
345
346
0
        return false;
347
39
    }
_ZN5doris12JsonbWriterTINS_14JsonbOutStreamEE12writeDecimalITk16JsonbDecimalTypeNS_12Decimal128V3EEEbRKT_jj
Line
Count
Source
323
31
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
324
31
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
325
31
            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
31
            } else if constexpr (std::same_as<T, Decimal128V3>) {
332
31
                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
31
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
340
31
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
341
31
            os_->write((char*)(&(v.value)), sizeof(v.value));
342
31
            kvState_ = WS_Value;
343
31
            return true;
344
31
        }
345
346
0
        return false;
347
31
    }
_ZN5doris12JsonbWriterTINS_14JsonbOutStreamEE12writeDecimalITk16JsonbDecimalTypeNS_7DecimalIN4wide7integerILm256EiEEEEEEbRKT_jj
Line
Count
Source
323
6
    bool writeDecimal(const T& v, const uint32_t precision, const uint32_t scale) {
324
6
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
325
6
            if (!writeFirstHeader()) {
326
0
                return false;
327
0
            }
328
329
6
            if constexpr (std::same_as<T, Decimal256>) {
330
6
                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
6
            os_->write(reinterpret_cast<const char*>(&precision), sizeof(uint32_t));
340
6
            os_->write(reinterpret_cast<const char*>(&scale), sizeof(uint32_t));
341
6
            os_->write((char*)(&(v.value)), sizeof(v.value));
342
6
            kvState_ = WS_Value;
343
6
            return true;
344
6
        }
345
346
0
        return false;
347
6
    }
348
349
    // must call writeStartString before writing a string val
350
1.66M
    bool writeStartString() {
351
1.66M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
352
1.66M
            if (!writeFirstHeader()) return 0;
353
1.66M
            os_->put((JsonbTypeUnder)JsonbType::T_String);
354
1.66M
            str_pos_ = os_->tellp();
355
356
            // fill the size bytes with 0 for now
357
1.66M
            uint32_t size = 0;
358
1.66M
            os_->write((char*)&size, sizeof(uint32_t));
359
360
1.66M
            kvState_ = WS_String;
361
1.66M
            return true;
362
1.66M
        }
363
364
18.4E
        return false;
365
1.66M
    }
366
367
    // finish writing a string val
368
1.66M
    bool writeEndString() {
369
1.66M
        if (kvState_ == WS_String) {
370
1.66M
            std::streampos cur_pos = os_->tellp();
371
1.66M
            int32_t size = (int32_t)(cur_pos - str_pos_ - sizeof(uint32_t));
372
1.66M
            assert(size >= 0);
373
374
1.66M
            os_->seekp(str_pos_);
375
1.66M
            os_->write((char*)&size, sizeof(uint32_t));
376
1.66M
            os_->seekp(cur_pos);
377
378
1.66M
            kvState_ = WS_Value;
379
1.66M
            return true;
380
1.66M
        }
381
382
18.4E
        return false;
383
1.66M
    }
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
1.65M
    bool writeString(const char* str, uint64_t len) {
388
1.65M
        if (kvState_ == WS_String) {
389
1.65M
            os_->write(str, len);
390
1.65M
            return true;
391
1.65M
        }
392
393
1
        return false;
394
1.65M
    }
395
396
827k
    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
3.79M
    bool writeStartBinary() {
408
3.80M
        if ((first_ && stack_.empty()) || (!stack_.empty() && verifyValueState())) {
409
3.80M
            if (!writeFirstHeader()) return 0;
410
3.80M
            os_->put((JsonbTypeUnder)JsonbType::T_Binary);
411
3.80M
            str_pos_ = os_->tellp();
412
413
            // fill the size bytes with 0 for now
414
3.80M
            uint32_t size = 0;
415
3.80M
            os_->write((char*)&size, sizeof(uint32_t));
416
417
3.80M
            kvState_ = WS_Binary;
418
3.80M
            return true;
419
3.80M
        }
420
421
18.4E
        return false;
422
3.79M
    }
423
424
    // finish writing a binary val
425
3.80M
    bool writeEndBinary() {
426
3.80M
        if (kvState_ == WS_Binary) {
427
3.80M
            std::streampos cur_pos = os_->tellp();
428
3.80M
            int32_t size = (int32_t)(cur_pos - str_pos_ - sizeof(uint32_t));
429
3.80M
            assert(size >= 0);
430
431
3.80M
            os_->seekp(str_pos_);
432
3.80M
            os_->write((char*)&size, sizeof(uint32_t));
433
3.80M
            os_->seekp(cur_pos);
434
435
3.80M
            kvState_ = WS_Value;
436
3.80M
            return true;
437
3.80M
        }
438
439
18.4E
        return false;
440
3.80M
    }
441
442
3.81M
    bool writeBinary(const char* bin, uint64_t len) {
443
3.81M
        if (kvState_ == WS_Binary) {
444
3.81M
            os_->write(bin, len);
445
3.81M
            return true;
446
3.81M
        }
447
448
18.4E
        return false;
449
3.81M
    }
450
451
    // must call writeStartObject before writing an object val
452
2.13M
    bool writeStartObject() {
453
2.13M
        if (stack_.empty() || verifyValueState()) {
454
2.13M
            if (stack_.empty()) {
455
                // if this is a new JSONB, write the header
456
1.95M
                if (!hasHdr_) {
457
1.95M
                    writeHeader();
458
1.95M
                } else
459
18.4E
                    return false;
460
1.95M
            }
461
462
            // check if the object exceeds the maximum nesting level
463
2.13M
            if (stack_.size() >= MaxNestingLevel) return false;
464
465
2.13M
            os_->put((JsonbTypeUnder)JsonbType::T_Object);
466
            // save the size position
467
2.13M
            stack_.push(WriteInfo({WS_Object, os_->tellp()}));
468
469
            // fill the size bytes with 0 for now
470
2.13M
            uint32_t size = 0;
471
2.13M
            os_->write((char*)&size, sizeof(uint32_t));
472
473
2.13M
            kvState_ = WS_Value;
474
2.13M
            return true;
475
2.13M
        }
476
477
18.4E
        return false;
478
2.13M
    }
479
480
    // finish writing an object val
481
2.13M
    bool writeEndObject() {
482
2.13M
        if (!stack_.empty() && stack_.top().state == WS_Object && kvState_ == WS_Value) {
483
2.13M
            WriteInfo& ci = stack_.top();
484
2.13M
            std::streampos cur_pos = os_->tellp();
485
2.13M
            auto size = (int32_t)(cur_pos - ci.sz_pos - sizeof(uint32_t));
486
2.13M
            assert(size >= 0);
487
488
2.13M
            os_->seekp(ci.sz_pos);
489
2.13M
            os_->write((char*)&size, sizeof(uint32_t));
490
2.13M
            os_->seekp(cur_pos);
491
2.13M
            stack_.pop();
492
493
2.13M
            return true;
494
2.13M
        }
495
496
18.4E
        return false;
497
2.13M
    }
498
499
    // must call writeStartArray before writing an array val
500
472k
    bool writeStartArray() {
501
472k
        if (stack_.empty() || verifyValueState()) {
502
472k
            if (stack_.empty()) {
503
                // if this is a new JSONB, write the header
504
235k
                if (!hasHdr_) {
505
235k
                    writeHeader();
506
18.4E
                } else {
507
18.4E
                    return false;
508
18.4E
                }
509
235k
            }
510
511
            // check if the array exceeds the maximum nesting level
512
472k
            if (stack_.size() >= MaxNestingLevel) {
513
0
                return false;
514
0
            }
515
516
472k
            os_->put((JsonbTypeUnder)JsonbType::T_Array);
517
            // save the size position
518
472k
            stack_.push(WriteInfo({WS_Array, os_->tellp()}));
519
520
            // fill the size bytes with 0 for now
521
472k
            uint32_t size = 0;
522
472k
            os_->write((char*)&size, sizeof(uint32_t));
523
524
472k
            kvState_ = WS_Value;
525
472k
            return true;
526
472k
        }
527
528
18.4E
        return false;
529
472k
    }
530
531
    // finish writing an array val
532
472k
    bool writeEndArray() {
533
472k
        if (!stack_.empty() && stack_.top().state == WS_Array && kvState_ == WS_Value) {
534
472k
            WriteInfo& ci = stack_.top();
535
472k
            std::streampos cur_pos = os_->tellp();
536
472k
            auto size = (int32_t)(cur_pos - ci.sz_pos - sizeof(uint32_t));
537
472k
            assert(size >= 0);
538
539
472k
            os_->seekp(ci.sz_pos);
540
472k
            os_->write((char*)&size, sizeof(uint32_t));
541
472k
            os_->seekp(cur_pos);
542
472k
            stack_.pop();
543
544
472k
            return true;
545
472k
        }
546
547
18.4E
        return false;
548
472k
    }
549
550
6.97M
    OS_TYPE* getOutput() { return os_; }
551
552
#ifdef BE_TEST
553
    const JsonbDocument* getDocument() {
554
        const JsonbDocument* doc = nullptr;
555
        THROW_IF_ERROR(JsonbDocument::checkAndCreateDocument(getOutput()->getBuffer(),
556
                                                             getOutput()->getSize(), &doc));
557
        return doc;
558
    }
559
560
    const JsonbValue* getValue() {
561
        return JsonbDocument::createValue(getOutput()->getBuffer(), getOutput()->getSize());
562
    }
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
25.8M
    bool verifyValueState() {
595
25.8M
        assert(!stack_.empty());
596
        // The document can only be an Object or an Array which follows
597
        // the standard.
598
25.7M
        return (stack_.top().state == WS_Object && kvState_ == WS_Key) ||
599
25.7M
               (stack_.top().state == WS_Array && kvState_ == WS_Value);
600
25.8M
    }
601
602
    // verify we are in the right state before writing a key
603
43.9M
    bool verifyKeyState() {
604
43.9M
        assert(!stack_.empty());
605
45.7M
        return stack_.top().state == WS_Object && kvState_ == WS_Value;
606
43.9M
    }
607
608
3.48M
    void writeHeader() {
609
3.48M
        os_->put(JSONB_VER);
610
3.48M
        hasHdr_ = true;
611
3.48M
    }
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