
This gives a small but noticeable compile time improvement as well as a measurable, albeit not great, reduction in size of the stdlib.
151 lines
3.9 KiB
C++
151 lines
3.9 KiB
C++
#ifndef CHAISCRIPT_SIMPLEJSON_WRAP_HPP
|
|
#define CHAISCRIPT_SIMPLEJSON_WRAP_HPP
|
|
|
|
#include "json.hpp"
|
|
|
|
namespace chaiscript
|
|
{
|
|
class json_wrap
|
|
{
|
|
public:
|
|
|
|
static Module& library(Module& m)
|
|
{
|
|
|
|
m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
|
m.add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
static Boxed_Value from_json(const json::JSON &t_json)
|
|
{
|
|
switch( t_json.JSONType() ) {
|
|
case json::JSON::Class::Null:
|
|
return Boxed_Value();
|
|
case json::JSON::Class::Object:
|
|
{
|
|
std::map<std::string, Boxed_Value> m;
|
|
|
|
for (const auto &p : t_json.object_range())
|
|
{
|
|
m.insert(std::make_pair(p.first, from_json(p.second)));
|
|
}
|
|
|
|
return Boxed_Value(m);
|
|
}
|
|
case json::JSON::Class::Array:
|
|
{
|
|
std::vector<Boxed_Value> vec;
|
|
|
|
for (const auto &p : t_json.array_range())
|
|
{
|
|
vec.emplace_back(from_json(p));
|
|
}
|
|
|
|
return Boxed_Value(vec);
|
|
}
|
|
case json::JSON::Class::String:
|
|
return Boxed_Value(t_json.to_string());
|
|
case json::JSON::Class::Floating:
|
|
return Boxed_Value(t_json.to_float());
|
|
case json::JSON::Class::Integral:
|
|
return Boxed_Value(t_json.to_int());
|
|
case json::JSON::Class::Boolean:
|
|
return Boxed_Value(t_json.to_bool());
|
|
}
|
|
|
|
throw std::runtime_error("Unknown JSON type");
|
|
}
|
|
|
|
static Boxed_Value from_json(const std::string &t_json)
|
|
{
|
|
return from_json( json::JSON::Load(t_json) );
|
|
}
|
|
|
|
static std::string to_json(const Boxed_Value &t_bv)
|
|
{
|
|
return to_json_object(t_bv).dump();
|
|
}
|
|
|
|
static json::JSON to_json_object(const Boxed_Value &t_bv)
|
|
{
|
|
try {
|
|
const std::map<std::string, Boxed_Value> m = chaiscript::boxed_cast<const std::map<std::string, Boxed_Value> &>(t_bv);
|
|
|
|
json::JSON obj;
|
|
for (const auto &o : m)
|
|
{
|
|
obj[o.first] = to_json_object(o.second);
|
|
}
|
|
return obj;
|
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
// not a map
|
|
}
|
|
|
|
try {
|
|
const std::vector<Boxed_Value> v = chaiscript::boxed_cast<const std::vector<Boxed_Value> &>(t_bv);
|
|
|
|
json::JSON obj;
|
|
for (size_t i = 0; i < v.size(); ++i)
|
|
{
|
|
obj[i] = to_json_object(v[i]);
|
|
}
|
|
return obj;
|
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
// not a vector
|
|
}
|
|
|
|
|
|
try {
|
|
Boxed_Number bn(t_bv);
|
|
if (Boxed_Number::is_floating_point(t_bv))
|
|
{
|
|
return json::JSON(bn.get_as<double>());
|
|
} else {
|
|
return json::JSON(bn.get_as<long>());
|
|
}
|
|
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
|
// not a number
|
|
}
|
|
|
|
try {
|
|
return json::JSON(boxed_cast<bool>(t_bv));
|
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
// not a bool
|
|
}
|
|
|
|
try {
|
|
return json::JSON(boxed_cast<std::string>(t_bv));
|
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
// not a string
|
|
}
|
|
|
|
|
|
try {
|
|
const chaiscript::dispatch::Dynamic_Object &o = boxed_cast<const dispatch::Dynamic_Object &>(t_bv);
|
|
|
|
json::JSON obj;
|
|
for (const auto &attr : o.get_attrs())
|
|
{
|
|
obj[attr.first] = to_json_object(attr.second);
|
|
}
|
|
return obj;
|
|
} catch (const chaiscript::exception::bad_boxed_cast &) {
|
|
// not a dynamic object
|
|
}
|
|
|
|
throw std::runtime_error("Unknown object type to convert to JSON");
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
#endif
|