Coverage Report

Created: 2025-04-16 14:29

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