287 lines
7.1 KiB
C++
287 lines
7.1 KiB
C++
/**
|
|
* @author Edouard DUPIN
|
|
*
|
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
*
|
|
* @license BSD v3 (see license file)
|
|
*/
|
|
|
|
|
|
#include <ejson/Object.h>
|
|
#include <ejson/Array.h>
|
|
#include <ejson/String.h>
|
|
#include <ejson/debug.h>
|
|
#include <ejson/ejson.h>
|
|
|
|
#undef __class__
|
|
#define __class__ "Object"
|
|
|
|
void ejson::Object::Clear(void)
|
|
{
|
|
for (esize_t iii=0; iii<m_value.Size(); ++iii) {
|
|
if (NULL == m_value[iii]) {
|
|
continue;
|
|
}
|
|
delete(m_value[iii]);
|
|
m_value[iii] = NULL;
|
|
}
|
|
m_value.Clear();
|
|
}
|
|
|
|
|
|
typedef enum {
|
|
parseName,
|
|
parseMiddle,
|
|
parseValue,
|
|
} statusParsing_te;
|
|
|
|
bool ejson::Object::IParse(const etk::UString& _data, int32_t& _pos, ejson::filePos& _filePos, ejson::Document& _doc)
|
|
{
|
|
statusParsing_te mode = parseName;
|
|
etk::UString currentName;
|
|
JSON_PARSE_ELEMENT("start parse : 'Object' ");
|
|
for (int32_t iii=_pos+1; iii<_data.Size(); iii++) {
|
|
_filePos.Check(_data[iii]);
|
|
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
|
DrawElementParsed(_data[iii], _filePos);
|
|
#endif
|
|
ejson::filePos tmpPos;
|
|
if( _data[iii]==' '
|
|
|| _data[iii]=='\t'
|
|
|| _data[iii]=='\n'
|
|
|| _data[iii]=='\r') {
|
|
// white space ==> nothing to do ...
|
|
} else if(_data[iii]=='}') {
|
|
// find end of value:
|
|
_pos=iii; // ==> return the end element type ==> usefull to check end and check if adding element is needed
|
|
return true;
|
|
} else {
|
|
if (mode == parseName) {
|
|
JSON_PARSE_ELEMENT("name START " << '"');
|
|
if (_data[iii]=='"') {
|
|
currentName = "";
|
|
for (iii++; iii<_data.Size(); iii++) {
|
|
_filePos.Check(_data[iii]);
|
|
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
|
DrawElementParsed(_data[iii], _filePos);
|
|
#endif
|
|
if (_data[iii]=='\"') {
|
|
mode = parseMiddle;
|
|
break;
|
|
} else {
|
|
currentName += _data[iii];
|
|
}
|
|
}
|
|
} else if (CheckAvaillable(_data[iii]) ) {
|
|
currentName += _data[iii];
|
|
for (iii++; iii<_data.Size(); iii++) {
|
|
_filePos.Check(_data[iii]);
|
|
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
|
DrawElementParsed(_data[iii], _filePos);
|
|
#endif
|
|
if (false==CheckAvaillable(_data[iii])) {
|
|
mode = parseMiddle;
|
|
iii--;
|
|
break;
|
|
} else {
|
|
currentName += _data[iii];
|
|
}
|
|
}
|
|
} else {
|
|
EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "element unknow ...");
|
|
_pos = iii;
|
|
return false;
|
|
}
|
|
JSON_PARSE_ELEMENT("name END ");
|
|
} else if (mode == parseMiddle) {
|
|
JSON_PARSE_ELEMENT(" middle ... ");
|
|
if (_data[iii]==':') {
|
|
mode = parseValue;
|
|
} else {
|
|
EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "separator is not ':'");
|
|
return false;
|
|
}
|
|
} else if (mode == parseValue) {
|
|
if (_data[iii]=='{') {
|
|
// find an object:
|
|
JSON_PARSE_ELEMENT("find Object");
|
|
ejson::Object * tmpElement = new ejson::Object();
|
|
if (NULL==tmpElement) {
|
|
EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in object");
|
|
_pos=iii;
|
|
return false;
|
|
}
|
|
tmpElement->IParse(_data, iii, _filePos, _doc);
|
|
AddSub(currentName, tmpElement);
|
|
currentName = "";
|
|
} else if (_data[iii]=='"') {
|
|
// find a string:
|
|
JSON_PARSE_ELEMENT("find String quoted");
|
|
ejson::String * tmpElement = new ejson::String(true);
|
|
if (NULL==tmpElement) {
|
|
EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in String");
|
|
_pos=iii;
|
|
return false;
|
|
}
|
|
tmpElement->IParse(_data, iii, _filePos, _doc);
|
|
AddSub(currentName, tmpElement);
|
|
currentName = "";
|
|
} else if (_data[iii]=='[') {
|
|
// find a list:
|
|
JSON_PARSE_ELEMENT("find List");
|
|
ejson::Array * tmpElement = new ejson::Array();
|
|
if (NULL==tmpElement) {
|
|
EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in Array");
|
|
_pos=iii;
|
|
return false;
|
|
}
|
|
tmpElement->IParse(_data, iii, _filePos, _doc);
|
|
AddSub(currentName, tmpElement);
|
|
currentName = "";
|
|
} else if( CheckAvaillable(_data[iii]) ) {
|
|
// find a string without "" ==> special hook for the etk-json parser
|
|
JSON_PARSE_ELEMENT("find String");
|
|
ejson::String * tmpElement = new ejson::String(false);
|
|
if (NULL==tmpElement) {
|
|
EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in String");
|
|
_pos=iii;
|
|
return false;
|
|
}
|
|
iii--;
|
|
tmpElement->IParse(_data, iii, _filePos, _doc);
|
|
iii--;
|
|
//JSON_ERROR(" add : " << currentName );
|
|
AddSub(currentName, tmpElement);
|
|
currentName = "";
|
|
} else if(_data[iii]==',') {
|
|
// find Separator : Restart cycle ...
|
|
mode = parseName;
|
|
currentName = "";
|
|
} else {
|
|
// find an error ....
|
|
EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Find '>' with no element in the element...");
|
|
// move the curent index
|
|
_pos = iii+1;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_pos = _data.Size();
|
|
return false;
|
|
}
|
|
bool ejson::Object::IGenerate(etk::UString& _data, int32_t _indent) const
|
|
{
|
|
_data += "{\n";
|
|
for (esize_t iii=0; iii<m_value.Size() ; iii++) {
|
|
AddIndent(_data, _indent);
|
|
_data += "\"";
|
|
_data += m_value.GetKey(iii);
|
|
_data += "\": ";
|
|
m_value.GetValue(iii)->IGenerate(_data, _indent+1);
|
|
if (iii<m_value.Size()-1) {
|
|
_data += ",";
|
|
}
|
|
_data += "\n";
|
|
}
|
|
AddIndent(_data, _indent-1);
|
|
_data += "}";
|
|
return true;
|
|
}
|
|
|
|
|
|
ejson::Value* ejson::Object::GetSub(const etk::UString& _named) const
|
|
{
|
|
if (false==m_value.Exist(_named)) {
|
|
return NULL;
|
|
}
|
|
return m_value[_named];
|
|
}
|
|
|
|
ejson::Object* ejson::Object::GetSubObject(const etk::UString& _named) const
|
|
{
|
|
ejson::Value* tmp = GetSub(_named);
|
|
if (NULL == tmp) {
|
|
return NULL;
|
|
}
|
|
return tmp->ToObject();
|
|
}
|
|
|
|
ejson::String* ejson::Object::GetSubString(const etk::UString& _named) const
|
|
{
|
|
ejson::Value* tmp = GetSub(_named);
|
|
if (NULL == tmp) {
|
|
return NULL;
|
|
}
|
|
return tmp->ToString();
|
|
}
|
|
|
|
ejson::Array* ejson::Object::GetSubArray(const etk::UString& _named) const
|
|
{
|
|
ejson::Value* tmp = GetSub(_named);
|
|
if (NULL == tmp) {
|
|
return NULL;
|
|
}
|
|
return tmp->ToArray();
|
|
}
|
|
|
|
|
|
bool ejson::Object::AddSub(const etk::UString& _name, ejson::Value* _value)
|
|
{
|
|
if (NULL == _value) {
|
|
return false;
|
|
}
|
|
if (_name.Size()==0) {
|
|
return false;
|
|
}
|
|
if (m_value.Exist(_name)) {
|
|
ejson::Value* tmp = m_value[_name];
|
|
delete(tmp);
|
|
m_value[_name] = _value;
|
|
return true;
|
|
}
|
|
m_value.Add(_name, _value);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool ejson::Object::TransfertIn(ejson::Value* _obj)
|
|
{
|
|
if (NULL==_obj) {
|
|
JSON_ERROR("Request transfer on an NULL pointer");
|
|
return false;
|
|
}
|
|
ejson::Object* other = _obj->ToObject();
|
|
if (NULL==other) {
|
|
JSON_ERROR("Request transfer on an element that is not an object");
|
|
return false;
|
|
}
|
|
// remove destination elements
|
|
other->Clear();
|
|
// Copy to the destination
|
|
other->m_value = m_value;
|
|
// remove current:
|
|
m_value.Clear();
|
|
return true;
|
|
}
|
|
|
|
// TODO : Manage error ...
|
|
ejson::Value* ejson::Object::Duplicate(void) const
|
|
{
|
|
ejson::Object* output = new ejson::Object();
|
|
if (NULL==output) {
|
|
JSON_ERROR("Allocation error ...");
|
|
return NULL;
|
|
}
|
|
for (esize_t iii=0; iii<m_value.Size(); ++iii) {
|
|
ejson::Value* val = m_value.GetValue(iii);
|
|
etk::UString key = m_value.GetKey(iii);
|
|
if (NULL == val) {
|
|
continue;
|
|
}
|
|
output->AddSub(key, val->Duplicate());
|
|
}
|
|
return output;
|
|
}
|