Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarJsonBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/StarJsonBuilder.cpp')
-rw-r--r--source/core/StarJsonBuilder.cpp168
1 files changed, 168 insertions, 0 deletions
diff --git a/source/core/StarJsonBuilder.cpp b/source/core/StarJsonBuilder.cpp
new file mode 100644
index 0000000..432cef9
--- /dev/null
+++ b/source/core/StarJsonBuilder.cpp
@@ -0,0 +1,168 @@
+#include "StarJsonBuilder.hpp"
+#include "StarLexicalCast.hpp"
+
+namespace Star {
+
+void JsonBuilderStream::beginObject() {
+ pushSentry();
+}
+
+void JsonBuilderStream::objectKey(char32_t const* s, size_t len) {
+ push(Json(s, len));
+}
+
+void JsonBuilderStream::endObject() {
+ JsonObject object;
+ while (true) {
+ if (isSentry()) {
+ set(Json(move(object)));
+ return;
+ } else {
+ Json v = pop();
+ String k = pop().toString();
+ if (!object.insert(k, move(v)).second)
+ throw JsonParsingException(strf("Json object contains a duplicate entry for key '%s'", k));
+ }
+ }
+}
+
+void JsonBuilderStream::beginArray() {
+ pushSentry();
+}
+
+void JsonBuilderStream::endArray() {
+ JsonArray array;
+ while (true) {
+ if (isSentry()) {
+ array.reverse();
+ set(Json(move(array)));
+ return;
+ } else {
+ array.append(pop());
+ }
+ }
+}
+
+void JsonBuilderStream::putString(char32_t const* s, size_t len) {
+ push(Json(s, len));
+}
+
+void JsonBuilderStream::putDouble(char32_t const* s, size_t len) {
+ push(Json(lexicalCast<double>(String(s, len))));
+}
+
+void JsonBuilderStream::putInteger(char32_t const* s, size_t len) {
+ push(Json(lexicalCast<long long>(String(s, len))));
+}
+
+void JsonBuilderStream::putBoolean(bool b) {
+ push(Json(b));
+}
+
+void JsonBuilderStream::putNull() {
+ push(Json());
+}
+
+void JsonBuilderStream::putWhitespace(char32_t const*, size_t) {}
+
+void JsonBuilderStream::putColon() {}
+
+void JsonBuilderStream::putComma() {}
+
+size_t JsonBuilderStream::stackSize() {
+ return m_stack.size();
+}
+
+Json JsonBuilderStream::takeTop() {
+ if (m_stack.size())
+ return m_stack.takeLast().take();
+ else
+ return Json();
+}
+
+void JsonBuilderStream::push(Json v) {
+ m_stack.append(move(v));
+}
+
+Json JsonBuilderStream::pop() {
+ return m_stack.takeLast().take();
+}
+
+void JsonBuilderStream::set(Json v) {
+ m_stack.last() = move(v);
+}
+
+void JsonBuilderStream::pushSentry() {
+ m_stack.append({});
+}
+
+bool JsonBuilderStream::isSentry() {
+ return !m_stack.empty() && !m_stack.last();
+}
+
+void JsonStreamer<Json>::toJsonStream(Json const& val, JsonStream& stream, bool sort) {
+ Json::Type type = val.type();
+ if (type == Json::Type::Null) {
+ stream.putNull();
+ } else if (type == Json::Type::Float) {
+ auto d = String(toString(val.toDouble())).wideString();
+ stream.putDouble(d.c_str(), d.length());
+ } else if (type == Json::Type::Bool) {
+ stream.putBoolean(val.toBool());
+ } else if (type == Json::Type::Int) {
+ auto i = String(toString(val.toInt())).wideString();
+ stream.putInteger(i.c_str(), i.length());
+ } else if (type == Json::Type::String) {
+ auto ws = val.toString().wideString();
+ stream.putString(ws.c_str(), ws.length());
+ } else if (type == Json::Type::Array) {
+ stream.beginArray();
+ bool first = true;
+ for (auto const& elem : val.iterateArray()) {
+ if (!first)
+ stream.putComma();
+ first = false;
+ toJsonStream(elem, stream, sort);
+ }
+ stream.endArray();
+ } else if (type == Json::Type::Object) {
+ stream.beginObject();
+ List<String::Char> chars;
+ if (sort) {
+ auto objectPtr = val.objectPtr();
+ List<JsonObject::const_iterator> iterators;
+ iterators.reserve(objectPtr->size());
+ for (auto i = objectPtr->begin(); i != objectPtr->end(); ++i)
+ iterators.append(i);
+ iterators.sort([](JsonObject::const_iterator a, JsonObject::const_iterator b) {
+ return a->first < b->first;
+ });
+ bool first = true;
+ for (auto const& i : iterators) {
+ if (!first)
+ stream.putComma();
+ first = false;
+ chars.clear();
+ for (auto const& c : i->first)
+ chars.push_back(c);
+ stream.objectKey(chars.ptr(), chars.size());
+ stream.putColon();
+ toJsonStream(i->second, stream, sort);
+ }
+ } else {
+ bool first = true;
+ for (auto const& pair : val.iterateObject()) {
+ if (!first)
+ stream.putComma();
+ first = false;
+ auto ws = pair.first.wideString();
+ stream.objectKey(ws.c_str(), ws.length());
+ stream.putColon();
+ toJsonStream(pair.second, stream, sort);
+ }
+ }
+ stream.endObject();
+ }
+}
+
+}