Coverage Report

Created: 2024-11-21 11:46

/root/doris/be/src/util/jsonb_stream.h
Line
Count
Source (jump to first uncovered line)
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 <assert.h>
37
#include <fmt/format.h>
38
#include <string.h>
39
40
#include <algorithm>
41
#include <cinttypes>
42
#include <iostream>
43
44
namespace doris {
45
46
using int128_t = __int128;
47
48
// lengths includes sign
49
304
#define MAX_INT_DIGITS 11
50
30
#define MAX_INT64_DIGITS 20
51
0
#define MAX_INT128_DIGITS 40
52
114
#define MAX_DOUBLE_DIGITS 23 // 1(sign)+16(significant)+1(decimal)+5(exponent)
53
54
/*
55
 * JSONB's implementation of input buffer
56
 */
57
class JsonbInBuffer : public std::streambuf {
58
public:
59
1.19k
    JsonbInBuffer(const char* str, uint32_t len) {
60
        // this is read buffer and the str will not be changed
61
        // so we use const_cast (ugly!) to remove constness
62
1.19k
        char* pch(const_cast<char*>(str));
63
1.19k
        setg(pch, pch, pch + len);
64
1.19k
    }
65
};
66
67
/*
68
 * JSONB's implementation of output stream.
69
 *
70
 * This is a wrapper of a char buffer. By default, the buffer capacity is 1024
71
 * bytes. We will double the buffer if realloc is needed for writes.
72
 */
73
class JsonbOutStream : public std::ostream {
74
public:
75
    explicit JsonbOutStream(uint64_t capacity = 1024)
76
2.05k
            : std::ostream(nullptr), head_(nullptr), size_(0), capacity_(capacity), alloc_(true) {
77
2.05k
        if (capacity_ == 0) {
78
0
            capacity_ = 1024;
79
0
        }
80
81
2.05k
        head_ = (char*)malloc(capacity_);
82
2.05k
    }
Unexecuted instantiation: _ZN5doris14JsonbOutStreamC2Em
_ZN5doris14JsonbOutStreamC1Em
Line
Count
Source
76
2.05k
            : std::ostream(nullptr), head_(nullptr), size_(0), capacity_(capacity), alloc_(true) {
77
2.05k
        if (capacity_ == 0) {
78
0
            capacity_ = 1024;
79
0
        }
80
81
2.05k
        head_ = (char*)malloc(capacity_);
82
2.05k
    }
83
84
    JsonbOutStream(char* buffer, uint64_t capacity)
85
266
            : std::ostream(nullptr), head_(buffer), size_(0), capacity_(capacity), alloc_(false) {
86
266
        assert(buffer && capacity_ > 0);
87
266
    }
Unexecuted instantiation: _ZN5doris14JsonbOutStreamC2EPcm
_ZN5doris14JsonbOutStreamC1EPcm
Line
Count
Source
85
266
            : std::ostream(nullptr), head_(buffer), size_(0), capacity_(capacity), alloc_(false) {
86
266
        assert(buffer && capacity_ > 0);
87
266
    }
88
89
2.31k
    ~JsonbOutStream() {
90
2.31k
        if (alloc_) {
91
2.05k
            free(head_);
92
2.05k
        }
93
2.31k
    }
94
95
27.0k
    void put(char c) { write(&c, 1); }
96
97
0
    void write(const char* c_str) { write(c_str, strlen(c_str)); }
98
99
55.9k
    void write(const char* bytes, uint64_t len) {
100
55.9k
        if (len == 0) {
101
0
            return;
102
0
        }
103
104
55.9k
        if (size_ + len > capacity_) {
105
0
            realloc(len);
106
0
        }
107
108
55.9k
        memcpy(head_ + size_, bytes, len);
109
55.9k
        size_ += len;
110
55.9k
    }
111
112
    // write the integer to string
113
152
    void write(int i) {
114
        // snprintf automatically adds a NULL, so we need one more char
115
152
        if (size_ + MAX_INT_DIGITS + 1 > capacity_) {
116
0
            realloc(MAX_INT_DIGITS + 1);
117
0
        }
118
119
152
        int len = snprintf(head_ + size_, MAX_INT_DIGITS + 1, "%d", i);
120
152
        assert(len > 0);
121
0
        size_ += len;
122
152
    }
123
124
    // write the 64bit integer to string
125
15
    void write(int64_t l) {
126
        // snprintf automatically adds a NULL, so we need one more char
127
15
        if (size_ + MAX_INT64_DIGITS + 1 > capacity_) {
128
0
            realloc(MAX_INT64_DIGITS + 1);
129
0
        }
130
131
15
        int len = snprintf(head_ + size_, MAX_INT64_DIGITS + 1, "%" PRIi64, l);
132
15
        assert(len > 0);
133
0
        size_ += len;
134
15
    }
135
136
0
    void write(int128_t l) {
137
        // snprintf automatically adds a NULL, so we need one more char
138
0
        if (size_ + MAX_INT128_DIGITS + 1 > capacity_) {
139
0
            realloc(MAX_INT128_DIGITS + 1);
140
0
        }
141
142
0
        const auto result = fmt::format_to_n(head_ + size_, MAX_INT128_DIGITS, "{}", l);
143
0
        assert(result.size > 0);
144
0
        size_ += result.size;
145
0
    }
146
147
    // write the double to string
148
57
    void write(double d) {
149
        // snprintf automatically adds a NULL, so we need one more char
150
57
        if (size_ + MAX_DOUBLE_DIGITS + 1 > capacity_) {
151
0
            realloc(MAX_DOUBLE_DIGITS + 1);
152
0
        }
153
154
57
        int len = snprintf(head_ + size_, MAX_DOUBLE_DIGITS + 1, "%.15g", d);
155
57
        assert(len > 0);
156
0
        size_ += len;
157
57
    }
158
159
13.0k
    pos_type tellp() const { return size_; }
160
161
12.3k
    void seekp(pos_type pos) { size_ = (uint64_t)pos; }
162
163
2.49k
    const char* getBuffer() const { return head_; }
164
165
2.20k
    pos_type getSize() const { return tellp(); }
166
167
private:
168
0
    void realloc(uint64_t len) {
169
0
        assert(capacity_ > 0);
170
171
0
        capacity_ *= 2;
172
0
        while (capacity_ < size_ + len) {
173
0
            capacity_ *= 2;
174
0
        }
175
176
0
        if (alloc_) {
177
0
            char* new_buf = (char*)::realloc(head_, capacity_);
178
0
            assert(new_buf);
179
0
            head_ = new_buf;
180
0
        } else {
181
0
            char* new_buf = (char*)::malloc(capacity_);
182
0
            assert(new_buf);
183
0
            memcpy(new_buf, head_, size_);
184
0
            head_ = new_buf;
185
0
            alloc_ = true;
186
0
        }
187
0
    }
188
189
private:
190
    char* head_ = nullptr;
191
    uint64_t size_;
192
    uint64_t capacity_;
193
    bool alloc_;
194
};
195
196
} // namespace doris
197
198
#endif // JSONB_JSONBSTREAM_H