/** @file * @author Edouard DUPIN * @copyright 2011, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file) */ #include #include #include #include #include #include #include #include ememory::SharedPtr ejson::internal::Object::create() { return ememory::SharedPtr(new ejson::internal::Object()); } ememory::SharedPtr ejson::internal::Object::create(const std::string& _data) { ejson::internal::Document doc; doc.parse(_data); return doc.cloneObj(); } void ejson::internal::Object::clear() { m_value.clear(); } enum statusParsing { parseName, parseMiddle, parseValue, }; bool ejson::internal::Object::iParse(const std::string& _data, size_t& _pos, ejson::FilePos& _filePos, ejson::internal::Document& _doc) { enum statusParsing mode = parseName; std::string currentName; EJSON_PARSE_ELEMENT("start parse : 'Object' "); bool standalone = true; size_t startPos = _pos+1; if (_data[_pos] != '{' ) { // when the main node call it, it can be start with != '{' standalone = false; startPos = _pos; } for (size_t iii=startPos; 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] == '#') { // comment Line ... for (iii++; iii<_data.size(); iii++) { if( _data[iii] == '\n' || _data[iii] == '\r') { break; } } } 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) { EJSON_PARSE_ELEMENT("name START " << '"'); if ( _data[iii] == '"' || _data[iii] == '\'') { char startValue=_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] == startValue) { mode = parseMiddle; break; } else { currentName += _data[iii]; } } } else if (checkString(_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 == checkString(_data[iii])) { mode = parseMiddle; iii--; break; } else { currentName += _data[iii]; } } } else { EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "element unknow ..."); _pos = iii; return false; } EJSON_PARSE_ELEMENT("name END "); } else if (mode == parseMiddle) { EJSON_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: EJSON_PARSE_ELEMENT("find Object"); ememory::SharedPtr tmpElement = ejson::internal::Object::create(); if (tmpElement == nullptr) { EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in object"); _pos=iii; return false; } tmpElement->iParse(_data, iii, _filePos, _doc); add(currentName, tmpElement); currentName = ""; } else if ( _data[iii] == '"' || _data[iii] == '\'') { // find a string: EJSON_PARSE_ELEMENT("find String quoted"); ememory::SharedPtr tmpElement = ejson::internal::String::create(); if (tmpElement == nullptr) { EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in String"); _pos=iii; return false; } tmpElement->iParse(_data, iii, _filePos, _doc); add(currentName, tmpElement); currentName = ""; } else if (_data[iii] == '[') { // find a list: EJSON_PARSE_ELEMENT("find List"); ememory::SharedPtr tmpElement = ejson::internal::Array::create(); if (tmpElement == nullptr) { EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in Array"); _pos=iii; return false; } tmpElement->iParse(_data, iii, _filePos, _doc); add(currentName, tmpElement); currentName = ""; } else if( _data[iii] == 'f' || _data[iii] == 't' ) { // find boolean: EJSON_PARSE_ELEMENT("find Boolean"); ememory::SharedPtr tmpElement = ejson::internal::Boolean::create(); if (tmpElement == nullptr) { EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in Boolean"); _pos=iii; return false; } tmpElement->iParse(_data, iii, _filePos, _doc); add(currentName, tmpElement); currentName = ""; } else if( _data[iii] == 'n') { // find null: EJSON_PARSE_ELEMENT("find Null"); ememory::SharedPtr tmpElement = ejson::internal::Null::create(); if (tmpElement == nullptr) { EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in Boolean"); _pos=iii; return false; } tmpElement->iParse(_data, iii, _filePos, _doc); add(currentName, tmpElement); currentName = ""; } else if(true == checkNumber(_data[iii])) { // find number: EJSON_PARSE_ELEMENT("find Number"); ememory::SharedPtr tmpElement = ejson::internal::Number::create(); if (tmpElement == nullptr) { EJSON_CREATE_ERROR(_doc, _data, iii, _filePos, "Allocation error in Boolean"); _pos=iii; return false; } tmpElement->iParse(_data, iii, _filePos, _doc); add(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, std::string("Find '") + _data[iii] + "' with no element in the element..."); // move the curent index _pos = iii+1; return false; } } } } _pos = _data.size(); if (false == standalone) { return true; } return false; } bool ejson::internal::Object::iGenerate(std::string& _data, size_t _indent) const { bool oneLine=true; if (m_value.size()>3) { oneLine=false; } else if (_indent<=1) { oneLine=false; } else { for (int32_t iii=0; iii tmp = m_value[iii]; if (tmp == nullptr) { continue; } if ( tmp->getType() == ejson::valueType::object || tmp->getType() == ejson::valueType::document) { oneLine=false; break; } if (tmp->getType() == ejson::valueType::array) { oneLine=false; break; } if (tmp->getType() == ejson::valueType::string) { ememory::SharedPtr tmp2 = std::static_pointer_cast(tmp); if( tmp2->get().size()>25 || m_value.getKey(iii).size()>25) { oneLine=false; break; } } } } if (true == oneLine) { _data += "{ "; } else { _data += "{\n"; } for (int32_t iii=0; iiiiGenerate(_data, _indent+1); if (iii ejson::internal::Object::getKeys() const { return m_value.getKeys(); } size_t ejson::internal::Object::size() const { return m_value.size(); } ememory::SharedPtr ejson::internal::Object::get(size_t _id) { return m_value[_id]; } const ememory::SharedPtr ejson::internal::Object::get(size_t _id) const{ return m_value[_id]; } ememory::SharedPtr ejson::internal::Object::get(const std::string& _name) { if (m_value.exist(_name) == false) { return ememory::SharedPtr(); } return m_value[_name]; } const ememory::SharedPtr ejson::internal::Object::get(const std::string& _name) const { if (m_value.exist(_name) == false) { return ememory::SharedPtr(); } return m_value[_name]; } std::string ejson::internal::Object::getKey(size_t _id) const { return m_value.getKey(_id); } bool ejson::internal::Object::add(const std::string& _name, ememory::SharedPtr _value) { if (_value == nullptr) { return false; } if (_name.size() == 0) { return false; } if (m_value.exist(_name)) { m_value[_name] = _value; return true; } m_value.add(_name, _value); return true; } void ejson::internal::Object::remove(const std::string& _name) { m_value.remove(_name); } void ejson::internal::Object::remove(size_t _id) { m_value.remove(getKey(_id)); } bool ejson::internal::Object::transfertIn(ememory::SharedPtr _obj) { if (_obj == nullptr) { EJSON_ERROR("Request transfer on an nullptr pointer"); return false; } if ( _obj->getType() != ejson::valueType::object && _obj->getType() != ejson::valueType::document) { EJSON_ERROR("Request transfer on an element that is not an object"); return false; } ememory::SharedPtr other = std::static_pointer_cast(_obj); // remove destination elements other->clear(); // Copy to the destination other->m_value = m_value; // remove current: m_value.clear(); return true; } bool ejson::internal::Object::cloneIn(const ememory::SharedPtr& _obj) const { if (_obj == nullptr) { return false; } _obj->clear(); for (int32_t iii=0; iiiadd(m_value.getKey(iii), m_value[iii]->clone()); } return true; } // TODO : Manage error ... ememory::SharedPtr ejson::internal::Object::clone() const { return cloneObj(); } ememory::SharedPtr ejson::internal::Object::cloneObj() const { ememory::SharedPtr output = ejson::internal::Object::create(); if (output == nullptr) { EJSON_ERROR("Allocation error ..."); return ememory::SharedPtr(); } for (int32_t iii=0; iii val = m_value.getValue(iii); std::string key = m_value.getKey(iii); if (val == nullptr) { continue; } output->add(key, val->clone()); } return output; }