Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Analysis/src/JsonEmitter.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "Luau/JsonEmitter.h"
3
4
#include "Luau/StringUtils.h"
5
6
#include <string.h>
7
8
namespace Luau::Json
9
{
10
11
static constexpr int CHUNK_SIZE = 1024;
12
13
ObjectEmitter::ObjectEmitter(NotNull<JsonEmitter> emitter)
14
: emitter(emitter)
15
, finished(false)
16
{
17
comma = emitter->pushComma();
18
emitter->writeRaw('{');
19
}
20
21
ObjectEmitter::~ObjectEmitter()
22
{
23
finish();
24
}
25
26
void ObjectEmitter::finish()
27
{
28
if (finished)
29
return;
30
31
emitter->writeRaw('}');
32
emitter->popComma(comma);
33
finished = true;
34
}
35
36
ArrayEmitter::ArrayEmitter(NotNull<JsonEmitter> emitter)
37
: emitter(emitter)
38
, finished(false)
39
{
40
comma = emitter->pushComma();
41
emitter->writeRaw('[');
42
}
43
44
ArrayEmitter::~ArrayEmitter()
45
{
46
finish();
47
}
48
49
void ArrayEmitter::finish()
50
{
51
if (finished)
52
return;
53
54
emitter->writeRaw(']');
55
emitter->popComma(comma);
56
finished = true;
57
}
58
59
JsonEmitter::JsonEmitter()
60
{
61
newChunk();
62
}
63
64
std::string JsonEmitter::str()
65
{
66
return join(chunks, "");
67
}
68
69
bool JsonEmitter::pushComma()
70
{
71
bool current = comma;
72
comma = false;
73
return current;
74
}
75
76
void JsonEmitter::popComma(bool c)
77
{
78
comma = c;
79
}
80
81
void JsonEmitter::writeRaw(std::string_view sv)
82
{
83
if (sv.size() > CHUNK_SIZE)
84
{
85
chunks.emplace_back(sv);
86
newChunk();
87
return;
88
}
89
90
auto& chunk = chunks.back();
91
if (chunk.size() + sv.size() < CHUNK_SIZE)
92
{
93
chunk.append(sv.data(), sv.size());
94
return;
95
}
96
97
size_t prefix = CHUNK_SIZE - chunk.size();
98
chunk.append(sv.data(), prefix);
99
newChunk();
100
101
chunks.back().append(sv.data() + prefix, sv.size() - prefix);
102
}
103
104
void JsonEmitter::writeRaw(char c)
105
{
106
writeRaw(std::string_view{&c, 1});
107
}
108
109
void write(JsonEmitter& emitter, bool b)
110
{
111
if (b)
112
emitter.writeRaw("true");
113
else
114
emitter.writeRaw("false");
115
}
116
117
void write(JsonEmitter& emitter, double d)
118
{
119
emitter.writeRaw(std::to_string(d));
120
}
121
122
void write(JsonEmitter& emitter, int i)
123
{
124
emitter.writeRaw(std::to_string(i));
125
}
126
127
void write(JsonEmitter& emitter, long i)
128
{
129
emitter.writeRaw(std::to_string(i));
130
}
131
132
void write(JsonEmitter& emitter, long long i)
133
{
134
emitter.writeRaw(std::to_string(i));
135
}
136
137
void write(JsonEmitter& emitter, unsigned int i)
138
{
139
emitter.writeRaw(std::to_string(i));
140
}
141
142
void write(JsonEmitter& emitter, unsigned long i)
143
{
144
emitter.writeRaw(std::to_string(i));
145
}
146
147
void write(JsonEmitter& emitter, unsigned long long i)
148
{
149
emitter.writeRaw(std::to_string(i));
150
}
151
152
void write(JsonEmitter& emitter, std::string_view sv)
153
{
154
emitter.writeRaw('\"');
155
156
for (char c : sv)
157
{
158
if (c == '"')
159
emitter.writeRaw("\\\"");
160
else if (c == '\\')
161
emitter.writeRaw("\\\\");
162
else if (c == '\n')
163
emitter.writeRaw("\\n");
164
else if (c < ' ')
165
emitter.writeRaw(format("\\u%04x", c));
166
else
167
emitter.writeRaw(c);
168
}
169
170
emitter.writeRaw('\"');
171
}
172
173
void write(JsonEmitter& emitter, char c)
174
{
175
write(emitter, std::string_view{&c, 1});
176
}
177
178
void write(JsonEmitter& emitter, const char* str)
179
{
180
write(emitter, std::string_view{str, strlen(str)});
181
}
182
183
void write(JsonEmitter& emitter, const std::string& str)
184
{
185
write(emitter, std::string_view{str});
186
}
187
188
void write(JsonEmitter& emitter, std::nullptr_t)
189
{
190
emitter.writeRaw("null");
191
}
192
193
void write(JsonEmitter& emitter, std::nullopt_t)
194
{
195
emitter.writeRaw("null");
196
}
197
198
void JsonEmitter::writeComma()
199
{
200
if (comma)
201
writeRaw(',');
202
else
203
comma = true;
204
}
205
206
ObjectEmitter JsonEmitter::writeObject()
207
{
208
return ObjectEmitter{NotNull(this)};
209
}
210
211
ArrayEmitter JsonEmitter::writeArray()
212
{
213
return ArrayEmitter{NotNull(this)};
214
}
215
216
void JsonEmitter::newChunk()
217
{
218
chunks.emplace_back();
219
chunks.back().reserve(CHUNK_SIZE);
220
}
221
222
} // namespace Luau::Json
223
224