Coverage Report

Created: 2025-04-24 12:01

/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 <sstream>
25
26
#include "common/exception.h"
27
#include "jsonb_document.h"
28
#include "jsonb_stream.h"
29
#include "jsonb_writer.h"
30
31
namespace doris {
32
33
#define OUT_BUF_SIZE 1024
34
35
/*
36
 * JsonbToJson converts an JsonbValue object to a JSON string.
37
 */
38
class JsonbToJson {
39
public:
40
59
    JsonbToJson() : os_(buffer_, OUT_BUF_SIZE) {}
41
42
    // get json string
43
55
    const std::string to_json_string(const char* data, size_t size) {
44
55
        JsonbDocument* pdoc = doris::JsonbDocument::checkAndCreateDocument(data, size);
45
55
        if (!pdoc) {
46
0
            throw Exception(Status::FatalError("invalid json binary value: {}",
47
0
                                               std::string_view(data, size)));
48
0
        }
49
55
        return to_json_string(pdoc->getValue());
50
55
    }
51
52
81
    const std::string to_json_string(const JsonbValue* val) {
53
81
        os_.clear();
54
81
        os_.seekp(0);
55
56
81
        if (val) {
57
81
            intern_json(val);
58
81
        }
59
60
81
        os_.put(0);
61
62
81
        std::string json_string {os_.getBuffer()};
63
81
        return json_string;
64
81
    }
65
66
55
    static const std::string jsonb_to_json_string(const char* data, size_t size) {
67
55
        JsonbToJson jsonb_to_json;
68
55
        return jsonb_to_json.to_json_string(data, size);
69
55
    }
70
71
private:
72
    // recursively convert JsonbValue
73
272
    void intern_json(const JsonbValue* val) {
74
272
        switch (val->type()) {
75
8
        case JsonbType::T_Null: {
76
8
            os_.write("null", 4);
77
8
            break;
78
0
        }
79
8
        case JsonbType::T_True: {
80
8
            os_.write("true", 4);
81
8
            break;
82
0
        }
83
5
        case JsonbType::T_False: {
84
5
            os_.write("false", 5);
85
5
            break;
86
0
        }
87
40
        case JsonbType::T_Int8: {
88
40
            os_.write(((JsonbInt8Val*)val)->val());
89
40
            break;
90
0
        }
91
17
        case JsonbType::T_Int16: {
92
17
            os_.write(((JsonbInt16Val*)val)->val());
93
17
            break;
94
0
        }
95
4
        case JsonbType::T_Int32: {
96
4
            os_.write(((JsonbInt32Val*)val)->val());
97
4
            break;
98
0
        }
99
4
        case JsonbType::T_Int64: {
100
4
            os_.write(((JsonbInt64Val*)val)->val());
101
4
            break;
102
0
        }
103
38
        case JsonbType::T_Double: {
104
38
            os_.write(((JsonbDoubleVal*)val)->val());
105
38
            break;
106
0
        }
107
0
        case JsonbType::T_Float: {
108
0
            os_.write(((JsonbFloatVal*)val)->val());
109
0
            break;
110
0
        }
111
0
        case JsonbType::T_Int128: {
112
0
            os_.write(((JsonbInt128Val*)val)->val());
113
0
            break;
114
0
        }
115
45
        case JsonbType::T_String: {
116
45
            string_to_json(((JsonbStringVal*)val)->getBlob(), ((JsonbStringVal*)val)->length());
117
45
            break;
118
0
        }
119
0
        case JsonbType::T_Binary: {
120
0
            os_.write("\"<BINARY>", 9);
121
0
            os_.write(((JsonbBinaryVal*)val)->getBlob(), ((JsonbBinaryVal*)val)->getBlobLen());
122
0
            os_.write("<BINARY>\"", 9);
123
0
            break;
124
0
        }
125
73
        case JsonbType::T_Object: {
126
73
            object_to_json((ObjectVal*)val);
127
73
            break;
128
0
        }
129
30
        case JsonbType::T_Array: {
130
30
            array_to_json((ArrayVal*)val);
131
30
            break;
132
0
        }
133
0
        default:
134
0
            break;
135
272
        }
136
272
    }
137
138
145
    void string_to_json(const char* str, size_t len) {
139
145
        os_.put('"');
140
145
        if (nullptr == str) {
141
1
            os_.put('"');
142
1
            return;
143
1
        }
144
144
        char char_buffer[16];
145
1.00M
        for (const char* ptr = str; ptr != str + len && *ptr; ++ptr) {
146
1.00M
            if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
147
1.00M
                os_.put(*ptr);
148
6
            else {
149
6
                os_.put('\\');
150
6
                unsigned char token;
151
6
                switch (token = *ptr) {
152
0
                case '\\':
153
0
                    os_.put('\\');
154
0
                    break;
155
1
                case '\"':
156
1
                    os_.put('\"');
157
1
                    break;
158
1
                case '\b':
159
1
                    os_.put('b');
160
1
                    break;
161
1
                case '\f':
162
1
                    os_.put('f');
163
1
                    break;
164
1
                case '\n':
165
1
                    os_.put('n');
166
1
                    break;
167
1
                case '\r':
168
1
                    os_.put('r');
169
1
                    break;
170
1
                case '\t':
171
1
                    os_.put('t');
172
1
                    break;
173
0
                default: {
174
0
                    int char_num = snprintf(char_buffer, sizeof(char_buffer), "u%04x", token);
175
0
                    os_.write(char_buffer, char_num);
176
0
                    break;
177
0
                }
178
6
                }
179
6
            }
180
1.00M
        }
181
144
        os_.put('"');
182
144
    }
183
184
    // convert object
185
73
    void object_to_json(const ObjectVal* val) {
186
73
        os_.put('{');
187
188
73
        auto iter = val->begin();
189
73
        auto iter_fence = val->end();
190
191
173
        while (iter < iter_fence) {
192
            // write key
193
100
            if (iter->klen()) {
194
99
                string_to_json(iter->getKeyStr(), iter->klen());
195
99
            } else {
196
                // NOTE: we use sMaxKeyId to represent an empty key. see jsonb_writer.h
197
1
                if (iter->getKeyId() == JsonbKeyValue::sMaxKeyId) {
198
1
                    string_to_json(nullptr, 0);
199
1
                } else {
200
0
                    os_.write(iter->getKeyId());
201
0
                }
202
1
            }
203
100
            os_.put(':');
204
205
            // convert value
206
100
            intern_json(iter->value());
207
208
100
            ++iter;
209
100
            if (iter != iter_fence) {
210
33
                os_.put(',');
211
33
            }
212
100
        }
213
214
73
        assert(iter == iter_fence);
215
216
0
        os_.put('}');
217
73
    }
218
219
    // convert array to json
220
30
    void array_to_json(const ArrayVal* val) {
221
30
        os_.put('[');
222
223
30
        auto iter = val->begin();
224
30
        auto iter_fence = val->end();
225
226
121
        while (iter != iter_fence) {
227
            // convert value
228
91
            intern_json((const JsonbValue*)iter);
229
91
            ++iter;
230
91
            if (iter != iter_fence) {
231
64
                os_.put(',');
232
64
            }
233
91
        }
234
235
30
        assert(iter == iter_fence);
236
237
0
        os_.put(']');
238
30
    }
239
240
private:
241
    JsonbOutStream os_;
242
    char buffer_[OUT_BUF_SIZE];
243
};
244
245
// This class is a utility to create a JsonbValue.
246
template <class OS_TYPE>
247
class JsonbValueCreaterT {
248
public:
249
    JsonbValue* operator()(int32_t val) { return operator()((int64_t)val); }
250
251
    JsonbValue* operator()(int64_t val) {
252
        writer_.reset();
253
        writer_.writeStartArray();
254
        writer_.writeInt(val);
255
        writer_.writeEndArray();
256
        return extractValue();
257
    }
258
    JsonbValue* operator()(double val) {
259
        writer_.reset();
260
        writer_.writeStartArray();
261
        writer_.writeDouble(val);
262
        writer_.writeEndArray();
263
        return extractValue();
264
    }
265
    JsonbValue* operator()(const char* str) { return operator()(str, (unsigned int)strlen(str)); }
266
    JsonbValue* operator()(const char* str, unsigned int str_len) {
267
        writer_.reset();
268
        writer_.writeStartArray();
269
        writer_.writeStartString();
270
        writer_.writeString(str, str_len);
271
        writer_.writeEndString();
272
        writer_.writeEndArray();
273
        return extractValue();
274
    }
275
    JsonbValue* operator()(bool val) {
276
        writer_.reset();
277
        writer_.writeStartArray();
278
        writer_.writeBool(val);
279
        writer_.writeEndArray();
280
        return extractValue();
281
    }
282
    JsonbValue* operator()() {
283
        writer_.reset();
284
        writer_.writeStartArray();
285
        writer_.writeNull();
286
        writer_.writeEndArray();
287
        return extractValue();
288
    }
289
290
private:
291
    JsonbValue* extractValue() {
292
        return static_cast<ArrayVal*>(
293
                       JsonbDocument::createValue(writer_.getOutput()->getBuffer(),
294
                                                  (int)writer_.getOutput()->getSize()))
295
                ->get(0);
296
    }
297
    JsonbWriterT<OS_TYPE> writer_;
298
};
299
typedef JsonbValueCreaterT<JsonbOutStream> JsonbValueCreater;
300
} // namespace doris
301
302
#endif // JSONB_JSONBUTIL_H