Coverage Report

Created: 2026-03-19 11:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/jsonb_stream.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 header file defines JsonbInBuffer and JsonbOutStream classes.
13
 *
14
 * ** Input Buffer **
15
 * JsonbInBuffer is a customer input buffer to wrap raw character buffer. Its
16
 * object instances are used to create std::istream objects interally.
17
 *
18
 * ** Output Stream **
19
 * JsonbOutStream is a custom output stream classes, to contain the JSONB
20
 * serialized binary. The class is conveniently used to specialize templates of
21
 * JsonbParser and JsonbWriter.
22
 *
23
 * @author Tian Xia <tianx@fb.com>
24
 * this file is copied from 
25
 * https://github.com/facebook/mysql-5.6/blob/fb-mysql-5.6.35/fbson/FbsonStream.h
26
 * and modified by Doris
27
 */
28
29
#ifndef JSONB_JSONBSTREAM_H
30
#define JSONB_JSONBSTREAM_H
31
32
#ifndef __STDC_FORMAT_MACROS
33
#define __STDC_FORMAT_MACROS
34
#endif
35
36
#include <fmt/format.h>
37
38
#include <cinttypes>
39
#include <iostream>
40
41
namespace doris {
42
43
using int128_t = __int128;
44
45
// lengths includes sign
46
118k
#define MAX_INT_DIGITS 11
47
215k
#define MAX_INT64_DIGITS 20
48
4.15k
#define MAX_INT128_DIGITS 40
49
14.4k
#define MAX_DOUBLE_DIGITS 23 // 1(sign)+16(significant)+1(decimal)+5(exponent)
50
51
/*
52
 * JSONB's implementation of input buffer
53
 */
54
class JsonbInBuffer : public std::streambuf {
55
public:
56
0
    JsonbInBuffer(const char* str, uint32_t len) {
57
0
        // this is read buffer and the str will not be changed
58
0
        // so we use const_cast (ugly!) to remove constness
59
0
        char* pch(const_cast<char*>(str));
60
0
        setg(pch, pch, pch + len);
61
0
    }
62
};
63
64
/*
65
 * JSONB's implementation of output stream.
66
 *
67
 * This is a wrapper of a char buffer. By default, the buffer capacity is 1024
68
 * bytes. We will double the buffer if realloc is needed for writes.
69
 */
70
class JsonbOutStream : public std::ostream {
71
public:
72
    explicit JsonbOutStream(uint64_t capacity = 1024)
73
5.03M
            : std::ostream(nullptr), head_(nullptr), size_(0), capacity_(capacity), alloc_(true) {
74
5.03M
        if (capacity_ == 0) {
75
0
            capacity_ = 1024;
76
0
        }
77
78
5.03M
        head_ = (char*)malloc(capacity_);
79
5.03M
    }
80
81
    JsonbOutStream(char* buffer, uint64_t capacity)
82
194k
            : std::ostream(nullptr), head_(buffer), size_(0), capacity_(capacity), alloc_(false) {
83
194k
        assert(buffer && capacity_ > 0);
84
194k
    }
85
86
5.23M
    ~JsonbOutStream() {
87
5.23M
        if (alloc_) {
88
5.04M
            free(head_);
89
5.04M
        }
90
5.23M
    }
91
92
79.9M
    void put(char c) { write(&c, 1); }
93
94
0
    void write(const char* c_str) { write(c_str, strlen(c_str)); }
95
96
148M
    void write(const char* bytes, uint64_t len) {
97
148M
        if (len == 0) {
98
23.8k
            return;
99
23.8k
        }
100
101
148M
        if (size_ + len > capacity_) {
102
24.3k
            realloc(len);
103
24.3k
        }
104
105
148M
        memcpy(head_ + size_, bytes, len);
106
148M
        size_ += len;
107
148M
    }
108
109
    // write the integer to string
110
59.3k
    void write(int i) {
111
        // snprintf automatically adds a NULL, so we need one more char
112
59.3k
        if (size_ + MAX_INT_DIGITS + 1 > capacity_) {
113
0
            realloc(MAX_INT_DIGITS + 1);
114
0
        }
115
116
59.3k
        int len = snprintf(head_ + size_, MAX_INT_DIGITS + 1, "%d", i);
117
59.3k
        assert(len > 0);
118
59.5k
        size_ += len;
119
59.5k
    }
120
121
    // write the 64bit integer to string
122
107k
    void write(int64_t l) {
123
        // snprintf automatically adds a NULL, so we need one more char
124
107k
        if (size_ + MAX_INT64_DIGITS + 1 > capacity_) {
125
0
            realloc(MAX_INT64_DIGITS + 1);
126
0
        }
127
128
107k
        int len = snprintf(head_ + size_, MAX_INT64_DIGITS + 1, "%" PRIi64, l);
129
107k
        assert(len > 0);
130
108k
        size_ += len;
131
108k
    }
132
133
2.07k
    void write(int128_t l) {
134
        // snprintf automatically adds a NULL, so we need one more char
135
2.07k
        if (size_ + MAX_INT128_DIGITS + 1 > capacity_) {
136
0
            realloc(MAX_INT128_DIGITS + 1);
137
0
        }
138
139
2.07k
        const auto result = fmt::format_to_n(head_ + size_, MAX_INT128_DIGITS, "{}", l);
140
2.07k
        assert(result.size > 0);
141
2.07k
        size_ += result.size;
142
2.07k
    }
143
144
    // write the double/float to string
145
    template <typename T>
146
        requires(std::is_floating_point_v<T>)
147
7.21k
    void write(T d) {
148
        // snprintf automatically adds a NULL, so we need one more char
149
7.21k
        if (size_ + MAX_DOUBLE_DIGITS + 1 > capacity_) {
150
0
            realloc(MAX_DOUBLE_DIGITS + 1);
151
0
        }
152
153
7.21k
        const auto result = fmt::format_to_n(head_ + size_, MAX_DOUBLE_DIGITS + 1, "{}", d);
154
7.21k
        assert(result.size > 0);
155
7.21k
        size_ += result.size;
156
7.21k
    }
_ZN5doris14JsonbOutStream5writeIdQsr3stdE19is_floating_point_vIT_EEEvS2_
Line
Count
Source
147
7.21k
    void write(T d) {
148
        // snprintf automatically adds a NULL, so we need one more char
149
7.21k
        if (size_ + MAX_DOUBLE_DIGITS + 1 > capacity_) {
150
0
            realloc(MAX_DOUBLE_DIGITS + 1);
151
0
        }
152
153
7.21k
        const auto result = fmt::format_to_n(head_ + size_, MAX_DOUBLE_DIGITS + 1, "{}", d);
154
7.21k
        assert(result.size > 0);
155
7.21k
        size_ += result.size;
156
7.21k
    }
_ZN5doris14JsonbOutStream5writeIfQsr3stdE19is_floating_point_vIT_EEEvS2_
Line
Count
Source
147
4
    void write(T d) {
148
        // snprintf automatically adds a NULL, so we need one more char
149
4
        if (size_ + MAX_DOUBLE_DIGITS + 1 > capacity_) {
150
0
            realloc(MAX_DOUBLE_DIGITS + 1);
151
0
        }
152
153
4
        const auto result = fmt::format_to_n(head_ + size_, MAX_DOUBLE_DIGITS + 1, "{}", d);
154
4
        assert(result.size > 0);
155
4
        size_ += result.size;
156
4
    }
157
158
25.5M
    pos_type tellp() const { return size_; }
159
160
20.9M
    void seekp(pos_type pos) { size_ = (uint64_t)pos; }
161
162
5.39M
    const char* getBuffer() const { return head_; }
163
164
5.19M
    pos_type getSize() const { return tellp(); }
165
166
private:
167
24.3k
    void realloc(uint64_t len) {
168
24.3k
        assert(capacity_ > 0);
169
170
24.3k
        capacity_ *= 2;
171
24.6k
        while (capacity_ < size_ + len) {
172
281
            capacity_ *= 2;
173
281
        }
174
175
24.3k
        if (alloc_) {
176
22.7k
            char* new_buf = (char*)::realloc(head_, capacity_);
177
22.7k
            assert(new_buf);
178
22.7k
            head_ = new_buf;
179
22.7k
        } else {
180
1.62k
            char* new_buf = (char*)::malloc(capacity_);
181
1.62k
            assert(new_buf);
182
1.62k
            memcpy(new_buf, head_, size_);
183
1.62k
            head_ = new_buf;
184
1.62k
            alloc_ = true;
185
1.62k
        }
186
24.3k
    }
187
188
private:
189
    char* head_ = nullptr;
190
    uint64_t size_;
191
    uint64_t capacity_;
192
    bool alloc_;
193
};
194
195
} // namespace doris
196
197
#endif // JSONB_JSONBSTREAM_H