2020-11-26 23:28:50 +01:00
|
|
|
/* Copyright (C) 2020 Wildfire Games.
|
2011-05-29 17:02:02 +02:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "AtlasObject.h"
|
|
|
|
#include "AtlasObjectImpl.h"
|
|
|
|
|
2013-12-06 01:42:50 +01:00
|
|
|
#if defined(_MSC_VER)
|
|
|
|
# pragma warning(disable:4996) // deprecated CRT
|
2020-11-26 23:28:50 +01:00
|
|
|
# pragma warning(disable: 4459) // global declaration hidden
|
2013-12-06 01:42:50 +01:00
|
|
|
#endif
|
2012-01-04 14:19:38 +01:00
|
|
|
|
2020-11-26 23:28:50 +01:00
|
|
|
#include "JSONSpiritInclude.h"
|
|
|
|
|
2011-05-29 17:02:02 +02:00
|
|
|
#include <sstream>
|
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
static AtSmartPtr<AtNode> ConvertNode(json_spirit::Value node);
|
2011-05-29 17:02:02 +02:00
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
AtObj AtlasObject::LoadFromJSON(const std::string& json)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Value rootnode;
|
|
|
|
json_spirit::read_string(json, rootnode);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
AtObj obj;
|
2019-04-05 14:37:37 +02:00
|
|
|
obj.m_Node = ConvertNode(rootnode);
|
2014-02-24 21:22:02 +01:00
|
|
|
return obj;
|
|
|
|
}
|
2011-05-29 17:02:02 +02:00
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
// Convert from a JSON to an AtNode
|
|
|
|
static AtSmartPtr<AtNode> ConvertNode(json_spirit::Value node)
|
|
|
|
{
|
|
|
|
AtSmartPtr<AtNode> obj (new AtNode());
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
if (node.type() == json_spirit::str_type)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-06-03 22:19:53 +02:00
|
|
|
obj->m_Value = node.get_str();
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
2014-02-24 21:22:02 +01:00
|
|
|
else if (node.type() == json_spirit::int_type || node.type() == json_spirit::real_type)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-06-03 22:19:53 +02:00
|
|
|
std::stringstream stream;
|
2014-02-24 21:22:02 +01:00
|
|
|
if (node.type() == json_spirit::int_type)
|
|
|
|
stream << node.get_int();
|
|
|
|
if (node.type() == json_spirit::real_type)
|
|
|
|
stream << node.get_real();
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2019-04-05 14:37:37 +02:00
|
|
|
obj->m_Value = stream.str().c_str();
|
|
|
|
obj->m_Children.insert(AtNode::child_pairtype(
|
2014-02-24 21:22:02 +01:00
|
|
|
"@number", AtSmartPtr<AtNode>(new AtNode())
|
|
|
|
));
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
2014-02-24 21:22:02 +01:00
|
|
|
else if (node.type() == json_spirit::bool_type)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-06-03 22:19:53 +02:00
|
|
|
obj->m_Value = node.get_bool() ? "true" : "false";
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2019-04-05 14:37:37 +02:00
|
|
|
obj->m_Children.insert(AtNode::child_pairtype(
|
2014-02-24 21:22:02 +01:00
|
|
|
"@boolean", AtSmartPtr<AtNode>(new AtNode())
|
|
|
|
));
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
2014-02-24 21:22:02 +01:00
|
|
|
else if (node.type() == json_spirit::array_type)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-04-05 14:37:37 +02:00
|
|
|
obj->m_Children.insert(AtNode::child_pairtype(
|
2014-02-24 21:22:02 +01:00
|
|
|
"@array", AtSmartPtr<AtNode>(new AtNode())
|
|
|
|
));
|
|
|
|
|
|
|
|
json_spirit::Array nodeChildren = node.get_array();
|
|
|
|
json_spirit::Array::iterator itr = nodeChildren.begin();
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2017-09-05 00:00:04 +02:00
|
|
|
for (; itr != nodeChildren.end(); ++itr)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-04-05 14:37:37 +02:00
|
|
|
obj->m_Children.insert(AtNode::child_pairtype(
|
2014-02-24 21:22:02 +01:00
|
|
|
"item", ConvertNode(*itr)
|
2011-05-29 17:02:02 +02:00
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
2014-02-24 21:22:02 +01:00
|
|
|
else if (node.type() == json_spirit::obj_type)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Object objectProperties = node.get_obj();
|
|
|
|
json_spirit::Object::iterator itr = objectProperties.begin();
|
2017-09-05 00:00:04 +02:00
|
|
|
for (; itr != objectProperties.end(); ++itr)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-04-05 14:37:37 +02:00
|
|
|
obj->m_Children.insert(AtNode::child_pairtype(
|
2014-02-24 21:22:02 +01:00
|
|
|
itr->name_, ConvertNode(itr->value_)
|
2011-05-29 17:02:02 +02:00
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
2014-03-09 18:55:54 +01:00
|
|
|
else if (node.type() == json_spirit::null_type)
|
|
|
|
{
|
|
|
|
return obj;
|
|
|
|
}
|
2014-02-24 21:22:02 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(! "Unimplemented type found when parsing JSON!");
|
|
|
|
}
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2011-05-29 17:02:02 +02:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Value BuildJSONNode(AtNode::Ptr p)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
|
|
|
if (!p)
|
2014-02-24 21:22:02 +01:00
|
|
|
{
|
|
|
|
json_spirit::Value rval;
|
|
|
|
return rval;
|
|
|
|
}
|
2011-05-29 17:02:02 +02:00
|
|
|
|
|
|
|
// Special case for numbers/booleans to allow round-tripping
|
2019-04-05 14:37:37 +02:00
|
|
|
if (p->m_Children.count("@number"))
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
|
|
|
// Convert to double
|
|
|
|
double val = 0;
|
2019-06-03 22:19:53 +02:00
|
|
|
static_cast<std::stringstream>(p->m_Value) >> val;
|
2011-05-29 17:02:02 +02:00
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Value rval(val);
|
2011-05-29 17:02:02 +02:00
|
|
|
return rval;
|
|
|
|
}
|
2019-04-05 14:37:37 +02:00
|
|
|
else if (p->m_Children.count("@boolean"))
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
|
|
|
bool val = false;
|
2019-06-03 22:19:53 +02:00
|
|
|
if (p->m_Value == "true")
|
2011-05-29 17:02:02 +02:00
|
|
|
val = true;
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Value rval(val);
|
|
|
|
return rval;
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// If no children, then use the value string instead
|
2019-04-05 14:37:37 +02:00
|
|
|
if (p->m_Children.empty())
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-06-03 22:19:53 +02:00
|
|
|
json_spirit::Value rval(p->m_Value);
|
2014-02-24 21:22:02 +01:00
|
|
|
return rval;
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
|
|
|
|
2019-04-05 14:37:37 +02:00
|
|
|
if (p->m_Children.find("@array") != p->m_Children.end())
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Array rval;
|
2011-05-29 17:02:02 +02:00
|
|
|
|
|
|
|
// Find the <item> children
|
2019-04-05 14:37:37 +02:00
|
|
|
AtNode::child_maptype::const_iterator lower = p->m_Children.lower_bound("item");
|
|
|
|
AtNode::child_maptype::const_iterator upper = p->m_Children.upper_bound("item");
|
2011-05-29 17:02:02 +02:00
|
|
|
|
2014-03-01 15:41:32 +01:00
|
|
|
unsigned int idx = 0;
|
2011-05-29 17:02:02 +02:00
|
|
|
for (AtNode::child_maptype::const_iterator it = lower; it != upper; ++it)
|
|
|
|
{
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Value child = BuildJSONNode(it->second);
|
|
|
|
rval.push_back(child);
|
2011-05-29 17:02:02 +02:00
|
|
|
|
|
|
|
++idx;
|
|
|
|
}
|
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
return rval;
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Object rval;
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2019-04-05 14:37:37 +02:00
|
|
|
for (AtNode::child_maptype::const_iterator it = p->m_Children.begin(); it != p->m_Children.end(); ++it)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2014-02-24 21:22:02 +01:00
|
|
|
json_spirit::Value child = BuildJSONNode(it->second);
|
2014-03-09 18:55:54 +01:00
|
|
|
// We don't serialize childs with null value.
|
|
|
|
// Instead of something like this we omit the whole property: "StartingCamera": null
|
|
|
|
// There's no special reason for that, it's just the same behaviour the previous implementations had.
|
|
|
|
if (child.type() != json_spirit::null_type)
|
|
|
|
rval.push_back(json_spirit::Pair(it->first.c_str(), child));
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
return rval;
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-24 21:22:02 +01:00
|
|
|
std::string AtlasObject::SaveToJSON(AtObj& obj)
|
2011-05-29 17:02:02 +02:00
|
|
|
{
|
2019-04-05 14:37:37 +02:00
|
|
|
json_spirit::Value root = BuildJSONNode(obj.m_Node);
|
2019-06-03 22:19:53 +02:00
|
|
|
return json_spirit::write_string(root, json_spirit::raw_utf8);
|
2011-05-29 17:02:02 +02:00
|
|
|
}
|