• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / github_pull_request_281750

30 Oct 2023 03:37PM UTC coverage: 90.528% (-1.0%) from 91.571%
github_pull_request_281750

Pull #6073

Evergreen

jedelbo
Log free space and history sizes when opening file
Pull Request #6073: Merge next-major

95488 of 175952 branches covered (0.0%)

8973 of 12277 new or added lines in 149 files covered. (73.09%)

622 existing lines in 51 files now uncovered.

233503 of 257934 relevant lines covered (90.53%)

6533720.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.06
/src/realm/to_json.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2016 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#include <realm/group.hpp>
20
#include <realm/dictionary.hpp>
21
#include <realm/list.hpp>
22
#include <realm/set.hpp>
23
#include <external/json/json.hpp>
24
#include "realm/util/base64.hpp"
25

26
namespace realm {
27

28
void Group::schema_to_json(std::ostream& out, std::map<std::string, std::string>* opt_renames) const
29
{
6✔
30
    check_attached();
6✔
31

3✔
32
    std::map<std::string, std::string> renames;
6✔
33
    if (opt_renames) {
6✔
NEW
34
        renames = *opt_renames;
×
NEW
35
    }
×
36

3✔
37
    out << "[" << std::endl;
6✔
38

3✔
39
    auto keys = get_table_keys();
6✔
40
    int sz = int(keys.size());
6✔
41
    for (int i = 0; i < sz; ++i) {
18✔
42
        auto key = keys[i];
12✔
43
        ConstTableRef table = get_table(key);
12✔
44

6✔
45
        table->schema_to_json(out, renames);
12✔
46
        if (i < sz - 1)
12✔
47
            out << ",";
6✔
48
        out << std::endl;
12✔
49
    }
12✔
50

3✔
51
    out << "]" << std::endl;
6✔
52
}
6✔
53

54
void Group::to_json(std::ostream& out, size_t link_depth, std::map<std::string, std::string>* opt_renames,
55
                    JSONOutputMode output_mode) const
56
{
18✔
57
    check_attached();
18✔
58

9✔
59
    std::map<std::string, std::string> renames;
18✔
60
    if (opt_renames) {
18✔
NEW
61
        renames = *opt_renames;
×
NEW
62
    }
×
63

9✔
64
    out << "{" << std::endl;
18✔
65

9✔
66
    auto keys = get_table_keys();
18✔
67
    bool first = true;
18✔
68
    for (size_t i = 0; i < keys.size(); ++i) {
36✔
69
        auto key = keys[i];
18✔
70
        StringData name = get_table_name(key);
18✔
71
        if (renames[name] != "")
18✔
NEW
72
            name = renames[name];
×
73

9✔
74
        ConstTableRef table = get_table(key);
18✔
75

9✔
76
        if (!table->is_embedded()) {
18✔
77
            if (!first)
18✔
NEW
78
                out << ",";
×
79
            out << "\"" << name << "\"";
18✔
80
            out << ":";
18✔
81
            table->to_json(out, link_depth, renames, output_mode);
18✔
82
            out << std::endl;
18✔
83
            first = false;
18✔
84
        }
18✔
85
    }
18✔
86

9✔
87
    out << "}" << std::endl;
18✔
88
}
18✔
89

90
void Table::to_json(std::ostream& out, size_t link_depth, const std::map<std::string, std::string>& renames,
91
                    JSONOutputMode output_mode) const
92
{
294✔
93
    // Represent table as list of objects
147✔
94
    out << "[";
294✔
95
    bool first = true;
294✔
96

147✔
97
    for (auto& obj : *this) {
906✔
98
        if (first) {
906✔
99
            first = false;
294✔
100
        }
294✔
101
        else {
612✔
102
            out << ",";
612✔
103
        }
612✔
104
        obj.to_json(out, link_depth, renames, output_mode);
906✔
105
    }
906✔
106

147✔
107
    out << "]";
294✔
108
}
294✔
109

110
using Json = nlohmann::json;
111

112
template <typename T>
113
void Dictionary::insert_json(const std::string& key, const T& value)
114
{
48✔
115
    const Json& j = value;
48✔
116
    switch (j.type()) {
48✔
NEW
117
        case Json::value_t::null:
✔
NEW
118
            insert(key, Mixed());
×
NEW
119
            break;
×
120
        case Json::value_t::string:
12✔
121
            insert(key, j.get<std::string>());
12✔
122
            break;
12✔
NEW
123
        case Json::value_t::boolean:
✔
NEW
124
            insert(key, j.get<bool>());
×
NEW
125
            break;
×
126
        case Json::value_t::number_integer:
12✔
127
        case Json::value_t::number_unsigned:
24✔
128
            insert(key, j.get<int64_t>());
24✔
129
            break;
24✔
130
        case Json::value_t::number_float:
12✔
NEW
131
            insert(key, j.get<double>());
×
NEW
132
            break;
×
133
        case Json::value_t::object: {
12✔
NEW
134
            insert_collection(key, CollectionType::Dictionary);
×
NEW
135
            auto dict = get_dictionary(key);
×
NEW
136
            for (auto [k, v] : j.items()) {
×
NEW
137
                dict->insert_json(k, v);
×
NEW
138
            }
×
NEW
139
            break;
×
140
        }
12✔
141
        case Json::value_t::array: {
18✔
142
            insert_collection(key, CollectionType::List);
12✔
143
            auto list = get_list(key);
12✔
144
            for (auto&& elem : value) {
36✔
145
                list->add_json(elem);
36✔
146
            }
36✔
147
            break;
12✔
148
        }
12✔
149
        case Json::value_t::binary:
12✔
NEW
150
        case Json::value_t::discarded:
✔
NEW
151
            REALM_TERMINATE("should never see discarded or binary");
×
152
    }
48✔
153
}
48✔
154

155
template <typename T>
156
void Lst<Mixed>::add_json(const T& value)
157
{
72✔
158
    const Json& j = value;
72✔
159
    size_t sz = size();
72✔
160
    switch (j.type()) {
72✔
NEW
161
        case Json::value_t::null:
✔
NEW
162
            insert(sz, Mixed());
×
NEW
163
            break;
×
164
        case Json::value_t::string:
12✔
165
            insert(sz, j.get<std::string>());
12✔
166
            break;
12✔
NEW
167
        case Json::value_t::boolean:
✔
NEW
168
            insert(sz, j.get<bool>());
×
NEW
169
            break;
×
NEW
170
        case Json::value_t::number_integer:
✔
NEW
171
        case Json::value_t::number_unsigned:
✔
NEW
172
            insert(sz, j.get<int64_t>());
×
NEW
173
            break;
×
174
        case Json::value_t::number_float:
36✔
175
            insert(sz, j.get<double>());
36✔
176
            break;
36✔
177
        case Json::value_t::object: {
24✔
178
            insert_collection(sz, CollectionType::Dictionary);
24✔
179
            auto dict = get_dictionary(sz);
24✔
180
            for (auto [k, v] : j.items()) {
48✔
181
                dict->insert_json(k, v);
48✔
182
            }
48✔
183
            break;
24✔
NEW
184
        }
×
NEW
185
        case Json::value_t::array: {
✔
NEW
186
            insert_collection(sz, CollectionType::List);
×
NEW
187
            auto list = get_list(sz);
×
NEW
188
            for (auto&& elem : j) {
×
NEW
189
                list->add_json(elem);
×
NEW
190
            }
×
NEW
191
            break;
×
NEW
192
        }
×
NEW
193
        case Json::value_t::binary:
✔
NEW
194
        case Json::value_t::discarded:
✔
NEW
195
            REALM_TERMINATE("should never see discarded or binary");
×
196
    }
72✔
197
}
72✔
198

199
Obj& Obj::set_json(ColKey col_key, StringData json)
200
{
12✔
201
    auto j = Json::parse(std::string_view(json.data(), json.size()), nullptr, false);
12✔
202
    switch (j.type()) {
12✔
NEW
203
        case Json::value_t::null:
✔
NEW
204
            set(col_key, Mixed());
×
NEW
205
            break;
×
NEW
206
        case Json::value_t::string:
✔
NEW
207
            set(col_key, Mixed(j.get<std::string>()));
×
NEW
208
            break;
×
NEW
209
        case Json::value_t::boolean:
✔
NEW
210
            set(col_key, Mixed(j.get<bool>()));
×
NEW
211
            break;
×
NEW
212
        case Json::value_t::number_integer:
✔
NEW
213
        case Json::value_t::number_unsigned:
✔
NEW
214
            set(col_key, Mixed(j.get<int64_t>()));
×
NEW
215
            break;
×
NEW
216
        case Json::value_t::number_float:
✔
NEW
217
            set(col_key, Mixed(j.get<double>()));
×
NEW
218
            break;
×
NEW
219
        case Json::value_t::object: {
✔
NEW
220
            set_collection(col_key, CollectionType::Dictionary);
×
NEW
221
            Dictionary dict(*this, col_key);
×
NEW
222
            for (auto [k, v] : j.items()) {
×
NEW
223
                dict.insert_json(k, v);
×
NEW
224
            }
×
NEW
225
            break;
×
NEW
226
        }
×
227
        case Json::value_t::array: {
12✔
228
            set_collection(col_key, CollectionType::List);
12✔
229
            Lst<Mixed> list(*this, col_key);
12✔
230
            list.clear();
12✔
231
            for (auto&& elem : j) {
36✔
232
                list.add_json(elem);
36✔
233
            }
36✔
234
        } break;
12✔
NEW
235
        case Json::value_t::binary:
✔
236
            // Parser will never return binary
NEW
237
        case Json::value_t::discarded:
✔
NEW
238
            throw InvalidArgument(ErrorCodes::MalformedJson, "Illegal json");
×
239
    }
12✔
240

6✔
241
    return *this;
12✔
242
}
12✔
243

244
void Obj::to_json(std::ostream& out, size_t link_depth, const std::map<std::string, std::string>& renames,
245
                  std::vector<ObjLink>& followed, JSONOutputMode output_mode) const
246
{
1,848✔
247
    followed.push_back(get_link());
1,848✔
248
    size_t new_depth = link_depth == not_found ? not_found : link_depth - 1;
1,707✔
249
    StringData name = "_key";
1,848✔
250
    bool prefixComma = false;
1,848✔
251
    if (renames.count(name))
1,848✔
NEW
252
        name = renames.at(name);
×
253
    out << "{";
1,848✔
254
    if (output_mode == output_mode_json) {
1,848✔
255
        prefixComma = true;
1,320✔
256
        out << "\"" << name << "\":" << this->m_key.value;
1,320✔
257
    }
1,320✔
258

924✔
259
    auto col_keys = m_table->get_column_keys();
1,848✔
260
    for (auto ck : col_keys) {
8,826✔
261
        name = m_table->get_column_name(ck);
8,826✔
262
        auto type = ck.get_type();
8,826✔
263
        if (type == col_type_LinkList)
8,826✔
264
            type = col_type_Link;
408✔
265
        if (renames.count(name))
8,826✔
266
            name = renames.at(name);
162✔
267

4,413✔
268
        if (prefixComma)
8,826✔
269
            out << ",";
8,298✔
270
        out << "\"" << name << "\":";
8,826✔
271
        prefixComma = true;
8,826✔
272

4,413✔
273
        TableRef target_table;
8,826✔
274
        ColKey pk_col_key;
8,826✔
275
        if (type == col_type_Link) {
8,826✔
276
            target_table = get_target_table(ck);
1,380✔
277
            pk_col_key = target_table->get_primary_key_column();
1,380✔
278
        }
1,380✔
279

4,413✔
280
        auto print_link = [&](const Mixed& val) {
5,058✔
281
            REALM_ASSERT(val.is_type(type_Link, type_TypedLink));
1,290✔
282
            TableRef tt = target_table;
1,290✔
283
            auto obj_key = val.get<ObjKey>();
1,290✔
284
            std::string table_info;
1,290✔
285
            std::string table_info_close;
1,290✔
286
            if (!tt) {
1,290✔
287
                // It must be a typed link
63✔
288
                tt = m_table->get_parent_group()->get_table(val.get_link().get_table_key());
126✔
289
                pk_col_key = tt->get_primary_key_column();
126✔
290
                if (output_mode == output_mode_xjson_plus) {
126✔
291
                    table_info = std::string("{ \"$link\": ");
30✔
292
                    table_info_close = " }";
30✔
293
                }
30✔
294

63✔
295
                table_info += std::string("{ \"table\": \"") + std::string(tt->get_name()) + "\", \"key\": ";
126✔
296
                table_info_close += " }";
126✔
297
            }
126✔
298
            if (pk_col_key && output_mode != output_mode_json) {
1,290✔
299
                out << table_info;
312✔
300
                tt->get_primary_key(obj_key).to_json(out, output_mode_xjson);
312✔
301
                out << table_info_close;
312✔
302
            }
312✔
303
            else {
978✔
304
                ObjLink link(tt->get_key(), obj_key);
978✔
305
                if (obj_key.is_unresolved()) {
978✔
NEW
306
                    out << "null";
×
NEW
307
                    return;
×
NEW
308
                }
×
309
                if (!tt->is_embedded()) {
978✔
310
                    if (link_depth == 0) {
906✔
311
                        out << table_info << obj_key.value << table_info_close;
522✔
312
                        return;
522✔
313
                    }
522✔
314
                    if ((link_depth == realm::npos &&
384✔
315
                         std::find(followed.begin(), followed.end(), link) != followed.end())) {
273✔
316
                        // We have detected a cycle in links
9✔
317
                        out << "{ \"table\": \"" << tt->get_name() << "\", \"key\": " << obj_key.value << " }";
18✔
318
                        return;
18✔
319
                    }
18✔
320
                }
438✔
321

219✔
322
                tt->get_object(obj_key).to_json(out, new_depth, renames, followed, output_mode);
438✔
323
            }
438✔
324
        };
1,290✔
325

4,413✔
326
        if (ck.is_collection()) {
8,826✔
327
            auto collection = get_collection_ptr(ck);
1,770✔
328
            collection->to_json(out, link_depth, output_mode, print_link);
1,770✔
329
        }
1,770✔
330
        else {
7,056✔
331
            auto val = get_any(ck);
7,056✔
332
            if (!val.is_null()) {
7,056✔
333
                if (type == col_type_Link) {
6,570✔
334
                    std::string close_string;
576✔
335
                    bool is_embedded = target_table->is_embedded();
576✔
336
                    bool link_depth_reached = !is_embedded && (link_depth == 0);
576✔
337

288✔
338
                    if (output_mode == output_mode_xjson_plus) {
576✔
339
                        out << "{ " << (is_embedded ? "\"$embedded" : "\"$link") << "\": ";
21✔
340
                        close_string += "}";
24✔
341
                    }
24✔
342
                    if ((link_depth_reached && output_mode == output_mode_json) ||
576✔
343
                        output_mode == output_mode_xjson_plus) {
486✔
344
                        out << "{ \"table\": \"" << target_table->get_name() << "\", "
396✔
345
                            << (is_embedded ? "\"value" : "\"key") << "\": ";
393✔
346
                        close_string += "}";
396✔
347
                    }
396✔
348

288✔
349
                    print_link(val);
576✔
350
                    out << close_string;
576✔
351
                }
576✔
352
                else if (val.is_type(type_TypedLink)) {
5,994✔
353
                    print_link(val);
24✔
354
                }
24✔
355
                else if (val.is_type(type_Dictionary)) {
5,970✔
356
                    DummyParent parent(m_table, val.get_ref());
12✔
357
                    Dictionary dict(parent, 0);
12✔
358
                    dict.to_json(out, link_depth, output_mode, print_link);
12✔
359
                }
12✔
360
                else if (val.is_type(type_Set)) {
5,958✔
361
                    DummyParent parent(this->get_table(), val.get_ref());
12✔
362
                    Set<Mixed> set(parent, 0);
12✔
363
                    set.to_json(out, link_depth, output_mode, print_link);
12✔
364
                }
12✔
365
                else if (val.is_type(type_List)) {
5,946✔
366
                    DummyParent parent(m_table, val.get_ref());
18✔
367
                    Lst<Mixed> list(parent, 0);
18✔
368
                    list.to_json(out, link_depth, output_mode, print_link);
18✔
369
                }
18✔
370
                else {
5,928✔
371
                    val.to_json(out, output_mode);
5,928✔
372
                }
5,928✔
373
            }
6,570✔
374
            else {
486✔
375
                out << "null";
486✔
376
            }
486✔
377
        }
7,056✔
378
    }
8,826✔
379
    out << "}";
1,848✔
380
    followed.pop_back();
1,848✔
381
}
1,848✔
382

383
namespace {
384
const char to_be_escaped[] = "\"\n\r\t\f\\\b";
385
const char encoding[] = "\"nrtf\\b";
386

387
template <class T>
388
inline void out_floats(std::ostream& out, T value)
389
{
540✔
390
    std::streamsize old = out.precision();
540✔
391
    out.precision(std::numeric_limits<T>::digits10 + 1);
540✔
392
    out << std::scientific << value;
540✔
393
    out.precision(old);
540✔
394
}
540✔
395

396
void out_string(std::ostream& out, std::string str)
397
{
2,928✔
398
    size_t p = str.find_first_of(to_be_escaped);
2,928✔
399
    while (p != std::string::npos) {
2,970✔
400
        char c = str[p];
42✔
401
        auto found = strchr(to_be_escaped, c);
42✔
402
        REALM_ASSERT(found);
42✔
403
        out << str.substr(0, p) << '\\' << encoding[found - to_be_escaped];
42✔
404
        str = str.substr(p + 1);
42✔
405
        p = str.find_first_of(to_be_escaped);
42✔
406
    }
42✔
407
    out << str;
2,928✔
408
}
2,928✔
409

410
void out_binary(std::ostream& out, BinaryData bin)
411
{
270✔
412
    const char* start = bin.data();
270✔
413
    const size_t len = bin.size();
270✔
414
    std::string encode_buffer;
270✔
415
    encode_buffer.resize(util::base64_encoded_size(len));
270✔
416
    util::base64_encode(start, len, encode_buffer.data(), encode_buffer.size());
270✔
417
    out << encode_buffer;
270✔
418
}
270✔
419
} // anonymous namespace
420

421

422
void Mixed::to_xjson(std::ostream& out) const noexcept
423
{
4,410✔
424
    switch (get_type()) {
4,410✔
425
        case type_Int:
1,320✔
426
            out << "{\"$numberLong\": \"";
1,320✔
427
            out << int_val;
1,320✔
428
            out << "\"}";
1,320✔
429
            break;
1,320✔
430
        case type_Bool:
180✔
431
            out << (bool_val ? "true" : "false");
138✔
432
            break;
180✔
433
        case type_Float:
180✔
434
            out << "{\"$numberDouble\": \"";
180✔
435
            out_floats<float>(out, float_val);
180✔
436
            out << "\"}";
180✔
437
            break;
180✔
438
        case type_Double:
180✔
439
            out << "{\"$numberDouble\": \"";
180✔
440
            out_floats<double>(out, double_val);
180✔
441
            out << "\"}";
180✔
442
            break;
180✔
443
        case type_String: {
1,644✔
444
            out << "\"";
1,644✔
445
            out_string(out, string_val);
1,644✔
446
            out << "\"";
1,644✔
447
            break;
1,644✔
NEW
448
        }
×
449
        case type_Binary: {
180✔
450
            out << "{\"$binary\": {\"base64\": \"";
180✔
451
            out_binary(out, binary_val);
180✔
452
            out << "\", \"subType\": \"00\"}}";
180✔
453
            break;
180✔
NEW
454
        }
×
455
        case type_Timestamp: {
186✔
456
            out << "{\"$date\": {\"$numberLong\": \"";
186✔
457
            int64_t timeMillis = date_val.get_seconds() * 1000 + date_val.get_nanoseconds() / 1000000;
186✔
458
            out << timeMillis;
186✔
459
            out << "\"}}";
186✔
460
            break;
186✔
NEW
461
        }
×
462
        case type_Decimal:
180✔
463
            out << "{\"$numberDecimal\": \"";
180✔
464
            out << decimal_val;
180✔
465
            out << "\"}";
180✔
466
            break;
180✔
467
        case type_ObjectId:
180✔
468
            out << "{\"$oid\": \"";
180✔
469
            out << id_val;
180✔
470
            out << "\"}";
180✔
471
            break;
180✔
472
        case type_UUID:
180✔
473
            out << "{\"$binary\": {\"base64\": \"";
180✔
474
            out << uuid_val.to_base64();
180✔
475
            out << "\", \"subType\": \"04\"}}";
180✔
476
            break;
180✔
477

NEW
478
        case type_TypedLink: {
✔
NEW
479
            Mixed val(get<ObjLink>().get_obj_key());
×
NEW
480
            val.to_xjson(out);
×
NEW
481
            break;
×
NEW
482
        }
×
NEW
483
        case type_Link:
✔
NEW
484
        case type_LinkList:
✔
NEW
485
        case type_Mixed:
✔
NEW
486
            break;
×
487
    }
4,410✔
488
}
4,410✔
489

490
void Mixed::to_xjson_plus(std::ostream& out) const noexcept
491
{
2,082✔
492

1,041✔
493
    // Special case for outputing a typedLink, otherwise just us out_mixed_xjson
1,041✔
494
    if (is_type(type_TypedLink)) {
2,082✔
NEW
495
        auto link = get<ObjLink>();
×
NEW
496
        out << "{ \"$link\": { \"table\": \"" << link.get_table_key() << "\", \"key\": ";
×
NEW
497
        Mixed val(link.get_obj_key());
×
NEW
498
        val.to_xjson(out);
×
NEW
499
        out << "}}";
×
NEW
500
        return;
×
NEW
501
    }
×
502

1,041✔
503
    to_xjson(out);
2,082✔
504
}
2,082✔
505

506
void Mixed::to_json(std::ostream& out, JSONOutputMode output_mode) const noexcept
507
{
8,118✔
508
    if (is_null()) {
8,118✔
509
        out << "null";
72✔
510
        return;
72✔
511
    }
72✔
512
    switch (output_mode) {
8,046✔
513
        case output_mode_xjson: {
2,328✔
514
            to_xjson(out);
2,328✔
515
            return;
2,328✔
NEW
516
        }
×
517
        case output_mode_xjson_plus: {
2,082✔
518
            to_xjson_plus(out);
2,082✔
519
            return;
2,082✔
NEW
520
        }
×
521
        case output_mode_json: {
3,636✔
522
            switch (get_type()) {
3,636✔
523
                case type_Int:
1,284✔
524
                    out << int_val;
1,284✔
525
                    break;
1,284✔
526
                case type_Bool:
108✔
527
                    out << (bool_val ? "true" : "false");
81✔
528
                    break;
108✔
529
                case type_Float:
90✔
530
                    out_floats<float>(out, float_val);
90✔
531
                    break;
90✔
532
                case type_Double:
90✔
533
                    out_floats<double>(out, double_val);
90✔
534
                    break;
90✔
535
                case type_String: {
1,284✔
536
                    out << "\"";
1,284✔
537
                    out_string(out, string_val);
1,284✔
538
                    out << "\"";
1,284✔
539
                    break;
1,284✔
NEW
540
                }
×
541
                case type_Binary: {
90✔
542
                    out << "\"";
90✔
543
                    out_binary(out, binary_val);
90✔
544
                    out << "\"";
90✔
545
                    break;
90✔
NEW
546
                }
×
547
                case type_Timestamp:
96✔
548
                    out << "\"";
96✔
549
                    out << date_val;
96✔
550
                    out << "\"";
96✔
551
                    break;
96✔
552
                case type_Decimal:
90✔
553
                    out << "\"";
90✔
554
                    out << decimal_val;
90✔
555
                    out << "\"";
90✔
556
                    break;
90✔
557
                case type_ObjectId:
414✔
558
                    out << "\"";
414✔
559
                    out << id_val;
414✔
560
                    out << "\"";
414✔
561
                    break;
414✔
562
                case type_UUID:
90✔
563
                    out << "\"";
90✔
564
                    out << uuid_val;
90✔
565
                    out << "\"";
90✔
566
                    break;
90✔
NEW
567
                case type_TypedLink:
✔
NEW
568
                    out << "\"";
×
NEW
569
                    out << link_val;
×
NEW
570
                    out << "\"";
×
NEW
571
                    break;
×
NEW
572
                case type_Link:
✔
NEW
573
                case type_LinkList:
✔
NEW
574
                case type_Mixed:
✔
NEW
575
                    break;
×
576
            }
3,636✔
577
        }
3,636✔
578
    }
8,046✔
579
}
8,046✔
580

581
} // namespace realm
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc