aboutsummaryrefslogtreecommitdiff
path: root/3rdparty/imgui-node-editor/crude_json.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/imgui-node-editor/crude_json.cpp')
-rw-r--r--3rdparty/imgui-node-editor/crude_json.cpp890
1 files changed, 0 insertions, 890 deletions
diff --git a/3rdparty/imgui-node-editor/crude_json.cpp b/3rdparty/imgui-node-editor/crude_json.cpp
deleted file mode 100644
index a9f7c70..0000000
--- a/3rdparty/imgui-node-editor/crude_json.cpp
+++ /dev/null
@@ -1,890 +0,0 @@
-// Crude implementation of JSON value object and parser.
-//
-// VERSION 0.1
-//
-// LICENSE
-// This software is dual-licensed to the public domain and under the following
-// license: you are granted a perpetual, irrevocable license to copy, modify,
-// publish, and distribute this file as you see fit.
-//
-// CREDITS
-// Written by Michal Cichon
-# include "crude_json.h"
-# include <iomanip>
-# include <limits>
-# include <cstdlib>
-# include <clocale>
-# include <cmath>
-# include <cstring>
-# if CRUDE_JSON_IO
-# include <stdio.h>
-# include <memory>
-# endif
-
-namespace crude_json {
-
-value::value(value&& other)
- : m_Type(other.m_Type)
-{
- switch (m_Type)
- {
- case type_t::object: construct(m_Storage, std::move( *object_ptr(other.m_Storage))); break;
- case type_t::array: construct(m_Storage, std::move( *array_ptr(other.m_Storage))); break;
- case type_t::string: construct(m_Storage, std::move( *string_ptr(other.m_Storage))); break;
- case type_t::boolean: construct(m_Storage, std::move(*boolean_ptr(other.m_Storage))); break;
- case type_t::number: construct(m_Storage, std::move( *number_ptr(other.m_Storage))); break;
- default: break;
- }
- destruct(other.m_Storage, other.m_Type);
- other.m_Type = type_t::null;
-}
-
-value::value(const value& other)
- : m_Type(other.m_Type)
-{
- switch (m_Type)
- {
- case type_t::object: construct(m_Storage, *object_ptr(other.m_Storage)); break;
- case type_t::array: construct(m_Storage, *array_ptr(other.m_Storage)); break;
- case type_t::string: construct(m_Storage, *string_ptr(other.m_Storage)); break;
- case type_t::boolean: construct(m_Storage, *boolean_ptr(other.m_Storage)); break;
- case type_t::number: construct(m_Storage, *number_ptr(other.m_Storage)); break;
- default: break;
- }
-}
-
-value& value::operator[](size_t index)
-{
- if (is_null())
- m_Type = construct(m_Storage, type_t::array);
-
- if (is_array())
- {
- auto& v = *array_ptr(m_Storage);
- if (index >= v.size())
- v.insert(v.end(), index - v.size() + 1, value());
-
- return v[index];
- }
-
- CRUDE_ASSERT(false && "operator[] on unsupported type");
- std::terminate();
-}
-
-const value& value::operator[](size_t index) const
-{
- if (is_array())
- return (*array_ptr(m_Storage))[index];
-
- CRUDE_ASSERT(false && "operator[] on unsupported type");
- std::terminate();
-}
-
-value& value::operator[](const string& key)
-{
- if (is_null())
- m_Type = construct(m_Storage, type_t::object);
-
- if (is_object())
- return (*object_ptr(m_Storage))[key];
-
- CRUDE_ASSERT(false && "operator[] on unsupported type");
- std::terminate();
-}
-
-const value& value::operator[](const string& key) const
-{
- if (is_object())
- {
- auto& o = *object_ptr(m_Storage);
- auto it = o.find(key);
- CRUDE_ASSERT(it != o.end());
- return it->second;
- }
-
- CRUDE_ASSERT(false && "operator[] on unsupported type");
- std::terminate();
-}
-
-bool value::contains(const string& key) const
-{
- if (is_object())
- {
- auto& o = *object_ptr(m_Storage);
- auto it = o.find(key);
- return it != o.end();
- }
-
- return false;
-}
-
-void value::push_back(const value& value)
-{
- if (is_null())
- m_Type = construct(m_Storage, type_t::array);
-
- if (is_array())
- {
- auto& v = *array_ptr(m_Storage);
- v.push_back(value);
- }
- else
- {
- CRUDE_ASSERT(false && "operator[] on unsupported type");
- std::terminate();
- }
-}
-
-void value::push_back(value&& value)
-{
- if (is_null())
- m_Type = construct(m_Storage, type_t::array);
-
- if (is_array())
- {
- auto& v = *array_ptr(m_Storage);
- v.push_back(std::move(value));
- }
- else
- {
- CRUDE_ASSERT(false && "operator[] on unsupported type");
- std::terminate();
- }
-}
-
-size_t value::erase(const string& key)
-{
- if (!is_object())
- return 0;
-
- auto& o = *object_ptr(m_Storage);
- auto it = o.find(key);
-
- if (it == o.end())
- return 0;
-
- o.erase(it);
-
- return 1;
-}
-
-void value::swap(value& other)
-{
- using std::swap;
-
- if (m_Type == other.m_Type)
- {
- switch (m_Type)
- {
- case type_t::object: swap(*object_ptr(m_Storage), *object_ptr(other.m_Storage)); break;
- case type_t::array: swap(*array_ptr(m_Storage), *array_ptr(other.m_Storage)); break;
- case type_t::string: swap(*string_ptr(m_Storage), *string_ptr(other.m_Storage)); break;
- case type_t::boolean: swap(*boolean_ptr(m_Storage), *boolean_ptr(other.m_Storage)); break;
- case type_t::number: swap(*number_ptr(m_Storage), *number_ptr(other.m_Storage)); break;
- default: break;
- }
- }
- else
- {
- value tmp(std::move(other));
- other.~value();
- new (&other) value(std::move(*this));
- this->~value();
- new (this) value(std::move(tmp));
- }
-}
-
-string value::dump(const int indent, const char indent_char) const
-{
- dump_context_t context(indent, indent_char);
-
- context.out.precision(std::numeric_limits<double>::max_digits10 + 1);
- context.out << std::defaultfloat;
-
- dump(context, 0);
- return context.out.str();
-}
-
-void value::dump_context_t::write_indent(int level)
-{
- if (indent <= 0 || level == 0)
- return;
-
- out.fill(indent_char);
- out.width(indent * level);
- out << indent_char;
- out.width(0);
-}
-
-void value::dump_context_t::write_separator()
-{
- if (indent < 0)
- return;
-
- out.put(' ');
-}
-
-void value::dump_context_t::write_newline()
-{
- if (indent < 0)
- return;
-
- out.put('\n');
-}
-
-void value::dump(dump_context_t& context, int level) const
-{
- context.write_indent(level);
-
- switch (m_Type)
- {
- case type_t::null:
- context.out << "null";
- break;
-
- case type_t::object:
- context.out << '{';
- {
- context.write_newline();
- bool first = true;
- for (auto& entry : *object_ptr(m_Storage))
- {
- if (!first) { context.out << ','; context.write_newline(); } else first = false;
- context.write_indent(level + 1);
- context.out << '\"' << entry.first << "\":";
- if (!entry.second.is_structured())
- {
- context.write_separator();
- entry.second.dump(context, 0);
- }
- else
- {
- context.write_newline();
- entry.second.dump(context, level + 1);
- }
- }
- if (!first)
- context.write_newline();
- }
- context.write_indent(level);
- context.out << '}';
- break;
-
- case type_t::array:
- context.out << '[';
- {
- context.write_newline();
- bool first = true;
- for (auto& entry : *array_ptr(m_Storage))
- {
- if (!first) { context.out << ','; context.write_newline(); } else first = false;
- if (!entry.is_structured())
- {
- context.write_indent(level + 1);
- entry.dump(context, 0);
- }
- else
- {
- entry.dump(context, level + 1);
- }
- }
- if (!first)
- context.write_newline();
- }
- context.write_indent(level);
- context.out << ']';
- break;
-
- case type_t::string:
- context.out << '\"';
-
- if (string_ptr(m_Storage)->find_first_of("\"\\/\b\f\n\r") != string::npos || string_ptr(m_Storage)->find('\0') != string::npos)
- {
- for (auto c : *string_ptr(m_Storage))
- {
- if (c == '\"') context.out << "\\\"";
- else if (c == '\\') context.out << "\\\\";
- else if (c == '/') context.out << "\\/";
- else if (c == '\b') context.out << "\\b";
- else if (c == '\f') context.out << "\\f";
- else if (c == '\n') context.out << "\\n";
- else if (c == '\r') context.out << "\\r";
- else if (c == '\t') context.out << "\\t";
- else if (c == 0) context.out << "\\u0000";
- else context.out << c;
- }
- }
- else
- context.out << *string_ptr(m_Storage);
- context.out << '\"';
- break;
-
-
- case type_t::boolean:
- if (*boolean_ptr(m_Storage))
- context.out << "true";
- else
- context.out << "false";
- break;
-
- case type_t::number:
- context.out << *number_ptr(m_Storage);
- break;
-
- default:
- break;
- }
-}
-
-struct value::parser
-{
- parser(const char* begin, const char* end)
- : m_Cursor(begin)
- , m_End(end)
- {
- }
-
- value parse()
- {
- value v;
-
- // Switch to C locale to make strtod and strtol work as expected
- auto previous_locale = std::setlocale(LC_NUMERIC, "C");
-
- // Accept single value only when end of the stream is reached.
- if (!accept_element(v) || !eof())
- v = value(type_t::discarded);
-
- if (previous_locale && strcmp(previous_locale, "C") != 0)
- std::setlocale(LC_NUMERIC, previous_locale);
-
- return v;
- }
-
-private:
- struct cursor_state
- {
- cursor_state(parser* p)
- : m_Owner(p)
- , m_LastCursor(p->m_Cursor)
- {
- }
-
- void reset()
- {
- m_Owner->m_Cursor = m_LastCursor;
- }
-
- bool operator()(bool accept)
- {
- if (!accept)
- reset();
- else
- m_LastCursor = m_Owner->m_Cursor;
- return accept;
- }
-
- private:
- parser* m_Owner;
- const char* m_LastCursor;
- };
-
- cursor_state state()
- {
- return cursor_state(this);
- }
-
- bool accept_value(value& result)
- {
- return accept_object(result)
- || accept_array(result)
- || accept_string(result)
- || accept_number(result)
- || accept_boolean(result)
- || accept_null(result);
- }
-
- bool accept_object(value& result)
- {
- auto s = state();
-
- object o;
- if (s(accept('{') && accept_ws() && accept('}')))
- {
- result = o;
- return true;
- }
- else if (s(accept('{') && accept_members(o) && accept('}')))
- {
- result = std::move(o);
- return true;
- }
-
- return false;
- }
-
- bool accept_members(object& o)
- {
- if (!accept_member(o))
- return false;
-
- while (true)
- {
- auto s = state();
- if (!s(accept(',') && accept_member(o)))
- break;
- }
-
- return true;
- }
-
- bool accept_member(object& o)
- {
- auto s = state();
-
- value key;
- value v;
- if (s(accept_ws() && accept_string(key) && accept_ws() && accept(':') && accept_element(v)))
- {
- o.emplace(std::move(key.get<string>()), std::move(v));
- return true;
- }
-
- return false;
- }
-
- bool accept_array(value& result)
- {
- auto s = state();
-
- if (s(accept('[') && accept_ws() && accept(']')))
- {
- result = array();
- return true;
- }
-
- array a;
- if (s(accept('[') && accept_elements(a) && accept(']')))
- {
- result = std::move(a);
- return true;
- }
-
- return false;
- }
-
- bool accept_elements(array& a)
- {
- value v;
- if (!accept_element(v))
- return false;
-
- a.emplace_back(std::move(v));
- while (true)
- {
- auto s = state();
- v = nullptr;
- if (!s(accept(',') && accept_element(v)))
- break;
- a.emplace_back(std::move(v));
- }
-
- return true;
- }
-
- bool accept_element(value& result)
- {
- auto s = state();
- return s(accept_ws() && accept_value(result) && accept_ws());
- }
-
- bool accept_string(value& result)
- {
- auto s = state();
-
- string v;
- if (s(accept('\"') && accept_characters(v) && accept('\"')))
- {
- result = std::move(v);
- return true;
- }
- else
- return false;
- }
-
- bool accept_characters(string& result)
- {
- int c;
- while (accept_character(c))
- {
- CRUDE_ASSERT(c < 128); // #todo: convert characters > 127 to UTF-8
- result.push_back(static_cast<char>(c));
- }
-
- return true;
- }
-
- bool accept_character(int& c)
- {
- auto s = state();
-
- if (accept('\\'))
- {
- return accept_escape(c);
- }
- else if (expect('\"'))
- return false;
-
- // #todo: Handle UTF-8 sequences.
- return s((c = peek()) >= 0) && advance();
- }
-
- bool accept_escape(int& c)
- {
- if (accept('\"')) { c = '\"'; return true; }
- if (accept('\\')) { c = '\\'; return true; }
- if (accept('/')) { c = '/'; return true; }
- if (accept('b')) { c = '\b'; return true; }
- if (accept('f')) { c = '\f'; return true; }
- if (accept('n')) { c = '\n'; return true; }
- if (accept('r')) { c = '\r'; return true; }
- if (accept('t')) { c = '\t'; return true; }
-
- auto s = state();
-
- string hex;
- hex.reserve(4);
- if (s(accept('u') && accept_hex(hex) && accept_hex(hex) && accept_hex(hex) && accept_hex(hex)))
- {
- char* end = nullptr;
- auto v = std::strtol(hex.c_str(), &end, 16);
- if (end != hex.c_str() + hex.size())
- return false;
-
- c = v;
- return true;
- }
-
- return false;
- }
-
- bool accept_hex(string& result)
- {
- if (accept_digit(result))
- return true;
-
- auto c = peek();
- if ((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
- {
- advance();
- result.push_back(static_cast<char>(c));
- return true;
- }
-
- return false;
- }
-
- bool accept_number(value& result)
- {
- auto s = state();
-
- string n;
- if (s(accept_int(n) && accept_frac(n) && accept_exp(n)))
- {
- char* end = nullptr;
- auto v = std::strtod(n.c_str(), &end);
- if (end != n.c_str() + n.size())
- return false;
-
- if (v != 0 && !std::isnormal(v))
- return false;
-
- result = v;
- return true;
- }
-
- return false;
- }
-
- bool accept_int(string& result)
- {
- auto s = state();
-
- string part;
- if (s(accept_onenine(part) && accept_digits(part)))
- {
- result += std::move(part);
- return true;
- }
-
- part.resize(0);
- if (accept_digit(part))
- {
- result += std::move(part);
- return true;
- }
-
- part.resize(0);
- if (s(accept('-') && accept_onenine(part) && accept_digits(part)))
- {
- result += '-';
- result += std::move(part);
- return true;
- }
-
- part.resize(0);
- if (s(accept('-') && accept_digit(part)))
- {
- result += '-';
- result += std::move(part);
- return true;
- }
-
- return false;
- }
-
- bool accept_digits(string& result)
- {
- string part;
- if (!accept_digit(part))
- return false;
-
- while (accept_digit(part))
- ;
-
- result += std::move(part);
-
- return true;
- }
-
- bool accept_digit(string& result)
- {
- if (accept('0'))
- {
- result.push_back('0');
- return true;
- }
- else if (accept_onenine(result))
- return true;
-
- return false;
- }
-
- bool accept_onenine(string& result)
- {
- auto c = peek();
- if (c >= '1' && c <= '9')
- {
- result.push_back(static_cast<char>(c));
- return advance();
- }
-
- return false;
- }
-
- bool accept_frac(string& result)
- {
- auto s = state();
-
- string part;
- if (s(accept('.') && accept_digits(part)))
- {
- result += '.';
- result += std::move(part);
- }
-
- return true;
- }
-
- bool accept_exp(string& result)
- {
- auto s = state();
-
- string part;
- if (s(accept('e') && accept_sign(part) && accept_digits(part)))
- {
- result += 'e';
- result += std::move(part);
- return true;
- }
- part.resize(0);
- if (s(accept('E') && accept_sign(part) && accept_digits(part)))
- {
- result += 'E';
- result += std::move(part);
- }
-
- return true;
- }
-
- bool accept_sign(string& result)
- {
- if (accept('+'))
- result.push_back('+');
- else if (accept('-'))
- result.push_back('-');
-
- return true;
- }
-
- bool accept_ws()
- {
- while (expect('\x09') || expect('\x0A') || expect('\x0D') || expect('\x20'))
- advance();
- return true;
- }
-
- bool accept_boolean(value& result)
- {
- if (accept("true"))
- {
- result = true;
- return true;
- }
- else if (accept("false"))
- {
- result = false;
- return true;
- }
-
- return false;
- }
-
- bool accept_null(value& result)
- {
- if (accept("null"))
- {
- result = nullptr;
- return true;
- }
-
- return false;
- }
-
- bool accept(char c)
- {
- if (expect(c))
- return advance();
- else
- return false;
- }
-
- bool accept(const char* str)
- {
- auto last = m_Cursor;
-
- while (*str)
- {
- if (eof() || *str != *m_Cursor)
- {
- m_Cursor = last;
- return false;
- }
-
- advance();
- ++str;
- }
-
- return true;
- }
-
- int peek() const
- {
- if (!eof())
- return *m_Cursor;
- else
- return -1;
- }
-
- bool expect(char c)
- {
- return peek() == c;
- }
-
- bool advance(int count = 1)
- {
- if (m_Cursor + count > m_End)
- {
- m_Cursor = m_End;
- return false;
- }
-
- m_Cursor += count;
-
- return true;
- }
-
- bool eof() const
- {
- return m_Cursor == m_End;
- }
-
- const char* m_Cursor;
- const char* m_End;
-};
-
-value value::parse(const string& data)
-{
- auto p = parser(data.c_str(), data.c_str() + data.size());
-
- auto v = p.parse();
-
- return v;
-}
-
-# if CRUDE_JSON_IO
-std::pair<value, bool> value::load(const string& path)
-{
- // Modern C++, so beautiful...
- std::unique_ptr<FILE, void(*)(FILE*)> file{nullptr, [](FILE* file) { if (file) fclose(file); }};
-# if defined(_MSC_VER) || (defined(__STDC_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__)
- FILE* handle = nullptr;
- if (fopen_s(&handle, path.c_str(), "rb") != 0)
- return {value{}, false};
- file.reset(handle);
-# else
- file.reset(fopen(path.c_str(), "rb"));
-# endif
-
- if (!file)
- return {value{}, false};
-
- fseek(file.get(), 0, SEEK_END);
- auto size = static_cast<size_t>(ftell(file.get()));
- fseek(file.get(), 0, SEEK_SET);
-
- string data;
- data.resize(size);
- if (fread(const_cast<char*>(data.data()), size, 1, file.get()) != 1)
- return {value{}, false};
-
- return {parse(data), true};
-}
-
-bool value::save(const string& path, const int indent, const char indent_char) const
-{
- // Modern C++, so beautiful...
- std::unique_ptr<FILE, void(*)(FILE*)> file{nullptr, [](FILE* file) { if (file) fclose(file); }};
-# if defined(_MSC_VER) || (defined(__STDC_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__)
- FILE* handle = nullptr;
- if (fopen_s(&handle, path.c_str(), "wb") != 0)
- return false;
- file.reset(handle);
-# else
- file.reset(fopen(path.c_str(), "wb"));
-# endif
-
- if (!file)
- return false;
-
- auto data = dump(indent, indent_char);
-
- if (fwrite(data.data(), data.size(), 1, file.get()) != 1)
- return false;
-
- return true;
-}
-
-# endif
-
-} // namespace crude_json