Coverage Report

Created: 2025-06-19 11:25

/root/doris/be/src/util/jsonb_utils.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 miscellaneous utility classes.
13
 *
14
 * @author Tian Xia <tianx@fb.com>
15
 *
16
 *  this file is copied from 
17
 * https://github.com/facebook/mysql-5.6/blob/fb-mysql-5.6.35/fbson/FbsonUtil.h
18
 * and modified by Doris
19
 */
20
21
#ifndef JSONB_JSONBUTIL_H
22
#define JSONB_JSONBUTIL_H
23
24
#include "common/status.h"
25
#include "jsonb_document.h"
26
#include "jsonb_stream.h"
27
28
namespace doris {
29
30
#define OUT_BUF_SIZE 1024
31
32
/*
33
 * JsonbToJson converts an JsonbValue object to a JSON string.
34
 */
35
class JsonbToJson {
36
public:
37
210
    JsonbToJson() : os_(buffer_, OUT_BUF_SIZE) {}
38
39
    // get json string
40
206
    std::string to_json_string(const char* data, size_t size) {
41
206
        JsonbDocument* pdoc;
42
206
        THROW_IF_ERROR(doris::JsonbDocument::checkAndCreateDocument(data, size, &pdoc));
43
206
        return to_json_string(pdoc->getValue());
44
206
    }
45
46
232
    std::string to_json_string(const JsonbValue* val) {
47
232
        os_.clear();
48
232
        os_.seekp(0);
49
50
232
        if (val) {
51
232
            intern_json(val);
52
232
        }
53
54
232
        os_.put(0);
55
56
232
        std::string json_string {os_.getBuffer()};
57
232
        return json_string;
58
232
    }
59
60
206
    static std::string jsonb_to_json_string(const char* data, size_t size) {
61
206
        JsonbToJson jsonb_to_json;
62
206
        return jsonb_to_json.to_json_string(data, size);
63
206
    }
64
65
private:
66
    // recursively convert JsonbValue
67
1.51k
    void intern_json(const JsonbValue* val) {
68
1.51k
        switch (val->type()) {
69
39
        case JsonbType::T_Null: {
70
39
            os_.write("null", 4);
71
39
            break;
72
0
        }
73
49
        case JsonbType::T_True: {
74
49
            os_.write("true", 4);
75
49
            break;
76
0
        }
77
16
        case JsonbType::T_False: {
78
16
            os_.write("false", 5);
79
16
            break;
80
0
        }
81
611
        case JsonbType::T_Int8: {
82
611
            os_.write(((JsonbInt8Val*)val)->val());
83
611
            break;
84
0
        }
85
18
        case JsonbType::T_Int16: {
86
18
            os_.write(((JsonbInt16Val*)val)->val());
87
18
            break;
88
0
        }
89
4
        case JsonbType::T_Int32: {
90
4
            os_.write(((JsonbInt32Val*)val)->val());
91
4
            break;
92
0
        }
93
4
        case JsonbType::T_Int64: {
94
4
            os_.write(((JsonbInt64Val*)val)->val());
95
4
            break;
96
0
        }
97
48
        case JsonbType::T_Double: {
98
48
            os_.write(((JsonbDoubleVal*)val)->val());
99
48
            break;
100
0
        }
101
1
        case JsonbType::T_Float: {
102
1
            os_.write(((JsonbFloatVal*)val)->val());
103
1
            break;
104
0
        }
105
1
        case JsonbType::T_Int128: {
106
1
            os_.write(((JsonbInt128Val*)val)->val());
107
1
            break;
108
0
        }
109
137
        case JsonbType::T_String: {
110
137
            string_to_json(((JsonbStringVal*)val)->getBlob(), ((JsonbStringVal*)val)->length());
111
137
            break;
112
0
        }
113
0
        case JsonbType::T_Binary: {
114
0
            os_.write("\"<BINARY>", 9);
115
0
            os_.write(((JsonbBinaryVal*)val)->getBlob(), ((JsonbBinaryVal*)val)->getBlobLen());
116
0
            os_.write("<BINARY>\"", 9);
117
0
            break;
118
0
        }
119
514
        case JsonbType::T_Object: {
120
514
            object_to_json((ObjectVal*)val);
121
514
            break;
122
0
        }
123
71
        case JsonbType::T_Array: {
124
71
            array_to_json((ArrayVal*)val);
125
71
            break;
126
0
        }
127
1
        case JsonbType::T_Decimal32: {
128
1
            const auto* decimal_val = static_cast<const JsonbDecimal32*>(val);
129
1
            decimal_to_json(decimal_val->val(), decimal_val->precision(), decimal_val->scale());
130
1
            break;
131
0
        }
132
1
        case JsonbType::T_Decimal64: {
133
1
            const auto* decimal_val = static_cast<const JsonbDecimal64*>(val);
134
1
            decimal_to_json(decimal_val->val(), decimal_val->precision(), decimal_val->scale());
135
1
            break;
136
0
        }
137
1
        case JsonbType::T_Decimal128: {
138
1
            const auto* decimal_val = static_cast<const JsonbDecimal128*>(val);
139
1
            decimal_to_json(decimal_val->val(), decimal_val->precision(), decimal_val->scale());
140
1
            break;
141
0
        }
142
1
        case JsonbType::T_Decimal256: {
143
1
            const auto* decimal_val = static_cast<const JsonbDecimal256*>(val);
144
1
            decimal_to_json(decimal_val->val(), decimal_val->precision(), decimal_val->scale());
145
1
            break;
146
0
        }
147
0
        default:
148
0
            break;
149
1.51k
        }
150
1.51k
    }
151
152
759
    void string_to_json(const char* str, size_t len) {
153
759
        os_.put('"');
154
759
        if (nullptr == str) {
155
1
            os_.put('"');
156
1
            return;
157
1
        }
158
758
        char char_buffer[16];
159
1.00M
        for (const char* ptr = str; ptr != str + len && *ptr; ++ptr) {
160
1.00M
            if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\') {
161
1.00M
                os_.put(*ptr);
162
1.00M
            } else {
163
6
                os_.put('\\');
164
6
                unsigned char token;
165
6
                switch (token = *ptr) {
166
0
                case '\\':
167
0
                    os_.put('\\');
168
0
                    break;
169
1
                case '\"':
170
1
                    os_.put('\"');
171
1
                    break;
172
1
                case '\b':
173
1
                    os_.put('b');
174
1
                    break;
175
1
                case '\f':
176
1
                    os_.put('f');
177
1
                    break;
178
1
                case '\n':
179
1
                    os_.put('n');
180
1
                    break;
181
1
                case '\r':
182
1
                    os_.put('r');
183
1
                    break;
184
1
                case '\t':
185
1
                    os_.put('t');
186
1
                    break;
187
0
                default: {
188
0
                    int char_num = snprintf(char_buffer, sizeof(char_buffer), "u%04x", token);
189
0
                    os_.write(char_buffer, char_num);
190
0
                    break;
191
0
                }
192
6
                }
193
6
            }
194
1.00M
        }
195
758
        os_.put('"');
196
758
    }
197
198
    // convert object
199
514
    void object_to_json(const ObjectVal* val) {
200
514
        os_.put('{');
201
202
514
        auto iter = val->begin();
203
514
        auto iter_fence = val->end();
204
205
1.13k
        while (iter < iter_fence) {
206
            // write key
207
622
            if (iter->klen()) {
208
621
                string_to_json(iter->getKeyStr(), iter->klen());
209
621
            } else {
210
                // NOTE: we use sMaxKeyId to represent an empty key. see jsonb_writer.h
211
1
                if (iter->getKeyId() == JsonbKeyValue::sMaxKeyId) {
212
1
                    string_to_json(nullptr, 0);
213
1
                } else {
214
0
                    os_.write(iter->getKeyId());
215
0
                }
216
1
            }
217
622
            os_.put(':');
218
219
            // convert value
220
622
            intern_json(iter->value());
221
222
622
            ++iter;
223
622
            if (iter != iter_fence) {
224
124
                os_.put(',');
225
124
            }
226
622
        }
227
228
514
        assert(iter == iter_fence);
229
230
0
        os_.put('}');
231
514
    }
232
233
    // convert array to json
234
71
    void array_to_json(const ArrayVal* val) {
235
71
        os_.put('[');
236
237
71
        auto iter = val->begin();
238
71
        auto iter_fence = val->end();
239
240
734
        while (iter != iter_fence) {
241
            // convert value
242
663
            intern_json((const JsonbValue*)iter);
243
663
            ++iter;
244
663
            if (iter != iter_fence) {
245
605
                os_.put(',');
246
605
            }
247
663
        }
248
249
71
        assert(iter == iter_fence);
250
251
0
        os_.put(']');
252
71
    }
253
254
    template <JsonbDecimalType T>
255
    void decimal_to_json(const T& value, const uint32_t precision, const uint32_t scale);
256
257
    JsonbOutStream os_;
258
    char buffer_[OUT_BUF_SIZE];
259
};
260
261
} // namespace doris
262
263
#endif // JSONB_JSONBUTIL_H