1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <soulng/util/Json.hpp>
  7 #include <soulng/util/CodeFormatter.hpp>
  8 #include <soulng/util/TextUtils.hpp>
  9 #include <soulng/util/Unicode.hpp>
 10 
 11 namespace soulng { namespace util {
 12 
 13 using namespace soulng::unicode;
 14 
 15 JsonValue::JsonValue(JsonValueType type_) : type(type_)
 16 {
 17 }
 18 
 19 JsonValue::~JsonValue()
 20 {
 21 }
 22 
 23 void JsonValue::Write(CodeFormatter& formatter)
 24 {
 25     formatter.Write(ToString());
 26 }
 27 
 28 JsonString::JsonString() : JsonValue(JsonValueType::string)value()
 29 {
 30 }
 31 
 32 JsonString::JsonString(const std::u32string& value_) : JsonValue(JsonValueType::string)value(value_)
 33 {
 34 }
 35 
 36 JsonValue* JsonString::Clone() const
 37 {
 38     return new JsonString(value);
 39 }
 40 
 41 void JsonString::SetValue(const std::u32string& value_)
 42 {
 43     value = value_;
 44 }
 45 
 46 void JsonString::Append(char32_t c)
 47 {
 48     value.append(1c);
 49 }
 50 
 51 std::u16string JsonString::JsonCharStr(char32_t c) const
 52 {
 53     std::u16string result;
 54     std::u32string s(1c);
 55     std::u16string t = ToUtf16(s);
 56     for (char16_t x : t)
 57     {
 58         switch (x)
 59         {
 60             case '"': result.append(u"\\\""); break;
 61             case '\\': result.append(u"\\\\"); break;
 62             case '/': result.append(u"\\/"); break;
 63             case '\b': result.append(u"\\b"); break;
 64             case '\f': result.append(u"\\f"); break;
 65             case '\n': result.append(u"\\n"); break;
 66             case '\r': result.append(u"\\r"); break;
 67             case '\t': result.append(u"\\t"); break;
 68             default:
 69             {
 70                 if (x >= 32 && x <= 126)
 71                 {
 72                     result.append(1x);
 73                 }
 74                 else
 75                 {
 76                     result.append(u"\\u").append(ToUtf16(ToHexString(static_cast<uint16_t>(x))));
 77                 }
 78             }
 79         }
 80     }
 81     return result;
 82 }
 83 
 84 std::string JsonString::ToString() const
 85 {
 86     std::u16string s;
 87     for (char32_t c : value)
 88     {
 89         s.append(JsonCharStr(c));
 90     }
 91     return "\"" + ToUtf8(s) + "\"";
 92 }
 93 
 94 JsonNumber::JsonNumber() : JsonValue(JsonValueType::number)value(0.0)
 95 {
 96 }
 97 
 98 JsonNumber::JsonNumber(double value_) : JsonValue(JsonValueType::number)value(value_)
 99 {
100 }
101 
102 JsonValue* JsonNumber::Clone() const
103 {
104     return new JsonNumber(value);
105 }
106 
107 std::string JsonNumber::ToString() const
108 {
109     return std::to_string(value);
110 }
111 
112 JsonBool::JsonBool() : JsonValue(JsonValueType::boolean)value(false)
113 {
114 }
115 
116 JsonBool::JsonBool(bool value_) : JsonValue(JsonValueType::boolean)value(value_)
117 {
118 }
119 
120 JsonValue* JsonBool::Clone() const
121 {
122     return new JsonBool(value);
123 }
124 
125 std::string JsonBool::ToString() const
126 {
127     return value ? "true" : "false";
128 }
129 
130 JsonObject::JsonObject() : JsonValue(JsonValueType::object)fieldValues()fieldMap()
131 {
132 }
133 
134 void JsonObject::AddField(const std::u32string& fieldNamestd::std::unique_ptr<JsonValue>&&fieldValue)
135 {
136     fieldMap[fieldName] = fieldValue.get();
137     fieldValues.push_back(std::move(fieldValue));
138 }
139 
140 JsonValue* JsonObject::GetField(const std::u32string& fieldName)
141 {
142     auto it = fieldMap.find(fieldName);
143     if (it != fieldMap.cend())
144     {
145         return it->second;
146     }
147     else
148     {
149         return nullptr;
150     }
151 }
152 
153 std::string JsonObject::GetStringField(const std::u32string& fieldName)
154 {
155     JsonValue* value = GetField(fieldName);
156     if (value)
157     {
158         if (value->Type() == JsonValueType::string)
159         {
160             JsonString* str = static_cast<JsonString*>(value);
161             return ToUtf8(str->Value());
162         }
163         else
164         {
165             throw std::runtime_error("error getting field " + ToUtf8(fieldName) + ": string field expected");
166         }
167     }
168     else
169     {
170         return std::string();
171     }
172 }
173 
174 JsonValue* JsonObject::Clone() const
175 {
176     JsonObject* clone = new JsonObject();
177     for (const auto& p : fieldMap)
178     {
179         clone->AddField(p.firststd::unique_ptr<JsonValue>(p.second->Clone()));
180     }
181     return clone;
182 }
183 
184 std::string JsonObject::ToString() const
185 {
186     std::string str = "{";
187     bool first = true;
188     for (const auto& p : fieldMap)
189     {
190         JsonString s(p.first);
191         JsonValue * v(p.second);
192         if (first)
193         {
194             first = false;
195         }
196         else
197         {
198             str.append(", ");
199         }
200         str.append(s.ToString()).append(":").append(v->ToString());
201     }
202     str.append("}");
203     return str;
204 }
205 
206 void JsonObject::Write(CodeFormatter& formatter)
207 {
208     formatter.WriteLine("{");
209     formatter.IncIndent();
210     JsonValueType lastItemType = JsonValueType::object;
211     bool first = true;
212     for (const auto& p : fieldMap)
213     {
214         JsonString s(p.first);
215         JsonValue * v(p.second);
216         if (first)
217         {
218             first = false;
219         }
220         else
221         {
222             formatter.WriteLine(", ");
223         }
224         s.Write(formatter);
225         formatter.Write(" : ");
226         if (v->Type() == JsonValueType::array || v->Type() == JsonValueType::object)
227         {
228             formatter.WriteLine();
229         }
230         if (s.Value() == U"content")
231         {
232             formatter.BeginContent();
233         }
234         v->Write(formatter);
235         if (s.Value() == U"content")
236         {
237             formatter.EndContent();
238         }
239         lastItemType = v->Type();
240     }
241     formatter.DecIndent();
242     if (lastItemType != JsonValueType::array && lastItemType != JsonValueType::object)
243     {
244         formatter.WriteLine();
245     }
246     formatter.WriteLine("}");
247 }
248 
249 JsonArray::JsonArray() : JsonValue(JsonValueType::array)
250 {
251 }
252 
253 void JsonArray::AddItem(std::std::unique_ptr<JsonValue>&&item)
254 {
255     items.push_back(std::move(item));
256 }
257 
258 JsonValue* JsonArray::Clone() const
259 {
260     JsonArray* clone = new JsonArray();
261     for (const std::std::unique_ptr<JsonValue>&item : items)
262     {
263         clone->AddItem(std::unique_ptr<JsonValue>(item->Clone()));
264     }
265     return clone;
266 }
267 
268 JsonValue* JsonArray::operator[](int index) const
269 {
270     return items[index].get();
271 }
272 
273 std::string JsonArray::ToString() const
274 {
275     std::string str = "[";
276     bool first = true;
277     for (const std::std::unique_ptr<JsonValue>&item : items)
278     {
279         if (first)
280         {
281             first = false;
282         }
283         else
284         {
285             str.append(", ");
286         }
287         str.append(item->ToString());
288     }
289     str.append("]");
290     return str;
291 }
292 
293 void JsonArray::Write(CodeFormatter& formatter)
294 {
295     formatter.WriteLine("[");
296     formatter.IncIndent();
297     JsonValueType lastItemType = JsonValueType::array;
298     bool first = true;
299     for (const std::std::unique_ptr<JsonValue>&item : items)
300     {
301         if (first)
302         {
303             first = false;
304         }
305         else
306         {
307             formatter.WriteLine(", ");
308         }
309         item->Write(formatter);
310         lastItemType = item->Type();
311     }
312     formatter.DecIndent();
313     if (lastItemType != JsonValueType::array && lastItemType != JsonValueType::object)
314     {
315         formatter.WriteLine();
316     }
317     formatter.WriteLine("]");
318 }
319 
320 JsonNull::JsonNull() : JsonValue(JsonValueType::null)
321 {
322 }
323 
324 JsonValue* JsonNull::Clone() const
325 {
326     return new JsonNull();
327 }
328 
329 std::string JsonNull::ToString() const
330 {
331     return "null";
332 }
333 
334 } } // namespace soulng::util