Coverage Report

Created: 2024-11-21 10:56

/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
266
    JsonbToJson() : os_(buffer_, OUT_BUF_SIZE) {}
40
41
    // get json string
42
262
    const std::string to_json_string(const char* data, size_t size) {
43
262
        JsonbDocument* pdoc = doris::JsonbDocument::createDocument(data, size);
44
262
        if (!pdoc) {
45
0
            LOG(FATAL) << "invalid json binary value: " << std::string_view(data, size);
46
0
        }
47
262
        return to_json_string(pdoc->getValue());
48
262
    }
49
50
288
    const std::string to_json_string(const JsonbValue* val) {
51
288
        os_.clear();
52
288
        os_.seekp(0);
53
54
288
        if (val) {
55
288
            intern_json(val);
56
288
        }
57
58
288
        os_.put(0);
59
60
288
        std::string json_string {os_.getBuffer()};
61
288
        return json_string;
62
288
    }
63
64
262
    static const std::string jsonb_to_json_string(const char* data, size_t size) {
65
262
        JsonbToJson jsonb_to_json;
66
262
        return jsonb_to_json.to_json_string(data, size);
67
262
    }
68
69
private:
70
    // recursively convert JsonbValue
71
582
    void intern_json(const JsonbValue* val) {
72
582
        switch (val->type()) {
73
30
        case JsonbType::T_Null: {
74
30
            os_.write("null", 4);
75
30
            break;
76
0
        }
77
32
        case JsonbType::T_True: {
78
32
            os_.write("true", 4);
79
32
            break;
80
0
        }
81
32
        case JsonbType::T_False: {
82
32
            os_.write("false", 5);
83
32
            break;
84
0
        }
85
70
        case JsonbType::T_Int8: {
86
70
            os_.write(((JsonbInt8Val*)val)->val());
87
70
            break;
88
0
        }
89
67
        case JsonbType::T_Int16: {
90
67
            os_.write(((JsonbInt16Val*)val)->val());
91
67
            break;
92
0
        }
93
15
        case JsonbType::T_Int32: {
94
15
            os_.write(((JsonbInt32Val*)val)->val());
95
15
            break;
96
0
        }
97
15
        case JsonbType::T_Int64: {
98
15
            os_.write(((JsonbInt64Val*)val)->val());
99
15
            break;
100
0
        }
101
57
        case JsonbType::T_Double: {
102
57
            os_.write(((JsonbDoubleVal*)val)->val());
103
57
            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
128
        case JsonbType::T_String: {
114
128
            string_to_json(((JsonbStringVal*)val)->getBlob(), ((JsonbStringVal*)val)->length());
115
128
            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
57
        case JsonbType::T_Object: {
124
57
            object_to_json((ObjectVal*)val);
125
57
            break;
126
0
        }
127
79
        case JsonbType::T_Array: {
128
79
            array_to_json((ArrayVal*)val);
129
79
            break;
130
0
        }
131
0
        default:
132
0
            break;
133
582
        }
134
582
    }
135
136
200
    void string_to_json(const char* str, size_t len) {
137
200
        os_.put('"');
138
200
        if (nullptr == str) {
139
0
            os_.put('"');
140
0
            return;
141
0
        }
142
200
        char char_buffer[16];
143
711
        for (const char* ptr = str; ptr != str + len && *ptr; ++ptr) {
144
511
            if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
145
511
                os_.put(*ptr);
146
0
            else {
147
0
                os_.put('\\');
148
0
                unsigned char token;
149
0
                switch (token = *ptr) {
150
0
                case '\\':
151
0
                    os_.put('\\');
152
0
                    break;
153
0
                case '\"':
154
0
                    os_.put('\"');
155
0
                    break;
156
0
                case '\b':
157
0
                    os_.put('b');
158
0
                    break;
159
0
                case '\f':
160
0
                    os_.put('f');
161
0
                    break;
162
0
                case '\n':
163
0
                    os_.put('n');
164
0
                    break;
165
0
                case '\r':
166
0
                    os_.put('r');
167
0
                    break;
168
0
                case '\t':
169
0
                    os_.put('t');
170
0
                    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
0
                }
177
0
            }
178
511
        }
179
200
        os_.put('"');
180
200
    }
181
182
    // convert object
183
57
    void object_to_json(const ObjectVal* val) {
184
57
        os_.put('{');
185
186
57
        auto iter = val->begin();
187
57
        auto iter_fence = val->end();
188
189
129
        while (iter < iter_fence) {
190
            // write key
191
72
            if (iter->klen()) {
192
72
                string_to_json(iter->getKeyStr(), iter->klen());
193
72
            } else {
194
                // NOTE: we use sMaxKeyId to represent an empty key. see jsonb_writer.h
195
0
                if (iter->getKeyId() == JsonbKeyValue::sMaxKeyId) {
196
0
                    string_to_json(nullptr, 0);
197
0
                } else {
198
0
                    os_.write(iter->getKeyId());
199
0
                }
200
0
            }
201
72
            os_.put(':');
202
203
            // convert value
204
72
            intern_json(iter->value());
205
206
72
            ++iter;
207
72
            if (iter != iter_fence) {
208
36
                os_.put(',');
209
36
            }
210
72
        }
211
212
57
        assert(iter == iter_fence);
213
214
0
        os_.put('}');
215
57
    }
216
217
    // convert array to json
218
79
    void array_to_json(const ArrayVal* val) {
219
79
        os_.put('[');
220
221
79
        auto iter = val->begin();
222
79
        auto iter_fence = val->end();
223
224
301
        while (iter != iter_fence) {
225
            // convert value
226
222
            intern_json((const JsonbValue*)iter);
227
222
            ++iter;
228
222
            if (iter != iter_fence) {
229
158
                os_.put(',');
230
158
            }
231
222
        }
232
233
79
        assert(iter == iter_fence);
234
235
0
        os_.put(']');
236
79
    }
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