-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
Copy pathjson_renderer.hpp
162 lines (128 loc) · 4 KB
/
json_renderer.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// based on
// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
#ifndef JSON_RENDERER_HPP
#define JSON_RENDERER_HPP
#include "util/string_util.hpp"
#include "osrm/json_container.hpp"
#include <iterator>
#include <ostream>
#include <string>
#include <vector>
#include <boost/assert.hpp>
#include <fmt/compile.h>
namespace osrm::util::json
{
template <typename Out> struct Renderer
{
explicit Renderer(Out &_out) : out(_out) {}
void operator()(const String &string)
{
write('"');
// here we assume that vast majority of strings don't need to be escaped,
// so we check it first and escape only if needed
if (RequiresJSONStringEscaping(string.value))
{
std::string escaped;
// just a guess that 16 bytes for escaped characters will be enough to avoid
// reallocations
escaped.reserve(string.value.size() + 16);
EscapeJSONString(string.value, escaped);
write(escaped);
}
else
{
write(string.value);
}
write('"');
}
void operator()(const Number &number)
{
// we don't want to print NaN or Infinity
BOOST_ASSERT(std::isfinite(number.value));
// `fmt::memory_buffer` stores first 500 bytes in the object itself(i.e. on stack in this
// case) and then grows using heap if needed
fmt::memory_buffer buffer;
fmt::format_to(std::back_inserter(buffer), FMT_COMPILE("{:.12g}"), number.value);
write(buffer.data(), buffer.size());
}
void operator()(const Object &object)
{
write('{');
for (auto it = object.values.begin(), end = object.values.end(); it != end;)
{
write('\"');
write(it->first);
write<>("\":");
std::visit(Renderer(out), it->second);
if (++it != end)
{
write(',');
}
}
write('}');
}
void operator()(const Array &array)
{
write('[');
for (auto it = array.values.cbegin(), end = array.values.cend(); it != end;)
{
std::visit(Renderer(out), *it);
if (++it != end)
{
write(',');
}
}
write(']');
}
void operator()(const True &) { write<>("true"); }
void operator()(const False &) { write<>("false"); }
void operator()(const Null &) { write<>("null"); }
private:
void write(std::string_view str);
void write(const char *str, size_t size);
void write(char ch);
template <size_t StrLength> void write(const char (&str)[StrLength])
{
write(str, StrLength - 1);
}
private:
Out &out;
};
template <> void Renderer<std::vector<char>>::write(std::string_view str)
{
out.insert(out.end(), str.begin(), str.end());
}
template <> void Renderer<std::vector<char>>::write(const char *str, size_t size)
{
out.insert(out.end(), str, str + size);
}
template <> void Renderer<std::vector<char>>::write(char ch) { out.push_back(ch); }
template <> void Renderer<std::ostream>::write(std::string_view str) { out << str; }
template <> void Renderer<std::ostream>::write(const char *str, size_t size)
{
out.write(str, size);
}
template <> void Renderer<std::ostream>::write(char ch) { out << ch; }
template <> void Renderer<std::string>::write(std::string_view str) { out += str; }
template <> void Renderer<std::string>::write(const char *str, size_t size)
{
out.append(str, size);
}
template <> void Renderer<std::string>::write(char ch) { out += ch; }
inline void render(std::ostream &out, const Object &object)
{
Renderer renderer(out);
renderer(object);
}
inline void render(std::string &out, const Object &object)
{
Renderer renderer(out);
renderer(object);
}
inline void render(std::vector<char> &out, const Object &object)
{
Renderer renderer(out);
renderer(object);
}
} // namespace osrm::util::json
#endif // JSON_RENDERER_HPP