Coverage Report

Created: 2025-08-22 14:32

/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/exception.h"
25
#include "jsonb_document.h"
26
#include "jsonb_stream.h"
27
#include "jsonb_writer.h"
28
29
namespace doris {
30
31
#define OUT_BUF_SIZE 1024
32
33
/*
34
 * JsonbToJson converts an JsonbValue object to a JSON string.
35
 */
36
class JsonbToJson {
37
public:
38
91.3k
    JsonbToJson() : os_(buffer_, OUT_BUF_SIZE) {}
39
40
    // get json string
41
42
91.3k
    std::string to_json_string(const char* data, size_t size) {
43
91.3k
        JsonbDocument* pdoc;
44
91.3k
        auto st = doris::JsonbDocument::checkAndCreateDocument(data, size, &pdoc);
45
91.3k
        if (!st.ok()) {
  Branch (45:13): [True: 0, False: 91.3k]
46
0
            throw Exception(st);
47
0
        }
48
91.3k
        return to_json_string(pdoc->getValue());
49
91.3k
    }
50
51
91.4k
    std::string to_json_string(const JsonbValue* val) {
52
91.4k
        os_.clear();
53
91.4k
        os_.seekp(0);
54
55
91.4k
        if (val) {
  Branch (55:13): [True: 91.4k, False: 0]
56
91.4k
            intern_json(val);
57
91.4k
        }
58
59
91.4k
        os_.put(0);
60
61
91.4k
        std::string json_string {os_.getBuffer()};
62
91.4k
        return json_string;
63
91.4k
    }
64
65
91.3k
    static std::string jsonb_to_json_string(const char* data, size_t size) {
66
91.3k
        JsonbToJson jsonb_to_json;
67
91.3k
        return jsonb_to_json.to_json_string(data, size);
68
91.3k
    }
69
70
private:
71
    // recursively convert JsonbValue
72
4.25M
    void intern_json(const JsonbValue* val) {
73
4.25M
        switch (val->type()) {
74
88.6k
        case JsonbType::T_Null: {
  Branch (74:9): [True: 88.6k, False: 4.16M]
75
88.6k
            os_.write("null", 4);
76
88.6k
            break;
77
0
        }
78
10.7k
        case JsonbType::T_True: {
  Branch (78:9): [True: 10.7k, False: 4.24M]
79
10.7k
            os_.write("true", 4);
80
10.7k
            break;
81
0
        }
82
10.7k
        case JsonbType::T_False: {
  Branch (82:9): [True: 10.7k, False: 4.24M]
83
10.7k
            os_.write("false", 5);
84
10.7k
            break;
85
0
        }
86
744
        case JsonbType::T_Int8: {
  Branch (86:9): [True: 744, False: 4.25M]
87
744
            os_.write(((JsonbInt8Val*)val)->val());
88
744
            break;
89
0
        }
90
376
        case JsonbType::T_Int16: {
  Branch (90:9): [True: 376, False: 4.25M]
91
376
            os_.write(((JsonbInt16Val*)val)->val());
92
376
            break;
93
0
        }
94
388
        case JsonbType::T_Int32: {
  Branch (94:9): [True: 388, False: 4.25M]
95
388
            os_.write(((JsonbInt32Val*)val)->val());
96
388
            break;
97
0
        }
98
854k
        case JsonbType::T_Int64: {
  Branch (98:9): [True: 854k, False: 3.40M]
99
854k
            os_.write(((JsonbInt64Val*)val)->val());
100
854k
            break;
101
0
        }
102
768k
        case JsonbType::T_Double: {
  Branch (102:9): [True: 768k, False: 3.48M]
103
768k
            os_.write(((JsonbDoubleVal*)val)->val());
104
768k
            break;
105
0
        }
106
0
        case JsonbType::T_Float: {
  Branch (106:9): [True: 0, False: 4.25M]
107
0
            os_.write(((JsonbFloatVal*)val)->val());
108
0
            break;
109
0
        }
110
0
        case JsonbType::T_Int128: {
  Branch (110:9): [True: 0, False: 4.25M]
111
0
            os_.write(((JsonbInt128Val*)val)->val());
112
0
            break;
113
0
        }
114
1.96M
        case JsonbType::T_String: {
  Branch (114:9): [True: 1.96M, False: 2.29M]
115
1.96M
            string_to_json(((JsonbStringVal*)val)->getBlob(), ((JsonbStringVal*)val)->length());
116
1.96M
            break;
117
0
        }
118
0
        case JsonbType::T_Binary: {
  Branch (118:9): [True: 0, False: 4.25M]
119
0
            os_.write("\"<BINARY>", 9);
120
0
            os_.write(((JsonbBinaryVal*)val)->getBlob(), ((JsonbBinaryVal*)val)->getBlobLen());
121
0
            os_.write("<BINARY>\"", 9);
122
0
            break;
123
0
        }
124
249k
        case JsonbType::T_Object: {
  Branch (124:9): [True: 249k, False: 4.00M]
125
249k
            object_to_json((ObjectVal*)val);
126
249k
            break;
127
0
        }
128
309k
        case JsonbType::T_Array: {
  Branch (128:9): [True: 309k, False: 3.94M]
129
309k
            array_to_json((ArrayVal*)val);
130
309k
            break;
131
0
        }
132
0
        default:
  Branch (132:9): [True: 0, False: 4.25M]
133
0
            break;
134
4.25M
        }
135
4.25M
    }
136
137
2.71M
    void string_to_json(const char* str, size_t len) {
138
2.71M
        os_.put('"');
139
2.71M
        if (nullptr == str) {
  Branch (139:13): [True: 31.2k, False: 2.67M]
140
31.2k
            os_.put('"');
141
31.2k
            return;
142
31.2k
        }
143
2.67M
        char char_buffer[16];
144
92.3M
        for (const char* ptr = str; ptr != str + len && *ptr; ++ptr) {
  Branch (144:37): [True: 89.6M, False: 2.67M]
  Branch (144:57): [True: 89.6M, False: 288]
145
89.6M
            if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\') {
  Branch (145:17): [True: 89.1M, False: 482k]
  Branch (145:45): [True: 88.9M, False: 194k]
  Branch (145:61): [True: 88.7M, False: 196k]
146
88.7M
                os_.put(*ptr);
147
88.7M
            } else {
148
872k
                os_.put('\\');
149
872k
                unsigned char token;
150
872k
                switch (token = *ptr) {
151
196k
                case '\\':
  Branch (151:17): [True: 196k, False: 676k]
152
196k
                    os_.put('\\');
153
196k
                    break;
154
194k
                case '\"':
  Branch (154:17): [True: 194k, False: 678k]
155
194k
                    os_.put('\"');
156
194k
                    break;
157
96.4k
                case '\b':
  Branch (157:17): [True: 96.4k, False: 776k]
158
96.4k
                    os_.put('b');
159
96.4k
                    break;
160
96.4k
                case '\f':
  Branch (160:17): [True: 96.4k, False: 776k]
161
96.4k
                    os_.put('f');
162
96.4k
                    break;
163
96.4k
                case '\n':
  Branch (163:17): [True: 96.4k, False: 776k]
164
96.4k
                    os_.put('n');
165
96.4k
                    break;
166
96.3k
                case '\r':
  Branch (166:17): [True: 96.3k, False: 776k]
167
96.3k
                    os_.put('r');
168
96.3k
                    break;
169
96.5k
                case '\t':
  Branch (169:17): [True: 96.5k, False: 776k]
170
96.5k
                    os_.put('t');
171
96.5k
                    break;
172
0
                default: {
  Branch (172:17): [True: 0, False: 872k]
173
0
                    int char_num = snprintf(char_buffer, sizeof(char_buffer), "u%04x", token);
174
0
                    os_.write(char_buffer, char_num);
175
0
                    break;
176
0
                }
177
872k
                }
178
872k
            }
179
89.6M
        }
180
2.67M
        os_.put('"');
181
2.67M
    }
182
183
    // convert object
184
249k
    void object_to_json(const ObjectVal* val) {
185
249k
        os_.put('{');
186
187
249k
        auto iter = val->begin();
188
249k
        auto iter_fence = val->end();
189
190
998k
        while (iter < iter_fence) {
  Branch (190:16): [True: 749k, False: 249k]
191
            // write key
192
749k
            if (iter->klen()) {
  Branch (192:17): [True: 717k, False: 31.2k]
193
717k
                string_to_json(iter->getKeyStr(), iter->klen());
194
717k
            } else {
195
                // NOTE: we use sMaxKeyId to represent an empty key. see jsonb_writer.h
196
31.2k
                if (iter->getKeyId() == JsonbKeyValue::sMaxKeyId) {
  Branch (196:21): [True: 31.2k, False: 0]
197
31.2k
                    string_to_json(nullptr, 0);
198
31.2k
                } else {
199
0
                    os_.write(iter->getKeyId());
200
0
                }
201
31.2k
            }
202
749k
            os_.put(':');
203
204
            // convert value
205
749k
            intern_json(iter->value());
206
207
749k
            ++iter;
208
749k
            if (iter != iter_fence) {
  Branch (208:17): [True: 624k, False: 124k]
209
624k
                os_.put(',');
210
624k
            }
211
749k
        }
212
213
249k
        assert(iter == iter_fence);
214
215
0
        os_.put('}');
216
249k
    }
217
218
    // convert array to json
219
309k
    void array_to_json(const ArrayVal* val) {
220
309k
        os_.put('[');
221
222
309k
        auto iter = val->begin();
223
309k
        auto iter_fence = val->end();
224
225
3.72M
        while (iter != iter_fence) {
  Branch (225:16): [True: 3.41M, False: 309k]
226
            // convert value
227
3.41M
            intern_json((const JsonbValue*)iter);
228
3.41M
            ++iter;
229
3.41M
            if (iter != iter_fence) {
  Branch (229:17): [True: 3.10M, False: 309k]
230
3.10M
                os_.put(',');
231
3.10M
            }
232
3.41M
        }
233
234
309k
        assert(iter == iter_fence);
235
236
0
        os_.put(']');
237
309k
    }
238
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
using JsonbValueCreater = JsonbValueCreaterT<JsonbOutStream>;
298
} // namespace doris
299
300
#endif // JSONB_JSONBUTIL_H