Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/graphite/src/json.cpp
9903 views
1
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
2
// Copyright 2011, SIL International, All rights reserved.
3
4
// JSON debug logging
5
// Author: Tim Eves
6
7
#if !defined GRAPHITE2_NTRACING
8
9
#include <cstdio>
10
#include <limits>
11
#include "inc/json.h"
12
13
#if defined(_MSC_VER)
14
#define FORMAT_INTMAX "%lli"
15
#define FORMAT_UINTMAX "%llu"
16
#else
17
#define FORMAT_INTMAX "%ji"
18
#define FORMAT_UINTMAX "%ju"
19
#endif
20
21
using namespace graphite2;
22
23
namespace
24
{
25
enum
26
{
27
seq = ',',
28
obj='}', member=':', empty_obj='{',
29
arr=']', empty_arr='['
30
};
31
}
32
33
const std::nullptr_t json::null = nullptr;
34
35
inline
36
void json::context(const char current) throw()
37
{
38
fprintf(_stream, "%c", *_context);
39
indent();
40
*_context = current;
41
}
42
43
44
void json::indent(const int d) throw()
45
{
46
if (*_context == member || (_flatten && _flatten < _context))
47
fputc(' ', _stream);
48
else
49
fprintf(_stream, "\n%*s", 4*int(_context - _contexts + d), "");
50
}
51
52
53
inline
54
void json::push_context(const char prefix, const char suffix) throw()
55
{
56
assert(_context - _contexts < ptrdiff_t(sizeof _contexts));
57
58
if (_context == _contexts)
59
*_context = suffix;
60
else
61
context(suffix);
62
*++_context = prefix;
63
}
64
65
66
void json::pop_context() throw()
67
{
68
assert(_context > _contexts);
69
70
if (*_context == seq) indent(-1);
71
else fputc(*_context, _stream);
72
73
fputc(*--_context, _stream);
74
if (_context == _contexts) fputc('\n', _stream);
75
fflush(_stream);
76
77
if (_flatten >= _context) _flatten = 0;
78
*_context = seq;
79
}
80
81
82
// These four functions cannot be inlined as pointers to these
83
// functions are needed for operator << (_context_t) to work.
84
void json::flat(json & j) throw() { if (!j._flatten) j._flatten = j._context; }
85
void json::close(json & j) throw() { j.pop_context(); }
86
void json::object(json & j) throw() { j.push_context('{', '}'); }
87
void json::array(json & j) throw() { j.push_context('[', ']'); }
88
void json::item(json & j) throw()
89
{
90
while (j._context > j._contexts+1 && j._context[-1] != arr)
91
j.pop_context();
92
}
93
94
95
json & json::operator << (json::string s) throw()
96
{
97
const char ctxt = _context[-1] == obj ? *_context == member ? seq : member : seq;
98
context(ctxt);
99
fprintf(_stream, "\"%s\"", s);
100
if (ctxt == member) fputc(' ', _stream);
101
102
return *this;
103
}
104
105
json & json::operator << (json::number f) throw()
106
{
107
context(seq);
108
if (std::numeric_limits<json::number>::infinity() == f)
109
fputs("Infinity", _stream);
110
else if (-std::numeric_limits<json::number>::infinity() == f)
111
fputs("-Infinity", _stream);
112
else if (std::numeric_limits<json::number>::quiet_NaN() == f ||
113
std::numeric_limits<json::number>::signaling_NaN() == f)
114
fputs("NaN", _stream);
115
else
116
fprintf(_stream, "%g", f);
117
return *this;
118
}
119
json & json::operator << (json::integer d) throw() { context(seq); fprintf(_stream, FORMAT_INTMAX, intmax_t(d)); return *this; }
120
json & json::operator << (json::integer_u d) throw() { context(seq); fprintf(_stream, FORMAT_UINTMAX, uintmax_t(d)); return *this; }
121
json & json::operator << (json::boolean b) throw() { context(seq); fputs(b ? "true" : "false", _stream); return *this; }
122
json & json::operator << (std::nullptr_t) throw() { context(seq); fputs("null",_stream); return *this; }
123
124
#endif
125
126