[DEV] Review all the API of the XML to have user simple API to use ...
This commit is contained in:
parent
753c0c0db2
commit
401f6905e1
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -8,121 +8,65 @@
|
||||
|
||||
#include <exml/Attribute.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/Document.h>
|
||||
#include <exml/internal/Attribute.h>
|
||||
|
||||
ememory::SharedPtr<exml::Attribute> exml::Attribute::create(const std::string& _name, const std::string& _value) {
|
||||
return ememory::SharedPtr<exml::Attribute>(new exml::Attribute(_name, _value));
|
||||
exml::Attribute::Attribute(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::Node(_internalNode) {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (m_data->isAttribute() == false) {
|
||||
// try to set wrong type inside ... ==> remove it ...
|
||||
m_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
exml::Attribute::Attribute(const exml::Attribute& _obj) :
|
||||
exml::Node(_obj.m_data) {
|
||||
|
||||
}
|
||||
/*
|
||||
exml::Attribute::Attribute(nullptr) :
|
||||
exml::Node(nullptr) {
|
||||
|
||||
}
|
||||
*/
|
||||
exml::Attribute::Attribute(const std::string& _name, const std::string& _value) :
|
||||
exml::Node(_value),
|
||||
m_name(_name) {
|
||||
|
||||
exml::Node() {
|
||||
m_data = exml::internal::Attribute::create(_name, _value);
|
||||
}
|
||||
|
||||
bool exml::Attribute::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'attribute'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
size_t lastElementName = _pos;
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (checkAvaillable(_data[iii], false) == true) {
|
||||
lastElementName = iii;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_name = std::string(_data, _pos, lastElementName+1-(_pos));
|
||||
if (_caseSensitive == true) {
|
||||
m_name = etk::tolower(m_name);
|
||||
}
|
||||
// count white space :
|
||||
exml::FilePos tmpPos;
|
||||
int32_t white = countWhiteChar(_data, lastElementName+1, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
if (lastElementName+white+1 >= _data.size()) {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+1, _filePos, " parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
if (_data[lastElementName+white+1] != '=') {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+1, _filePos, " error attribute parsing == > missing '=' ...");
|
||||
return false;
|
||||
}
|
||||
white += countWhiteChar(_data, lastElementName+white+2, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
|
||||
if (lastElementName+white+2>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+2, _filePos, " parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
bool simpleQuoteCase = false;
|
||||
if (_data[lastElementName+white+2] == '\'') { // '
|
||||
simpleQuoteCase = true;
|
||||
}
|
||||
if ( _data[lastElementName+white+2] != '"'
|
||||
&& _data[lastElementName+white+2] != '\'') { // '
|
||||
// parse with no element " == > direct value separate with space ...
|
||||
++_filePos;
|
||||
size_t lastAttributePos = lastElementName+white+2;
|
||||
for (size_t iii=lastElementName+white+2; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
CREATE_ERROR(_doc, _data, iii, _filePos, "unexpected '\\n' in an attribute parsing");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii] != ' '
|
||||
&& _data[iii] != '/'
|
||||
&& _data[iii] != '?'
|
||||
&& _data[iii] != '>') {
|
||||
lastAttributePos = iii+1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = std::string(_data, lastElementName+white+2, lastAttributePos-(lastElementName+white+2));
|
||||
|
||||
EXML_PARSE_ATTRIBUTE(m_pos << " attribute : " << m_name << "=\"" << m_value << "\"");
|
||||
|
||||
_pos = lastAttributePos-1;
|
||||
return true;
|
||||
}
|
||||
size_t lastAttributePos = lastElementName+white+3;
|
||||
for (size_t iii=lastElementName+white+3; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
_filePos.check(_data[iii]);
|
||||
if ( (_data[iii] != '"' && simpleQuoteCase == false)
|
||||
|| (_data[iii] != '\'' && simpleQuoteCase == true) ) { // '
|
||||
lastAttributePos = iii+1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = std::string(_data, lastElementName+white+3, lastAttributePos-(lastElementName+white+3));
|
||||
|
||||
EXML_PARSE_ATTRIBUTE(m_pos << " attribute : " << m_name << "=\"" << m_value << "\"");
|
||||
|
||||
_pos = lastAttributePos;
|
||||
return true;
|
||||
exml::Attribute& exml::Attribute::operator= (const exml::Attribute& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool exml::Attribute::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
_data += " ";
|
||||
_data += m_name;
|
||||
_data += "=\"";
|
||||
_data += m_value;
|
||||
_data += "\"";
|
||||
return true;
|
||||
void exml::Attribute::setName(const std::string& _name){
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not setName (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
static_cast<exml::internal::Attribute*>(m_data.get())->setName(_name);
|
||||
}
|
||||
|
||||
const std::string& exml::Attribute::getName() const {
|
||||
if (m_data == nullptr) {
|
||||
static std::string errorValue = "";
|
||||
EXML_ERROR(" can not setName (nullptr) ...");
|
||||
return errorValue;
|
||||
}
|
||||
return static_cast<exml::internal::Attribute*>(m_data.get())->getName();
|
||||
}
|
||||
|
||||
void exml::Attribute::clear() {
|
||||
m_name = "";
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not setName (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
static_cast<exml::internal::Attribute*>(m_data.get())->clear();
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<exml::internal::Attribute> exml::Attribute::getInternalAttribute() {
|
||||
return std::static_pointer_cast<exml::internal::Attribute>(m_data);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -11,55 +11,57 @@
|
||||
#include <vector>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
class Attribute;
|
||||
}
|
||||
class AttributeListData;
|
||||
/**
|
||||
* @brief Single attribute element
|
||||
*/
|
||||
class Attribute : public exml::Node {
|
||||
protected:
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _internalNode Internal Node to set data
|
||||
*/
|
||||
Attribute(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
// TODO : Attribute(nullptr);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
Attribute(const exml::Attribute& _obj);
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _name Name of the attribute.
|
||||
* @param[in] _value Value of the attribute.
|
||||
*/
|
||||
Attribute(const std::string& _name="", const std::string& _value="");
|
||||
public:
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @param[in] _name Name of the attribute
|
||||
* @param[in] _value Value of the attribute
|
||||
* @return Shared pointer on the Attribute element
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
static ememory::SharedPtr<Attribute> create(const std::string& _name="", const std::string& _value="");
|
||||
protected:
|
||||
std::string m_name; //!< Name of the attribute
|
||||
exml::Attribute& operator= (const exml::Attribute& _obj);
|
||||
public:
|
||||
/**
|
||||
* @brief set the name of the attribute
|
||||
* @param[in] _name New name of the attribute
|
||||
*/
|
||||
virtual void setName(const std::string& _name) {
|
||||
m_name = _name;
|
||||
};
|
||||
virtual void setName(const std::string& _name);
|
||||
/**
|
||||
* @brief get the current name of the Attribute
|
||||
* @return String of the attribute
|
||||
*/
|
||||
virtual const std::string& getName() const {
|
||||
return m_name;
|
||||
};
|
||||
virtual const std::string& getName() const;
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return exml::nodeType_attribute;
|
||||
};
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::Attribute> toAttribute() override {
|
||||
return std::static_pointer_cast<exml::Attribute>(shared_from_this());
|
||||
};
|
||||
ememory::SharedPtr<const exml::Attribute> toAttribute() const override {
|
||||
return std::static_pointer_cast<const exml::Attribute>(shared_from_this());
|
||||
};
|
||||
void clear() override;
|
||||
friend class exml::AttributeListData;
|
||||
private:
|
||||
ememory::SharedPtr<exml::internal::Attribute> getInternalAttribute();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -6,122 +6,104 @@
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/AttributeList.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/AttributeList.h>
|
||||
#include <exml/internal/AttributeList.h>
|
||||
|
||||
ememory::SharedPtr<exml::Attribute> exml::AttributeList::getAttr(int32_t _id) {
|
||||
if (_id <0 || (size_t)_id>m_listAttribute.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listAttribute[_id];
|
||||
|
||||
exml::AttributeList::AttributeList(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::Node(_internalNode),
|
||||
attributes(this) {
|
||||
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Attribute> exml::AttributeList::getAttr(int32_t _id) const {
|
||||
if (_id <0 || (size_t)_id>m_listAttribute.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listAttribute[_id];
|
||||
exml::AttributeList::AttributeList() :
|
||||
exml::Node(),
|
||||
attributes(this) {
|
||||
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> exml::AttributeList::getAttrPair(int32_t _id) const {
|
||||
ememory::SharedPtr<const exml::Attribute> att = getAttr(_id);
|
||||
if (att == nullptr) {
|
||||
return std::make_pair<std::string, std::string>("","");
|
||||
}
|
||||
return std::make_pair(att->getName(),att->getValue());
|
||||
exml::AttributeListData::AttributeListData(exml::AttributeList* _list) :
|
||||
m_data(_list) {
|
||||
|
||||
}
|
||||
|
||||
size_t exml::AttributeListData::size() const {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not sizeAttribute ...");
|
||||
return 0;
|
||||
}
|
||||
return static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->sizeAttribute();
|
||||
|
||||
}
|
||||
|
||||
void exml::AttributeList::appendAttribute(const ememory::SharedPtr<exml::Attribute>& _attr) {
|
||||
if (_attr == nullptr) {
|
||||
EXML_ERROR("Try to set an empty node");
|
||||
exml::Attribute exml::AttributeListData::operator[] (int32_t _id) {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not getAttr (nullptr) ...");
|
||||
return exml::Attribute(ememory::SharedPtr<exml::internal::Attribute>(nullptr));
|
||||
}
|
||||
return exml::Attribute(static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->getAttr(_id));
|
||||
}
|
||||
|
||||
const exml::Attribute exml::AttributeListData::operator[] (int32_t _id) const {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not getAttr (nullptr) ...");
|
||||
return exml::Attribute(ememory::SharedPtr<exml::internal::Attribute>(nullptr));
|
||||
}
|
||||
return exml::Attribute(static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->getAttr(_id));
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> exml::AttributeListData::getPair(int32_t _id) const {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not getAttrPair (nullptr) ...");
|
||||
return std::pair<std::string, std::string>();
|
||||
}
|
||||
return static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->getAttrPair(_id);
|
||||
}
|
||||
|
||||
void exml::AttributeListData::add(exml::Attribute _attr) {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not appendAttribute (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (m_listAttribute[iii] == _attr) {
|
||||
EXML_ERROR("Try to add a node that is already added befor !!!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_listAttribute.push_back(_attr);
|
||||
static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->appendAttribute(_attr.getInternalAttribute());
|
||||
}
|
||||
|
||||
const std::string& exml::AttributeList::getAttribute(const std::string& _name) const {
|
||||
static const std::string errorReturn("");
|
||||
if (_name.size() == 0) {
|
||||
return errorReturn;
|
||||
const std::string& exml::AttributeListData::get(const std::string& _name) const {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not getAttribute (nullptr) ...");
|
||||
static std::string errorValue("");
|
||||
return errorValue;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if( m_listAttribute[iii] != nullptr
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
return m_listAttribute[iii]->getValue();
|
||||
}
|
||||
}
|
||||
return errorReturn;
|
||||
return static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->getAttribute(_name);
|
||||
}
|
||||
|
||||
|
||||
bool exml::AttributeList::existAttribute(const std::string& _name) const {
|
||||
if (_name.size() == 0) {
|
||||
bool exml::AttributeListData::exist(const std::string& _name) const {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not getAttribute (nullptr) ...");
|
||||
return false;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); ++iii) {
|
||||
if( m_listAttribute[iii] != nullptr
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->existAttribute(_name);
|
||||
}
|
||||
|
||||
bool exml::AttributeList::removeAttribute(const std::string& _name) {
|
||||
if (_name.size() == 0) {
|
||||
bool exml::AttributeListData::remove(const std::string& _name) {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not removeAttribute (nullptr) ...");
|
||||
return false;
|
||||
}
|
||||
auto it = m_listAttribute.begin();
|
||||
while (it != m_listAttribute.end()) {
|
||||
if (*it == nullptr) {
|
||||
it = m_listAttribute.erase(it);
|
||||
continue;
|
||||
}
|
||||
if((*it)->getName() == _name) {
|
||||
it = m_listAttribute.erase(it);
|
||||
return true;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return false;
|
||||
return static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->removeAttribute(_name);
|
||||
}
|
||||
|
||||
void exml::AttributeList::setAttribute(const std::string& _name, const std::string& _value) {
|
||||
// check if attribute already det :
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); ++iii) {
|
||||
if( m_listAttribute[iii] != nullptr
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
// update the value :
|
||||
m_listAttribute[iii]->setValue(_value);
|
||||
return;
|
||||
}
|
||||
void exml::AttributeListData::set(const std::string& _name, const std::string& _value) {
|
||||
if (m_data->m_data == nullptr) {
|
||||
EXML_ERROR(" can not setAttribute (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
ememory::SharedPtr<exml::Attribute> attr = exml::Attribute::create(_name, _value);
|
||||
if (attr == nullptr) {
|
||||
EXML_ERROR("memory allocation error...");
|
||||
}
|
||||
m_listAttribute.push_back(attr);
|
||||
static_cast<exml::internal::AttributeList*>(m_data->m_data.get())->setAttribute(_name, _value);
|
||||
}
|
||||
|
||||
bool exml::AttributeList::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (m_listAttribute[iii] != nullptr) {
|
||||
m_listAttribute[iii]->iGenerate(_data, _indent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#include <exml/details/iterator.hxx>
|
||||
|
||||
void exml::AttributeList::clear() {
|
||||
exml::Node::clear();
|
||||
m_listAttribute.clear();
|
||||
}
|
||||
template class exml::iterator<exml::AttributeListData, exml::Attribute>;
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -8,85 +8,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <exml/Node.h>
|
||||
#include <vector>
|
||||
#include <exml/Attribute.h>
|
||||
#include <utility>
|
||||
#include <exml/iterator.h>
|
||||
|
||||
namespace exml {
|
||||
/**
|
||||
* @brief List of all attribute element in a node
|
||||
*/
|
||||
class AttributeList : public exml::Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _value Node value;
|
||||
*/
|
||||
AttributeList(const std::string& _value="") :
|
||||
exml::Node(_value) {
|
||||
|
||||
};
|
||||
protected:
|
||||
std::vector<ememory::SharedPtr<exml::Attribute>> m_listAttribute; //!< list of all attribute
|
||||
class AttributeList;
|
||||
|
||||
class AttributeListData {
|
||||
private:
|
||||
exml::AttributeList* m_data;
|
||||
public:
|
||||
AttributeListData(exml::AttributeList* _list);
|
||||
public:
|
||||
/**
|
||||
* @brief get the number of attribute in the Node
|
||||
* @return Nulber of attribute >=0
|
||||
* @return Number of attribute >=0
|
||||
*/
|
||||
size_t sizeAttribute() const {
|
||||
return m_listAttribute.size();
|
||||
};
|
||||
size_t size() const;
|
||||
/**
|
||||
* @brief add attribute on the List
|
||||
* @param[in] _attr Pointer on the attribute
|
||||
*/
|
||||
void appendAttribute(const ememory::SharedPtr<exml::Attribute>& _attr);
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Pointer on the attribute or NULL
|
||||
*/
|
||||
ememory::SharedPtr<Attribute> getAttr(int32_t _id);
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Pointer on the attribute or NULL
|
||||
*/
|
||||
ememory::SharedPtr<const Attribute> getAttr(int32_t _id) const;
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Name and value of the attribute
|
||||
*/
|
||||
std::pair<std::string, std::string> getAttrPair(int32_t _id) const;
|
||||
/**
|
||||
* @brief get the attribute value with searching in the List with his name
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return Value of the attribute or no data in the string
|
||||
*/
|
||||
const std::string& getAttribute(const std::string& _name) const;
|
||||
/**
|
||||
* @brief check if an attribute exist or not with his name.
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return true if the attribute exist or False
|
||||
*/
|
||||
bool existAttribute(const std::string& _name) const;
|
||||
/**
|
||||
* @brief Set A new attribute or replace data of the previous one
|
||||
* @param[in] _name Name of the attribute
|
||||
* @param[in] _value Value of the attribute
|
||||
*/
|
||||
void setAttribute(const std::string& _name, const std::string& _value);
|
||||
void add(exml::Attribute _attr);
|
||||
/**
|
||||
* @brief Remove an attribute form the list
|
||||
* @param[in] _name Name of the attribute
|
||||
* @return true The attribute has been removed
|
||||
* @return false An error occured.
|
||||
*/
|
||||
bool removeAttribute(const std::string& _name);
|
||||
bool remove(const std::string& _name);
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Pointer on the attribute or NULL
|
||||
*/
|
||||
exml::Attribute operator[] (int32_t _id);
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Pointer on the attribute or NULL
|
||||
*/
|
||||
const exml::Attribute operator[](int32_t _id) const;
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Name and value of the attribute
|
||||
*/
|
||||
std::pair<std::string, std::string> getPair(int32_t _id) const;
|
||||
/**
|
||||
* @brief get the attribute value with searching in the List with his name
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return Value of the attribute or no data in the string
|
||||
*/
|
||||
const std::string& get(const std::string& _name) const;
|
||||
/**
|
||||
* @brief check if an attribute exist or not with his name.
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return true if the attribute exist or False
|
||||
*/
|
||||
bool exist(const std::string& _name) const;
|
||||
/**
|
||||
* @brief Set A new attribute or replace data of the previous one
|
||||
* @param[in] _name Name of the attribute
|
||||
* @param[in] _value Value of the attribute
|
||||
*/
|
||||
void set(const std::string& _name, const std::string& _value);
|
||||
public:
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
void clear() override;
|
||||
using iterator = exml::iterator<exml::AttributeListData, exml::Attribute>;
|
||||
iterator begin() {
|
||||
return iterator(*this, 0);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(*this, size());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief List of all attribute element in a node
|
||||
*/
|
||||
class AttributeList : public exml::Node {
|
||||
public:
|
||||
AttributeListData attributes;
|
||||
protected:
|
||||
/**
|
||||
* @brief basic element of a xml structure
|
||||
* @param[in] _value value of the node
|
||||
*/
|
||||
AttributeList(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief basic element of a xml structure
|
||||
*/
|
||||
AttributeList();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -8,65 +8,30 @@
|
||||
|
||||
#include <exml/Comment.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/Document.h>
|
||||
#include <exml/internal/Comment.h>
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
exml::Comment::Comment(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::Node(_internalNode) {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Comment> exml::Comment::create() {
|
||||
return ememory::SharedPtr<exml::Comment>(new exml::Comment());
|
||||
}
|
||||
|
||||
bool exml::Comment::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'comment'");
|
||||
m_pos = _filePos;
|
||||
exml::FilePos tmpPos;
|
||||
int32_t white = countWhiteChar(_data, _pos, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos+white; iii+2<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '-'
|
||||
&& _data[iii+1] == '-'
|
||||
&& _data[iii+2] == '>') {
|
||||
_filePos += 2;
|
||||
// search whitespace :
|
||||
int32_t newEnd=iii;
|
||||
for( int32_t jjj=iii-1; jjj>_pos; jjj--) {
|
||||
if(isWhiteChar(_data[jjj]) == true) {
|
||||
newEnd = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// find end of value:
|
||||
m_value = std::string(_data, _pos+white, newEnd-(_pos+white));
|
||||
EXML_VERBOSE(" find comment '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
if (m_data->isComment() == false) {
|
||||
// try to set wrong type inside ... ==> remove it ...
|
||||
m_data = nullptr;
|
||||
}
|
||||
_pos = _data.size();
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "comment got end of file without finding end node");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::Comment::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
addIndent(_data, _indent);
|
||||
_data += "<!--";
|
||||
_data += m_value;
|
||||
_data += "-->\n";
|
||||
return true;
|
||||
}
|
||||
exml::Comment::Comment(const exml::Comment& _obj) :
|
||||
exml::Node(_obj.m_data) {
|
||||
|
||||
}
|
||||
|
||||
exml::Comment::Comment(const std::string& _value) :
|
||||
exml::Node() {
|
||||
m_data = exml::internal::Comment::create(_value);
|
||||
}
|
||||
|
||||
exml::Comment& exml::Comment::operator= (const exml::Comment& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -15,37 +15,27 @@ namespace exml {
|
||||
* @brief Comment node: <!-- ... -->
|
||||
*/
|
||||
class Comment : public exml::Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Comment() { };
|
||||
public:
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @return Shared pointer on the Comment element
|
||||
* @brief Constructor
|
||||
* @param[in] _internalNode Internal Node to set data
|
||||
*/
|
||||
static ememory::SharedPtr<exml::Comment> create();
|
||||
Comment(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
Comment(const exml::Comment& _obj);
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _value comment value
|
||||
*/
|
||||
Comment(const std::string& _value) :
|
||||
exml::Node(_value) {
|
||||
|
||||
}
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return nodeType_attribute;
|
||||
}
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::Comment> toComment() override {
|
||||
return std::static_pointer_cast<exml::Comment>(shared_from_this());
|
||||
}
|
||||
ememory::SharedPtr<const exml::Comment> toComment() const override {
|
||||
return std::static_pointer_cast<const exml::Comment>(shared_from_this());
|
||||
}
|
||||
Comment(const std::string& _value="");
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
exml::Comment& operator= (const exml::Comment& _obj);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -8,92 +8,63 @@
|
||||
|
||||
#include <exml/Declaration.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/Document.h>
|
||||
#include <exml/internal/Declaration.h>
|
||||
|
||||
/* basic declaration have 3 attributes:
|
||||
version
|
||||
encoding
|
||||
standalone
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
*/
|
||||
|
||||
ememory::SharedPtr<exml::Declaration> exml::Declaration::create(const std::string& _name) {
|
||||
return ememory::SharedPtr<exml::Declaration>(new exml::Declaration(_name));
|
||||
exml::Declaration::Declaration(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::AttributeList(_internalNode) {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (m_data->isDeclaration() == false) {
|
||||
// try to set wrong type inside ... ==> remove it ...
|
||||
m_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::DeclarationXML> exml::DeclarationXML::create(const std::string& _version, const std::string& _format, bool _standalone) {
|
||||
return ememory::SharedPtr<exml::DeclarationXML>(new exml::DeclarationXML(_version, _format, _standalone));
|
||||
exml::Declaration::Declaration(const exml::Declaration& _obj) :
|
||||
exml::AttributeList(_obj.m_data) {
|
||||
|
||||
}
|
||||
|
||||
exml::Declaration::Declaration(const std::string& _name) :
|
||||
exml::AttributeList() {
|
||||
m_data = exml::internal::Declaration::create();
|
||||
}
|
||||
|
||||
exml::Declaration& exml::Declaration::operator= (const exml::Declaration& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
exml::DeclarationXML::DeclarationXML(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::Declaration(_internalNode) {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
// TODO: Do it better
|
||||
if (m_data->isDeclaration() == false) {
|
||||
// try to set wrong type inside ... ==> remove it ...
|
||||
m_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
exml::DeclarationXML::DeclarationXML(const exml::DeclarationXML& _obj) :
|
||||
exml::Declaration(_obj.m_data) {
|
||||
|
||||
}
|
||||
|
||||
exml::DeclarationXML::DeclarationXML(const std::string& _version, const std::string& _format, bool _standalone) :
|
||||
exml::Declaration("xml") {
|
||||
if (_version.size()!=0) {
|
||||
setAttribute("version", _version);
|
||||
}
|
||||
if (_format!="UTF-8") {
|
||||
setAttribute("encoding", "UTF-8");
|
||||
} else {
|
||||
EXML_ERROR("Actually does not supported other charset than UTF8");
|
||||
setAttribute("encoding", "UTF-8");
|
||||
}
|
||||
if (_standalone == true) {
|
||||
setAttribute("standalone", "true");
|
||||
} else {
|
||||
setAttribute("standalone", "true");
|
||||
}
|
||||
exml::Declaration() {
|
||||
m_data = exml::internal::DeclarationXML::create(_version, _format, _standalone);
|
||||
}
|
||||
|
||||
bool exml::Declaration::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
addIndent(_data, _indent);
|
||||
_data += "<?";
|
||||
_data += m_value;
|
||||
exml::AttributeList::iGenerate(_data, _indent);
|
||||
_data += "?>\n";
|
||||
return true;
|
||||
exml::DeclarationXML& exml::DeclarationXML::operator= (const exml::DeclarationXML& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool exml::Declaration::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'declaration' : '" << m_value << "'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos; iii+1<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
|| _data[iii] == '<') {
|
||||
// an error occured :
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, " find '>' or '<' instead of '?>'");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii] == '?'
|
||||
&& _data[iii+1] == '>') {
|
||||
++_filePos;
|
||||
// find end of declaration:
|
||||
_pos = iii+1;
|
||||
return true;
|
||||
}
|
||||
if (checkAvaillable(_data[iii], true) == true) {
|
||||
// we find an attibute == > create a new and parse it :
|
||||
ememory::SharedPtr<exml::Attribute> attribute = exml::Attribute::create();
|
||||
if (attribute == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
if (attribute->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listAttribute.push_back(attribute);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Text got end of file without finding end node");
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -7,6 +7,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/Node.h>
|
||||
#include <exml/AttributeList.h>
|
||||
|
||||
namespace exml {
|
||||
@ -14,40 +15,43 @@ namespace exml {
|
||||
* @brief Declaration node: <?XXXXXX ... >
|
||||
*/
|
||||
class Declaration : public exml::AttributeList {
|
||||
protected:
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _internalNode Internal Node to set data
|
||||
*/
|
||||
Declaration(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
Declaration(const exml::Declaration& _obj);
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _name name of the declaration (xml, xml:xxxx ...)
|
||||
*/
|
||||
Declaration(const std::string& _name="") :
|
||||
exml::AttributeList(_name) {
|
||||
|
||||
};
|
||||
public:
|
||||
Declaration(const std::string& _name="");
|
||||
/**
|
||||
* @brief Factory to create declaration
|
||||
* @param[in] _name name of the declaration (xml, xml:xxxx ...)
|
||||
* @return a structure declaration
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
static ememory::SharedPtr<Declaration> create(const std::string& _name="");
|
||||
public:
|
||||
enum nodeType getType() const override{
|
||||
return nodeType_attribute;
|
||||
};
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) override;
|
||||
ememory::SharedPtr<exml::Declaration> toDeclaration() override {
|
||||
return std::static_pointer_cast<exml::Declaration>(shared_from_this());
|
||||
};
|
||||
ememory::SharedPtr<const exml::Declaration> toDeclaration() const override {
|
||||
return std::static_pointer_cast<const exml::Declaration>(shared_from_this());
|
||||
};
|
||||
exml::Declaration& operator= (const exml::Declaration& _obj);
|
||||
};
|
||||
/**
|
||||
* @brief Declaration node: <?XML ... >
|
||||
*/
|
||||
class DeclarationXML : public exml::Declaration {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _internalNode Internal Node to set data
|
||||
*/
|
||||
DeclarationXML(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
DeclarationXML(const exml::DeclarationXML& _obj);
|
||||
/**
|
||||
* @brief Constructor for the generic declaration : <?xml version="" format="UTF-8"?>
|
||||
* @param[in] _version Xml version.
|
||||
@ -55,15 +59,11 @@ namespace exml {
|
||||
* @param[in] _standalone this document is standalone
|
||||
*/
|
||||
DeclarationXML(const std::string& _version, const std::string& _format = "UTF-8", bool _standalone = true);
|
||||
public:
|
||||
/**
|
||||
* @brief Factory to create XML declaration
|
||||
* @param[in] _version Xml version.
|
||||
* @param[in] _format charset of the XML
|
||||
* @param[in] _standalone this document is standalone
|
||||
* @return a structure declaration
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
static ememory::SharedPtr<DeclarationXML> create(const std::string& _version, const std::string& _format = "UTF-8", bool _standalone = true);
|
||||
exml::DeclarationXML& operator= (const exml::DeclarationXML& _obj);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -8,142 +8,113 @@
|
||||
|
||||
#include <exml/Document.h>
|
||||
#include <exml/debug.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <exml/internal/Document.h>
|
||||
|
||||
ememory::SharedPtr<exml::Document> exml::Document::create() {
|
||||
return ememory::SharedPtr<exml::Document>(new exml::Document());
|
||||
exml::Document::Document(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::Element(_internalNode) {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (m_data->isDocument() == false) {
|
||||
// try to set wrong type inside ... ==> remove it ...
|
||||
m_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
exml::Document::Document(const exml::Document& _obj) :
|
||||
exml::Element(_obj.m_data) {
|
||||
|
||||
}
|
||||
|
||||
exml::Document::Document() :
|
||||
m_caseSensitive(false),
|
||||
m_writeErrorWhenDetexted(true),
|
||||
m_comment(""),
|
||||
m_Line(""),
|
||||
m_filePos(0,0) {
|
||||
|
||||
exml::Element() {
|
||||
m_data = exml::internal::Document::create();
|
||||
}
|
||||
|
||||
|
||||
bool exml::Document::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] != nullptr) {
|
||||
m_listSub[iii]->iGenerate(_data, _indent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
exml::Document& exml::Document::operator= (const exml::Document& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool exml::Document::parse(const std::string& _data) {
|
||||
EXML_VERBOSE("Start parsing document (type: string) size=" << _data.size());
|
||||
clear();
|
||||
// came from char == > force in utf8 ...
|
||||
exml::FilePos filePos(1,0);
|
||||
m_pos = filePos;
|
||||
int32_t parsePos = 0;
|
||||
return subParse(_data, parsePos, m_caseSensitive, filePos, *this, true);
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not parse (nullptr) ...");
|
||||
return false;
|
||||
}
|
||||
return static_cast<exml::internal::Document*>(m_data.get())->parse(_data);
|
||||
}
|
||||
|
||||
bool exml::Document::generate(std::string& _data) {
|
||||
_data = "";
|
||||
return iGenerate(_data,0);
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not generate (nullptr) ...");
|
||||
return false;
|
||||
}
|
||||
return static_cast<exml::internal::Document*>(m_data.get())->generate(_data);
|
||||
}
|
||||
|
||||
bool exml::Document::load(const std::string& _file) {
|
||||
// Start loading the XML :
|
||||
EXML_VERBOSE("open file (xml) \"" << _file << "\"");
|
||||
clear();
|
||||
etk::FSNode tmpFile(_file);
|
||||
if (tmpFile.exist() == false) {
|
||||
EXML_ERROR("File Does not exist : " << _file);
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not load (nullptr) ...");
|
||||
return false;
|
||||
}
|
||||
int64_t fileSize = tmpFile.fileSize();
|
||||
if (fileSize == 0) {
|
||||
EXML_ERROR("This file is empty : " << _file);
|
||||
return false;
|
||||
}
|
||||
if (tmpFile.fileOpenRead() == false) {
|
||||
EXML_ERROR("Can not open (r) the file : " << _file);
|
||||
return false;
|
||||
}
|
||||
// allocate data
|
||||
std::vector<char> fileBuffer;
|
||||
fileBuffer.resize(fileSize+5, 0);
|
||||
// load data from the file :
|
||||
tmpFile.fileRead(&fileBuffer[0], 1, fileSize);
|
||||
// close the file:
|
||||
tmpFile.fileClose();
|
||||
|
||||
// convert in UTF8 :
|
||||
std::string tmpDataUnicode(&fileBuffer[0]);
|
||||
// parse the data :
|
||||
bool ret = parse(tmpDataUnicode);
|
||||
//Display();
|
||||
return ret;
|
||||
return static_cast<exml::internal::Document*>(m_data.get())->load(_file);
|
||||
}
|
||||
|
||||
bool exml::Document::store(const std::string& _file) {
|
||||
std::string createData;
|
||||
if (generate(createData) == false) {
|
||||
EXML_ERROR("Error while creating the XML : " << _file);
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not store (nullptr) ...");
|
||||
return false;
|
||||
}
|
||||
etk::FSNode tmpFile(_file);
|
||||
if (tmpFile.fileOpenWrite() == false) {
|
||||
EXML_ERROR("Can not open (w) the file : " << _file);
|
||||
return false;
|
||||
}
|
||||
if (tmpFile.fileWrite((char*)createData.c_str(), sizeof(char), createData.size()) != (int64_t)createData.size()) {
|
||||
EXML_ERROR("Error while writing output XML file : " << _file);
|
||||
tmpFile.fileClose();
|
||||
return false;
|
||||
}
|
||||
tmpFile.fileClose();
|
||||
return true;
|
||||
return static_cast<exml::internal::Document*>(m_data.get())->store(_file);
|
||||
}
|
||||
|
||||
void exml::Document::display() {
|
||||
std::string tmpp;
|
||||
iGenerate(tmpp, 0);
|
||||
EXML_INFO("Generated XML : \n" << tmpp);
|
||||
}
|
||||
|
||||
std::string createPosPointer(const std::string& _line, int32_t _pos) {
|
||||
std::string out;
|
||||
size_t iii;
|
||||
for (iii=0; (int64_t)iii<_pos && iii<_line.size(); iii++) {
|
||||
if (_line[iii] == '\t') {
|
||||
out += "\t";
|
||||
} else {
|
||||
out += " ";
|
||||
}
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not display (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
for (; (int64_t)iii<_pos; iii++) {
|
||||
out += " ";
|
||||
}
|
||||
out += "^";
|
||||
return out;
|
||||
static_cast<exml::internal::Document*>(m_data.get())->display();
|
||||
}
|
||||
|
||||
void exml::Document::displayError() {
|
||||
if (m_comment.size() == 0) {
|
||||
EXML_ERROR("No error detected ???");
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not displayError (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
EXML_ERROR(m_filePos << " " << m_comment << "\n"
|
||||
<< m_Line << "\n"
|
||||
<< createPosPointer(m_Line, m_filePos.getCol()) );
|
||||
#ifdef ENABLE_CRITICAL_WHEN_ERROR
|
||||
EXML_CRITICAL("detect error");
|
||||
#endif
|
||||
static_cast<exml::internal::Document*>(m_data.get())->displayError();
|
||||
}
|
||||
|
||||
void exml::Document::createError(const std::string& _data, int32_t _pos, const exml::FilePos& _filePos, const std::string& _comment) {
|
||||
m_comment = _comment;
|
||||
m_Line = etk::extract_line(_data, _pos);
|
||||
m_filePos = _filePos;
|
||||
if (m_writeErrorWhenDetexted== true) {
|
||||
displayError();
|
||||
|
||||
void exml::Document::setCaseSensitive(bool _val) {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not setCaseSensitive (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
static_cast<exml::internal::Document*>(m_data.get())->setCaseSensitive(_val);
|
||||
}
|
||||
|
||||
bool exml::Document::getCaseSensitive() const {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not getCaseSensitive (nullptr) ...");
|
||||
return false;
|
||||
}
|
||||
return static_cast<exml::internal::Document*>(m_data.get())->getCaseSensitive();
|
||||
}
|
||||
|
||||
void exml::Document::displayErrorWhenDetected() {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not displayErrorWhenDetected (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
static_cast<exml::internal::Document*>(m_data.get())->displayErrorWhenDetected();
|
||||
}
|
||||
|
||||
void exml::Document::notDisplayErrorWhenDetected() {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR("Can not notDisplayErrorWhenDetected (nullptr) ...");
|
||||
return;
|
||||
}
|
||||
static_cast<exml::internal::Document*>(m_data.get())->notDisplayErrorWhenDetected();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -16,32 +16,35 @@ namespace exml {
|
||||
*/
|
||||
class Document : public exml::Element {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _internalNode Internal Node to set data
|
||||
*/
|
||||
Document(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
Document(const exml::Document& _obj);
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Document();
|
||||
/**
|
||||
* @brief Factory on a document
|
||||
* @return an local created xml document
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
static ememory::SharedPtr<Document> create();
|
||||
private:
|
||||
bool m_caseSensitive; //!< check the case sensitive of the nodes and attribute
|
||||
public:
|
||||
exml::Document& operator= (const exml::Document& _obj);
|
||||
/**
|
||||
* @brief Enable or diasable the case sensitive (must be done before the call of parsing)
|
||||
* @param[in] _val true if enable; false else.
|
||||
*/
|
||||
virtual void setCaseSensitive(bool _val) {
|
||||
m_caseSensitive = _val;
|
||||
};
|
||||
void setCaseSensitive(bool _val);
|
||||
/**
|
||||
* @brief get the status of case sensitive mode.
|
||||
* @return true if case sensitive is active
|
||||
*/
|
||||
virtual bool getCaseSensitive() const {
|
||||
return m_caseSensitive;
|
||||
};
|
||||
virtual bool getCaseSensitive() const;
|
||||
public:
|
||||
/**
|
||||
* @brief parse a string that contain an XML
|
||||
@ -75,52 +78,17 @@ namespace exml {
|
||||
* @brief Display the Document on console
|
||||
*/
|
||||
void display();
|
||||
private:
|
||||
bool m_writeErrorWhenDetexted; //!< Request print error in parsing just when detected
|
||||
std::string m_comment; //!< Comment on the error
|
||||
std::string m_Line; //!< Parse line error (copy)
|
||||
exml::FilePos m_filePos; //!< position of the error
|
||||
public:
|
||||
/**
|
||||
* @brief Request display error when detected (not print only at the end ...)
|
||||
*/
|
||||
void displayErrorWhenDetected() {
|
||||
m_writeErrorWhenDetexted = true;
|
||||
}
|
||||
void displayErrorWhenDetected();
|
||||
/**
|
||||
* @brief Request NOT display error when detected.
|
||||
*/
|
||||
void notDisplayErrorWhenDetected() {
|
||||
m_writeErrorWhenDetexted = false;
|
||||
}
|
||||
/**
|
||||
* @brief Create an error in the parsing (call by the syetm for error management)
|
||||
* @param[in] _data string of chat is wrong
|
||||
* @param[in] _pos Position in the file
|
||||
* @param[in] _filePos human position of the error
|
||||
* @param[in] _comment Error string to display
|
||||
*/
|
||||
void createError(const std::string& _data, int32_t _pos, const exml::FilePos& _filePos, const std::string& _comment);
|
||||
void notDisplayErrorWhenDetected();
|
||||
/**
|
||||
* @brief request display in log of the error
|
||||
*/
|
||||
void displayError();
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return nodeType_document;
|
||||
}
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::Document> toDocument() override {
|
||||
return std::static_pointer_cast<exml::Document>(shared_from_this());
|
||||
}
|
||||
ememory::SharedPtr<const exml::Document> toDocument() const override {
|
||||
return std::static_pointer_cast<const exml::Document>(shared_from_this());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#define CREATE_ERROR(doc,data,pos,filePos,comment) \
|
||||
do { \
|
||||
EXML_ERROR(comment); \
|
||||
(doc).createError((data),(pos),(filePos),(comment)); \
|
||||
} while (0)
|
||||
|
514
exml/Element.cpp
514
exml/Element.cpp
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -8,478 +8,110 @@
|
||||
|
||||
#include <exml/Element.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/Text.h>
|
||||
#include <exml/Comment.h>
|
||||
#include <exml/Attribute.h>
|
||||
#include <exml/Declaration.h>
|
||||
#include <exml/Document.h>
|
||||
#include <exml/internal/Element.h>
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
|
||||
exml::Element::Element(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::AttributeList(_internalNode) {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (m_data->isElement() == false) {
|
||||
// try to set wrong type inside ... ==> remove it ...
|
||||
m_data = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Element> exml::Element::create(const std::string& _value) {
|
||||
return ememory::SharedPtr<exml::Element>(new exml::Element(_value));
|
||||
exml::Element::Element(const exml::Element& _obj) :
|
||||
exml::AttributeList(_obj.m_data) {
|
||||
|
||||
}
|
||||
|
||||
exml::Element::Element(const std::string& _data) :
|
||||
exml::AttributeList() {
|
||||
m_data = exml::internal::Element::create(_data);
|
||||
}
|
||||
|
||||
exml::Element& exml::Element::operator= (const exml::Element& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t exml::Element::size() const {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not get type ...");
|
||||
return 0;
|
||||
}
|
||||
return static_cast<exml::internal::Element*>(m_data.get())->size();
|
||||
}
|
||||
|
||||
|
||||
enum exml::nodeType exml::Element::getType(int32_t _id) const {
|
||||
ememory::SharedPtr<const exml::Node> tmpp = getNode(_id);
|
||||
if (tmpp == nullptr) {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not get type ...");
|
||||
return exml::nodeType_unknow;
|
||||
}
|
||||
return tmpp->getType();
|
||||
return static_cast<exml::internal::Element*>(m_data.get())->getType(_id);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Node> exml::Element::getNode(int32_t _id) {
|
||||
if (_id <0 || (size_t)_id>m_listSub.size()) {
|
||||
return nullptr;
|
||||
exml::Node exml::Element::operator[](int32_t _id) {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not get type ...");
|
||||
return exml::Node();
|
||||
}
|
||||
return m_listSub[_id];
|
||||
return exml::Node(static_cast<exml::internal::Element*>(m_data.get())->getNode(_id));
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Node> exml::Element::getNode(int32_t _id) const {
|
||||
if (_id <0 || (size_t)_id>m_listSub.size()) {
|
||||
return nullptr;
|
||||
const exml::Node exml::Element::operator[](int32_t _id) const {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not get type ...");
|
||||
return exml::Node();
|
||||
}
|
||||
return m_listSub[_id];
|
||||
return exml::Node(static_cast<exml::internal::Element*>(m_data.get())->getNode(_id));
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<exml::Element> exml::Element::getElement(int32_t _id) {
|
||||
ememory::SharedPtr<exml::Node> tmpp = getNode(_id);
|
||||
if (tmpp == nullptr) {
|
||||
return nullptr;
|
||||
exml::Element exml::Element::getNamed(const std::string& _name) {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not get type ...");
|
||||
return exml::Element();
|
||||
}
|
||||
return tmpp->toElement();
|
||||
return exml::Element(static_cast<exml::internal::Element*>(m_data.get())->getNamed(_name));
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Element> exml::Element::getElement(int32_t _id) const {
|
||||
ememory::SharedPtr<const exml::Node> tmpp = getNode(_id);
|
||||
if (tmpp == nullptr) {
|
||||
return nullptr;
|
||||
const exml::Element exml::Element::getNamed(const std::string& _name) const {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not get type ...");
|
||||
return exml::Element();
|
||||
}
|
||||
return tmpp->toElement();
|
||||
return exml::Element(static_cast<exml::internal::Element*>(m_data.get())->getNamed(_name));
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Element> exml::Element::getNamed(const std::string& _name) {
|
||||
if (_name.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if( m_listSub[iii] != nullptr
|
||||
&& m_listSub[iii]->getType() == exml::nodeType_element
|
||||
&& m_listSub[iii]->getValue() == _name) {
|
||||
if (m_listSub[iii] == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listSub[iii]->toElement();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Element> exml::Element::getNamed(const std::string& _name) const {
|
||||
if (_name.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if( m_listSub[iii] != nullptr
|
||||
&& m_listSub[iii]->getType() == exml::nodeType_element
|
||||
&& m_listSub[iii]->getValue() == _name) {
|
||||
if (m_listSub[iii] == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listSub[iii]->toElement();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void exml::Element::append(const ememory::SharedPtr<exml::Node>& _node) {
|
||||
if (_node == nullptr) {
|
||||
EXML_ERROR("Try to set an empty node");
|
||||
void exml::Element::append(const exml::Node& _node) {
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not APPEND on null element ...");
|
||||
return;
|
||||
}
|
||||
if (_node->getType() == exml::nodeType_attribute) {
|
||||
appendAttribute(_node->toAttribute());
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] == _node) {
|
||||
EXML_ERROR("Try to add a node that is already added before !!!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_listSub.push_back(_node);
|
||||
static_cast<exml::internal::Element*>(m_data.get())->append(_node.m_data);
|
||||
}
|
||||
|
||||
std::string exml::Element::getText() const {
|
||||
std::string res;
|
||||
if (m_listSub.size() == 1) {
|
||||
if (m_listSub[0]->getType() == nodeType_text) {
|
||||
res = m_listSub[0]->getValue();
|
||||
} else {
|
||||
m_listSub[0]->iGenerate(res, 0);
|
||||
}
|
||||
} else {
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] != nullptr) {
|
||||
m_listSub[iii]->iGenerate(res, 0);
|
||||
}
|
||||
}
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not APPEND on null element ...");
|
||||
return "";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool exml::Element::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
addIndent(_data, _indent);
|
||||
_data += "<";
|
||||
_data += m_value;
|
||||
exml::AttributeList::iGenerate(_data, _indent);
|
||||
|
||||
if (m_listSub.size()>0) {
|
||||
if( m_listSub.size() == 1
|
||||
&& m_listSub[0] != nullptr
|
||||
&& m_listSub[0]->getType() == exml::nodeType_text
|
||||
&& std::dynamic_pointer_cast<exml::Text>(m_listSub[0])->countLines() == 1) {
|
||||
_data += ">";
|
||||
m_listSub[0]->iGenerate(_data,0);
|
||||
EXML_VERBOSE(" generate : '" << _data << "'");
|
||||
} else {
|
||||
_data += ">\n";
|
||||
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] != nullptr) {
|
||||
m_listSub[iii]->iGenerate(_data, _indent+1);
|
||||
}
|
||||
}
|
||||
addIndent(_data, _indent);
|
||||
}
|
||||
_data += "</";
|
||||
_data += m_value;
|
||||
_data += ">\n";
|
||||
} else {
|
||||
_data += "/>\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool exml::Element::subParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc, bool _mainNode) {
|
||||
EXML_PARSE_ELEMENT(" start subParse ... " << _pos << " " << _filePos);
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
exml::FilePos tmpPos;
|
||||
if (_data[iii] == '<') {
|
||||
int32_t white = countWhiteChar(_data, iii+1, tmpPos);
|
||||
if (iii+white+1>=_data.size()) {
|
||||
_filePos+=tmpPos;
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<' char == > invalide XML");
|
||||
_pos = iii+white;
|
||||
return false;
|
||||
}
|
||||
// Detect type of the element:
|
||||
if(_data[iii+white+1] == '>') {
|
||||
_filePos+=tmpPos;
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find '>' with no element in the element...");
|
||||
_pos = iii+white+1;
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+1] == '?') {
|
||||
++tmpPos;
|
||||
// TODO : white space ...
|
||||
if(checkAvaillable(_data[iii+white+2], true) == false) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find unavaillable name in the Declaration node...");
|
||||
_pos = iii+white+1;
|
||||
return false;
|
||||
}
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
size_t endPosName = iii+white+1;
|
||||
// generate element name ...
|
||||
for (size_t jjj=iii+white+2; jjj<_data.size(); jjj++) {
|
||||
if(checkAvaillable(_data[jjj], false) == true) {
|
||||
// we find the end ...
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
std::string tmpname = std::string(_data, iii+white+2, endPosName+1-(iii+white+2));
|
||||
if (_caseSensitive == true) {
|
||||
tmpname = etk::tolower(tmpname);
|
||||
}
|
||||
// Find declaration balise
|
||||
ememory::SharedPtr<exml::Declaration> declaration = exml::Declaration::create(tmpname);
|
||||
if (declaration == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation Error...");
|
||||
return false;
|
||||
}
|
||||
_filePos += tmpPos;
|
||||
_pos = endPosName+1;
|
||||
if (declaration->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(declaration);
|
||||
continue;
|
||||
}
|
||||
if(_data[iii+white+1] == '!') {
|
||||
++tmpPos;
|
||||
// Find special block element
|
||||
if (iii+white+2>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+2] == '-') {
|
||||
++tmpPos;
|
||||
if (iii+white+3>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!-' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+3] != '-') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Element parse with '<!-") + _data[iii+3] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
++tmpPos;
|
||||
// find comment:
|
||||
ememory::SharedPtr<exml::Comment> comment = exml::Comment::create();
|
||||
if (comment == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+white+4;
|
||||
_filePos += tmpPos;
|
||||
if (comment->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(comment);
|
||||
} else if (_data[iii+white+2] == '[') {
|
||||
++tmpPos;
|
||||
if (iii+white+8>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<![' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii+white+3] != 'C'
|
||||
|| _data[iii+white+4] != 'D'
|
||||
|| _data[iii+white+5] != 'A'
|
||||
|| _data[iii+white+6] != 'T'
|
||||
|| _data[iii+white+7] != 'A'
|
||||
|| _data[iii+white+8] != '[') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Element parse with '<![") + _data[iii+white+3] + _data[iii+white+4] + _data[iii+white+5] + _data[iii+white+6] + _data[iii+white+7] + _data[iii+white+8] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
tmpPos+=6;
|
||||
// find text:
|
||||
ememory::SharedPtr<exml::TextCDATA> text = exml::TextCDATA::create();
|
||||
if (text == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+9+white;
|
||||
_filePos += tmpPos;
|
||||
if (text->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(text);
|
||||
} else {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("End file with '<!") + _data[iii+white+2] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(_data[iii+white+1] == '/') {
|
||||
++tmpPos;
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
size_t endPosName = iii+white+1;
|
||||
// generate element name ...
|
||||
for (size_t jjj=iii+white+2; jjj<_data.size(); jjj++) {
|
||||
if(checkAvaillable(_data[jjj], false) == true) {
|
||||
// we find the end ...
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
std::string tmpname = std::string(_data, iii+white+2, endPosName+1-(iii+white+2));
|
||||
if (_caseSensitive == true) {
|
||||
tmpname = etk::tolower(tmpname);
|
||||
}
|
||||
if( tmpname == m_value) {
|
||||
// find end of node :
|
||||
// find > element ...
|
||||
for (size_t jjj=endPosName+1; jjj<_data.size(); jjj++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[jjj], _filePos);
|
||||
#endif
|
||||
if (tmpPos.check(_data[jjj]) == true) {
|
||||
continue;
|
||||
}
|
||||
if(_data[jjj] == '>') {
|
||||
_pos = jjj;
|
||||
_filePos += tmpPos;
|
||||
return true;
|
||||
} else if( _data[jjj] != '\r'
|
||||
&& _data[jjj] != ' '
|
||||
&& _data[jjj] != '\t') {
|
||||
_filePos += tmpPos;
|
||||
CREATE_ERROR(_doc, _data, jjj, _filePos, std::string("End node error : have data inside end node other than [ \\n\\t\\r] ") + m_value + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("End node error : '") + tmpname + "' != '" + m_value + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (_data[iii+white+1] == '>') {
|
||||
// end of something == > this is really bad
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find '>' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkAvaillable(_data[iii+white+1], true) == true) {
|
||||
++tmpPos;
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
size_t endPosName = iii+white+1;
|
||||
// generate element name ...
|
||||
for (size_t jjj=iii+white+2; jjj<_data.size(); jjj++) {
|
||||
if(checkAvaillable(_data[jjj], false) == true) {
|
||||
// we find the end ...
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
std::string tmpname = std::string(_data, iii+white+1, endPosName+1-(iii+white+1));
|
||||
if (_caseSensitive == true) {
|
||||
etk::tolower(tmpname);
|
||||
}
|
||||
//EXML_INFO("find node named : '" << tmpname << "'");
|
||||
// find text:
|
||||
ememory::SharedPtr<exml::Element> element = exml::Element::create(tmpname);
|
||||
if (element == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = endPosName+1;
|
||||
_filePos += tmpPos;
|
||||
if (element->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(element);
|
||||
continue;
|
||||
}
|
||||
_filePos+=tmpPos;
|
||||
// here we have an error :
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Find an ununderstanding element : '") + _data[iii+white+1] + "'");
|
||||
return false;
|
||||
} else {
|
||||
if (_data[iii] == '>') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find elemement '>' == > no reason to be here ...");
|
||||
return false;
|
||||
}
|
||||
// might to be data text ...
|
||||
if( _data[iii] == '\n'
|
||||
|| _data[iii] == ' '
|
||||
|| _data[iii] == '\t'
|
||||
|| _data[iii] == '\r') {
|
||||
// empty spaces == > nothing to do ....
|
||||
} else {
|
||||
// find data == > parse it...
|
||||
ememory::SharedPtr<exml::Text> text = exml::Text::create();
|
||||
if (text == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
_filePos += tmpPos;
|
||||
if (text->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_mainNode == true) {
|
||||
return true;
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Did not find end of the exml::Element : '") + m_value + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::Element::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) {
|
||||
EXML_PARSE_ELEMENT("start parse : 'element' named='" << m_value << "'");
|
||||
// note : When start parsing the upper element must have set the value of the element and set the position after this one
|
||||
m_pos=_filePos;
|
||||
// find a normal node ...
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if(_data[iii] == '>') {
|
||||
// we find the end ...
|
||||
_pos = iii+1;
|
||||
return exml::Element::subParse(_data, _pos, _caseSensitive, _filePos, _doc, false);
|
||||
}
|
||||
if (_data[iii] == '/') {
|
||||
// standalone node or error...
|
||||
if (iii+1>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find end of files ... == > bad case");
|
||||
return false;
|
||||
}
|
||||
// TODO : Can have white spaces ....
|
||||
if (_data[iii+1] == '>') {
|
||||
_pos = iii+1;
|
||||
return true;
|
||||
}
|
||||
// error
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find / without > char ...");
|
||||
return false;
|
||||
}
|
||||
if (checkAvaillable(_data[iii], true) == true) {
|
||||
// we find an attibute == > create a new and parse it :
|
||||
ememory::SharedPtr<exml::Attribute> attribute = exml::Attribute::create();
|
||||
if (attribute == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
if (attribute->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listAttribute.push_back(attribute);
|
||||
continue;
|
||||
}
|
||||
if (isWhiteChar(_data[iii]) == false) {
|
||||
CREATE_ERROR(_doc, _data, iii, _filePos, std::string("Find an unknow element : '") + _data[iii] + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Unexpecting end of parsing exml::Element : '") + m_value + "' == > check if the '/>' is set or the end of element");
|
||||
return false;
|
||||
return static_cast<exml::internal::Element*>(m_data.get())->getText();
|
||||
}
|
||||
|
||||
void exml::Element::clear() {
|
||||
exml::AttributeList::clear();
|
||||
m_listSub.clear();
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not CLEAR on null element ...");
|
||||
return;
|
||||
}
|
||||
static_cast<exml::internal::Element*>(m_data.get())->clear();
|
||||
}
|
||||
|
||||
|
||||
#include <exml/details/iterator.hxx>
|
||||
|
||||
template class exml::iterator<exml::Element, exml::Node>;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -10,47 +10,44 @@
|
||||
#include <exml/Node.h>
|
||||
#include <vector>
|
||||
#include <exml/AttributeList.h>
|
||||
#include <exml/iterator.h>
|
||||
|
||||
namespace exml {
|
||||
/**
|
||||
* @brief Basic element Node of an XML document <YYYYY>
|
||||
*/
|
||||
class Element : public exml::AttributeList {
|
||||
protected:
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _internalNode Internal Node to set data
|
||||
*/
|
||||
Element() { };
|
||||
Element(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
Element(const exml::Element& _obj);
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _value Element name;
|
||||
*/
|
||||
Element(const std::string& _value) :
|
||||
exml::AttributeList(_value) {
|
||||
|
||||
};
|
||||
public:
|
||||
Element(const std::string& _value="");
|
||||
/**
|
||||
* @brief factory of an exml::Element
|
||||
* @param[in] _value Name of the node.
|
||||
* @return Shared pointer on the Element
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
static ememory::SharedPtr<Element> create(const std::string& _value="");
|
||||
protected:
|
||||
std::vector<ememory::SharedPtr<exml::Node>> m_listSub; //!< List of subNodes
|
||||
public:
|
||||
exml::Element& operator= (const exml::Element& _obj);
|
||||
/**
|
||||
* @brief get the number of sub element in the node (can be exml::Comment ; exml::Element ; exml::Text :exml::Declaration).
|
||||
* @return a number >=0.
|
||||
*/
|
||||
size_t size() const {
|
||||
return m_listSub.size();
|
||||
};
|
||||
size_t size() const;
|
||||
/**
|
||||
* @brief add a node at the element (not exml::Attribute (move in the attribute automaticly).
|
||||
* @param[in] _node Pointer of the node to add.
|
||||
*/
|
||||
void append(const ememory::SharedPtr<exml::Node>& _node);
|
||||
void append(const exml::Node& _node);
|
||||
/**
|
||||
* @brief get the type of the element id.
|
||||
* @param[in] _id Id of the element.
|
||||
@ -62,73 +59,40 @@ namespace exml {
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on node.
|
||||
*/
|
||||
ememory::SharedPtr<Node> getNode(int32_t _id);
|
||||
exml::Node operator[] (int32_t _id);
|
||||
/**
|
||||
* @brief get the Node pointer of the element id.
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on node.
|
||||
*/
|
||||
ememory::SharedPtr<const Node> getNode(int32_t _id) const;
|
||||
/**
|
||||
* @brief get the element casted in Element (if the node is not an element return NULL).
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<Element> getElement(int32_t _id);
|
||||
/**
|
||||
* @brief get the element casted in Element (if the node is not an element return NULL).
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<const Element> getElement(int32_t _id) const;
|
||||
const exml::Node operator[] (int32_t _id) const;
|
||||
/**
|
||||
* @brief get an element with his name (work only with exml::Element)
|
||||
* @param[in] _name Name of the element that is requested
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<Element> getNamed(const std::string& _name);
|
||||
exml::Element getNamed(const std::string& _name);
|
||||
/**
|
||||
* @brief get an element with his name (work only with exml::Element)
|
||||
* @param[in] _name Name of the element that is requested
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<const Element> getNamed(const std::string& _name) const;
|
||||
const exml::Element getNamed(const std::string& _name) const;
|
||||
/**
|
||||
* @brief get the internal data of the element (if the element has some sub node thay are converted in xml string == > like this it is not needed to use <![CDATA[...]]>
|
||||
* @return the curent data string. if Only one text node, then we get the parssed data (no & ...) if more than one node, then we transform &,",',<,> in xml normal text...
|
||||
*/
|
||||
std::string getText() const;
|
||||
protected:
|
||||
/**
|
||||
* @brief Parse sub node string
|
||||
* @param[in] _data all file string data
|
||||
* @param[in,out] _pos Position to start parsing in the file and return the end of parsing
|
||||
* @param[in] _caseSensitive Case sensitive parsing (usefull for html)
|
||||
* @param[in] _filePos Current File position of the parsing
|
||||
* @param[in] _doc Document base reference
|
||||
* @param[in] _mainNode if true, this is the first root node
|
||||
* @return true parsing is done OK
|
||||
* @return false An error appear in the parsing
|
||||
*/
|
||||
bool subParse(const std::string& _data,
|
||||
int32_t& _pos,
|
||||
bool _caseSensitive,
|
||||
exml::FilePos& _filePos,
|
||||
exml::Document& _doc,
|
||||
bool _mainNode=false);
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return nodeType_element;
|
||||
}
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::Element> toElement() override {
|
||||
return std::static_pointer_cast<exml::Element>(shared_from_this());
|
||||
}
|
||||
ememory::SharedPtr<const exml::Element> toElement() const override {
|
||||
return std::static_pointer_cast<const exml::Element>(shared_from_this());
|
||||
}
|
||||
void clear() override;
|
||||
public:
|
||||
using iterator = exml::iterator<exml::Element, exml::Node>;
|
||||
iterator begin() {
|
||||
return iterator(*this, 0);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(*this, size());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
94
exml/FilePos.cpp
Normal file
94
exml/FilePos.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#include <exml/FilePos.h>
|
||||
|
||||
exml::FilePos::FilePos() :
|
||||
m_col(0),
|
||||
m_line(0) {
|
||||
|
||||
}
|
||||
|
||||
exml::FilePos::FilePos(size_t _line, size_t _col) :
|
||||
m_col(_col),
|
||||
m_line(_line) {
|
||||
|
||||
}
|
||||
|
||||
exml::FilePos& exml::FilePos::operator ++() {
|
||||
m_col++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
exml::FilePos& exml::FilePos::operator --() {
|
||||
if(m_col>0) {
|
||||
m_col--;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
exml::FilePos& exml::FilePos::operator +=(const exml::FilePos& _obj) {
|
||||
if (_obj.m_line == 0) {
|
||||
m_col += _obj.m_col;
|
||||
} else {
|
||||
m_col = _obj.m_col;
|
||||
m_line += _obj.m_line;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
exml::FilePos& exml::FilePos::operator +=(size_t _col) {
|
||||
m_col += _col;
|
||||
return *this;
|
||||
}
|
||||
|
||||
exml::FilePos& exml::FilePos::operator= (const exml::FilePos& _obj ) {
|
||||
m_col = _obj.m_col;
|
||||
m_line = _obj.m_line;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void exml::FilePos::newLine() {
|
||||
m_col=0;
|
||||
m_line++;
|
||||
}
|
||||
|
||||
bool exml::FilePos::check(char32_t _val) {
|
||||
m_col++;
|
||||
if (_val == '\n') {
|
||||
newLine();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void exml::FilePos::set(size_t _line, size_t _col) {
|
||||
m_col = _col;
|
||||
m_line = _line;
|
||||
}
|
||||
|
||||
void exml::FilePos::clear() {
|
||||
m_col = 0;
|
||||
m_line = 0;
|
||||
}
|
||||
|
||||
size_t exml::FilePos::getCol() const {
|
||||
return m_col;
|
||||
}
|
||||
|
||||
size_t exml::FilePos::getLine() const {
|
||||
return m_line;
|
||||
}
|
||||
|
||||
std::ostream& exml::operator <<(std::ostream& _os, const exml::FilePos& _obj) {
|
||||
_os << "(l=";
|
||||
_os << _obj.getLine();
|
||||
_os << ",c=";
|
||||
_os << _obj.getCol();
|
||||
_os << ")";
|
||||
return _os;
|
||||
}
|
95
exml/FilePos.h
Normal file
95
exml/FilePos.h
Normal file
@ -0,0 +1,95 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.h>
|
||||
|
||||
namespace exml {
|
||||
/**
|
||||
* @brief Position in the file of the original data.
|
||||
*/
|
||||
class FilePos {
|
||||
private:
|
||||
size_t m_col; //!< source text colomn
|
||||
size_t m_line; //!< source Line colomn
|
||||
public:
|
||||
/**
|
||||
* @brief default contructor (set line and col at 0)
|
||||
*/
|
||||
FilePos();
|
||||
/**
|
||||
* @brief initialize constructor
|
||||
* @param[in] _line Line in the file
|
||||
* @param[in] _col Colomn in the file
|
||||
*/
|
||||
FilePos(size_t _line, size_t _col);
|
||||
/**
|
||||
* @brief Increment the colomn position
|
||||
* @return Reference on this
|
||||
*/
|
||||
FilePos& operator ++();
|
||||
/**
|
||||
* @brief Decrement the colomn position
|
||||
* @return Reference on this
|
||||
*/
|
||||
FilePos& operator --();
|
||||
/**
|
||||
* @brief Addition operator
|
||||
* @param[in] _obj Addition object..
|
||||
* @return Reference on this
|
||||
*/
|
||||
FilePos& operator +=(const FilePos& _obj);
|
||||
/**
|
||||
* @brief Colomn addition operator
|
||||
* @param[in] _col Number of colomn to add
|
||||
* @return Reference on this
|
||||
*/
|
||||
FilePos& operator +=(size_t _col);
|
||||
/**
|
||||
* @brief Asignment operator
|
||||
* @param[in] _obj Object to copy
|
||||
* @return Reference on this
|
||||
*/
|
||||
FilePos& operator= (const FilePos& _obj);
|
||||
/**
|
||||
* @brief Find a new line & reset colomn at 0
|
||||
*/
|
||||
void newLine();
|
||||
/**
|
||||
* @brief Check if the value is a new line and update internal property
|
||||
* @param[in] _val Char value to check
|
||||
* @return true We find a new line
|
||||
* @return false We NOT find a new line
|
||||
*/
|
||||
bool check(char32_t _val);
|
||||
/**
|
||||
* @brief Setter of specific data
|
||||
* @param[in] _line Line in the file
|
||||
* @param[in] _col Colomn in the file
|
||||
*/
|
||||
void set(size_t _line, size_t _col);
|
||||
/**
|
||||
* @brief Reset position at 0,0
|
||||
*/
|
||||
void clear();
|
||||
/**
|
||||
* @brief Get the colomn position
|
||||
* @return Colomn in number of utf8-char
|
||||
*/
|
||||
size_t getCol() const;
|
||||
/**
|
||||
* @brief Get the line number position
|
||||
* @return line ID (start at 0)
|
||||
*/
|
||||
size_t getLine() const;
|
||||
};
|
||||
//! @not-in-doc
|
||||
std::ostream& operator <<(std::ostream& _os, const FilePos& _obj);
|
||||
|
||||
}
|
||||
|
225
exml/Node.cpp
225
exml/Node.cpp
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -7,197 +7,168 @@
|
||||
*/
|
||||
|
||||
#include <exml/Node.h>
|
||||
#include <exml/internal/Node.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/Attribute.h>
|
||||
#include <exml/Comment.h>
|
||||
#include <exml/Declaration.h>
|
||||
#include <exml/Document.h>
|
||||
#include <exml/Element.h>
|
||||
#include <exml/Text.h>
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
exml::Node::Node(const std::string& _value) :
|
||||
m_pos(0,0),
|
||||
m_value(_value) {
|
||||
// nothing to do.
|
||||
std::ostream& exml::operator <<(std::ostream& _os, const exml::Node& _obj) {
|
||||
_os << "{";
|
||||
_os << "Node XML: " << _obj.getType();
|
||||
if (_obj.isElement() == true) {
|
||||
_os << " <" << _obj.getValue() << ">";
|
||||
};
|
||||
_os << "}";
|
||||
return _os;
|
||||
}
|
||||
|
||||
|
||||
void exml::Node::addIndent(std::string& _data, int32_t _indent) const {
|
||||
for (int32_t iii=0; iii<_indent; iii++) {
|
||||
_data += "\t";
|
||||
}
|
||||
exml::Node::Node(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
m_data(_internalNode) {
|
||||
// nothing to DO ...
|
||||
}
|
||||
|
||||
void exml::Node::drawElementParsed(char32_t _val, const exml::FilePos& _filePos) const {
|
||||
if (_val == '\n') {
|
||||
EXML_DEBUG(_filePos << " parse '\\n'");
|
||||
} else if (_val == '\t') {
|
||||
EXML_DEBUG(_filePos << " parse '\\t'");
|
||||
} else {
|
||||
EXML_DEBUG(_filePos << " parse '" << _val << "'");
|
||||
}
|
||||
exml::Node::Node() :
|
||||
m_data(nullptr) {
|
||||
|
||||
}
|
||||
|
||||
bool exml::Node::checkAvaillable(char32_t _val, bool _firstChar) const {
|
||||
if( _val == '!'
|
||||
|| _val == '"'
|
||||
|| _val == '#'
|
||||
|| _val == '$'
|
||||
|| _val == '%'
|
||||
|| _val == '&'
|
||||
|| _val == '\'' // '
|
||||
|| _val == '('
|
||||
|| _val == ')'
|
||||
|| _val == '*'
|
||||
|| _val == '+'
|
||||
|| _val == ','
|
||||
|| _val == '/'
|
||||
|| _val == ';'
|
||||
|| _val == '<'
|
||||
|| _val == '='
|
||||
|| _val == '>'
|
||||
|| _val == '?'
|
||||
|| _val == '@'
|
||||
|| _val == '['
|
||||
|| _val == '\\'
|
||||
|| _val == ']'
|
||||
|| _val == '^'
|
||||
|| _val == '`'
|
||||
|| _val == '{'
|
||||
|| _val == '|'
|
||||
|| _val == '}'
|
||||
|| _val == '~'
|
||||
|| _val == ' '
|
||||
|| _val == '\n'
|
||||
|| _val == '\t'
|
||||
|| _val == '\r') {
|
||||
bool exml::Node::exist() {
|
||||
if (m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (_firstChar == true) {
|
||||
if( _val == '-'
|
||||
|| _val == '.'
|
||||
|| ( _val >= '0'
|
||||
&& _val <= '9') ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32_t exml::Node::countWhiteChar(const std::string& _data, int32_t _pos, exml::FilePos& _filePos) const {
|
||||
_filePos.clear();
|
||||
int32_t white=0;
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
if(isWhiteChar(_data[iii]) == true) {
|
||||
white++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
exml::FilePos exml::Node::getPos() const {
|
||||
if (m_data == nullptr) {
|
||||
return exml::FilePos(0,0);
|
||||
}
|
||||
--_filePos;
|
||||
return white;
|
||||
}
|
||||
|
||||
bool exml::Node::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
const exml::FilePos& exml::Node::getPos() const {
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
void exml::Node::clear() {
|
||||
m_value = "";
|
||||
m_pos.clear();
|
||||
return m_data->getPos();
|
||||
}
|
||||
|
||||
void exml::Node::setValue(std::string _value) {
|
||||
m_value = _value;
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not set value: '" << _value << "'");
|
||||
return;
|
||||
}
|
||||
m_data->setValue(_value);
|
||||
}
|
||||
|
||||
const std::string& exml::Node::getValue() const {
|
||||
return m_value;
|
||||
if (m_data == nullptr) {
|
||||
static std::string errorString = "";
|
||||
EXML_ERROR(" can not get value ...");
|
||||
return errorString;
|
||||
}
|
||||
return m_data->getValue();
|
||||
}
|
||||
|
||||
enum exml::nodeType exml::Node::getType() const {
|
||||
return nodeType_node;
|
||||
if (m_data == nullptr) {
|
||||
EXML_ERROR(" can not get type ...");
|
||||
return exml::nodeType_unknow;
|
||||
}
|
||||
return m_data->getType();
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Document> exml::Node::toDocument() {
|
||||
return nullptr;
|
||||
exml::Document exml::Node::toDocument() {
|
||||
return exml::Document(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Document> exml::Node::toDocument() const {
|
||||
return nullptr;
|
||||
const exml::Document exml::Node::toDocument() const {
|
||||
return exml::Document(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Attribute> exml::Node::toAttribute() {
|
||||
return nullptr;
|
||||
exml::Attribute exml::Node::toAttribute() {
|
||||
return exml::Attribute(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Attribute> exml::Node::toAttribute() const {
|
||||
return nullptr;
|
||||
const exml::Attribute exml::Node::toAttribute() const {
|
||||
return exml::Attribute(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Comment> exml::Node::toComment() {
|
||||
return nullptr;
|
||||
exml::Comment exml::Node::toComment() {
|
||||
return exml::Comment(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Comment> exml::Node::toComment() const {
|
||||
return nullptr;
|
||||
const exml::Comment exml::Node::toComment() const {
|
||||
return exml::Comment(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Declaration> exml::Node::toDeclaration() {
|
||||
return nullptr;
|
||||
exml::Declaration exml::Node::toDeclaration() {
|
||||
return exml::Declaration(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Declaration> exml::Node::toDeclaration() const {
|
||||
return nullptr;
|
||||
const exml::Declaration exml::Node::toDeclaration() const {
|
||||
return exml::Declaration(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Element> exml::Node::toElement() {
|
||||
return nullptr;
|
||||
exml::Element exml::Node::toElement() {
|
||||
return exml::Element(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Element> exml::Node::toElement() const {
|
||||
return nullptr;
|
||||
const exml::Element exml::Node::toElement() const {
|
||||
return exml::Element(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Text> exml::Node::toText() {
|
||||
return nullptr;
|
||||
exml::Text exml::Node::toText() {
|
||||
return exml::Text(m_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::Text> exml::Node::toText() const{
|
||||
return nullptr;
|
||||
const exml::Text exml::Node::toText() const {
|
||||
return exml::Text(m_data);
|
||||
}
|
||||
|
||||
bool exml::Node::isDocument() const {
|
||||
return getType() == exml::nodeType_document;
|
||||
if (m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return m_data->isDocument();
|
||||
}
|
||||
|
||||
bool exml::Node::isAttribute() const {
|
||||
return getType() == exml::nodeType_attribute;
|
||||
if (m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return m_data->isAttribute();
|
||||
}
|
||||
|
||||
bool exml::Node::isComment() const {
|
||||
return getType() == exml::nodeType_comment;
|
||||
if (m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return m_data->isComment();
|
||||
}
|
||||
|
||||
bool exml::Node::isDeclaration() const {
|
||||
return getType() == exml::nodeType_declaration;
|
||||
if (m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return m_data->isDeclaration();
|
||||
}
|
||||
|
||||
bool exml::Node::isElement() const {
|
||||
return getType() == exml::nodeType_element;
|
||||
if (m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return m_data->isElement();
|
||||
}
|
||||
|
||||
bool exml::Node::isText() const {
|
||||
return getType() == exml::nodeType_text;
|
||||
if (m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return m_data->isText();
|
||||
}
|
||||
|
||||
void exml::Node::clear() {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
return m_data->clear();
|
||||
}
|
||||
|
138
exml/Node.h
138
exml/Node.h
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -11,60 +11,38 @@
|
||||
#include <etk/types.h>
|
||||
#include <etk/math/Vector2D.h>
|
||||
#include <exml/FilePos.h>
|
||||
#include <exml/internal/Node.h>
|
||||
#include <exml/nodeType.h>
|
||||
|
||||
/**
|
||||
* @brief exml namespace containing all function for XML interpretor
|
||||
*/
|
||||
namespace exml {
|
||||
//#define ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
//#define ENABLE_CRITICAL_WHEN_ERROR
|
||||
#if 1
|
||||
#define EXML_PARSE_ELEMENT EXML_VERBOSE
|
||||
#else
|
||||
#define EXML_PARSE_ELEMENT EXML_DEBUG
|
||||
#endif
|
||||
#if 1
|
||||
#define EXML_PARSE_ATTRIBUTE EXML_VERBOSE
|
||||
#else
|
||||
#define EXML_PARSE_ATTRIBUTE EXML_DEBUG
|
||||
#endif
|
||||
class Document;
|
||||
class Attribute;
|
||||
class Comment;
|
||||
class Declaration;
|
||||
class Element;
|
||||
class Text;
|
||||
|
||||
/**
|
||||
* @brief Type of the XML elements.
|
||||
*/
|
||||
enum nodeType {
|
||||
nodeType_unknow, //!< might be an error ...
|
||||
nodeType_node, //!< might be an error ...
|
||||
nodeType_document, //!< all the file main access
|
||||
nodeType_declaration, //!< <?xml ... ?>
|
||||
nodeType_attribute, //!< the <Element ATTRIBUTE="ATTRIBUTE_VALUE" />
|
||||
nodeType_element, //!< the <XXX> ... </XXX>
|
||||
nodeType_comment, //!< comment node : <!-- -->
|
||||
nodeType_text, //!< <XXX> InsideText </XXX>
|
||||
};
|
||||
class AttributeListData;
|
||||
/**
|
||||
* @brief Basic main object of all xml elements.
|
||||
*/
|
||||
class Node : public ememory::EnableSharedFromThis<Node>{
|
||||
class Node {
|
||||
friend class exml::Element;
|
||||
friend class exml::AttributeListData;
|
||||
protected:
|
||||
/**
|
||||
* @brief basic element of a xml structure
|
||||
*/
|
||||
Node() :
|
||||
m_pos(0,0) {
|
||||
|
||||
};
|
||||
ememory::SharedPtr<exml::internal::Node> m_data; //< internal reference on a node
|
||||
public:
|
||||
/**
|
||||
* @brief basic element of a xml structure
|
||||
* @param[in] _value value of the node
|
||||
*/
|
||||
Node(const std::string& _value);
|
||||
Node(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief basic element of a xml structure
|
||||
*/
|
||||
Node();
|
||||
public:
|
||||
/**
|
||||
* @brief Virtualize destructor
|
||||
@ -72,33 +50,14 @@ namespace exml {
|
||||
virtual ~Node() = default;
|
||||
public:
|
||||
/**
|
||||
* @brief parse the Current node [pure VIRUAL]
|
||||
* @param[in] _data data string to parse.
|
||||
* @param[in,out] _pos position in the string to start parse, return the position end of parsing.
|
||||
* @param[in] _caseSensitive Request a parsion of element that is not case sensitive (all element is in low case)
|
||||
* @param[in,out] _filePos file parsing position (line x col x)
|
||||
* @param[in,out] _doc Base document reference
|
||||
* @return false if an error occured.
|
||||
* @brief Check if the element exit
|
||||
*/
|
||||
virtual bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) = 0;
|
||||
/**
|
||||
* @brief generate a string with the tree of the xml
|
||||
* @param[in,out] _data string where to add the elements
|
||||
* @param[in] _indent current indentation of the file
|
||||
* @return false if an error occured.
|
||||
*/
|
||||
virtual bool iGenerate(std::string& _data, int32_t _indent) const;
|
||||
protected:
|
||||
exml::FilePos m_pos; //!< position in the readed file == > not correct when the file is generated
|
||||
public:
|
||||
bool exist();
|
||||
/**
|
||||
* @brief get the current position where the element is in the file
|
||||
* @return The file position reference
|
||||
*/
|
||||
const exml::FilePos& getPos() const;
|
||||
protected:
|
||||
std::string m_value; //!< value of the node (for element this is the name, for text it is the inside text ...)
|
||||
public:
|
||||
exml::FilePos getPos() const;
|
||||
/**
|
||||
* @brief set the value of the node.
|
||||
* @param[in] _value New value of the node.
|
||||
@ -108,104 +67,72 @@ namespace exml {
|
||||
* @brief get the current element Value.
|
||||
* @return the reference of the string value.
|
||||
*/
|
||||
virtual const std::string& getValue() const;
|
||||
public:
|
||||
const std::string& getValue() const;
|
||||
/**
|
||||
* @brief get the node type.
|
||||
* @return the type of the Node.
|
||||
*/
|
||||
virtual enum nodeType getType() const;
|
||||
protected:
|
||||
/**
|
||||
* @brief add indentation of the string input.
|
||||
* @param[in,out] _data String where the indentation is done.
|
||||
* @param[in] _indent Number of tab to add at the string.
|
||||
*/
|
||||
void addIndent(std::string& _data, int32_t _indent) const;
|
||||
/**
|
||||
* @brief Display the cuurent element that is curently parse.
|
||||
* @param[in] _val Char that is parsed.
|
||||
* @param[in] _filePos Position of the char in the file.
|
||||
*/
|
||||
void drawElementParsed(char32_t _val, const exml::FilePos& _filePos) const;
|
||||
/**
|
||||
* @brief check if an element or attribute is availlable (not : !"#$%&'()*+,/;<=>?@[\]^`{|}~ \\n\\t\\r and for first char : not -.0123456789).
|
||||
* @param[in] _val Value to check the conformity.
|
||||
* @param[in] _firstChar True if the element check is the first char.
|
||||
* @return true The value can be a part of attribute name
|
||||
* @return false The value can NOT be a part of attribute name
|
||||
*/
|
||||
bool checkAvaillable(char32_t _val, bool _firstChar) const;
|
||||
/**
|
||||
* @brief count the number of white char in the string from the specify position (stop at the first element that is not a white char)
|
||||
* @param[in] _data Data to parse.
|
||||
* @param[in] _pos Start position in the string.
|
||||
* @param[out] _filePos new poistion of te file to add.
|
||||
* @return number of white element.
|
||||
*/
|
||||
int32_t countWhiteChar(const std::string& _data, int32_t _pos, exml::FilePos& _filePos) const;
|
||||
public:
|
||||
enum nodeType getType() const;
|
||||
/**
|
||||
* @brief Cast the element in a Document if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::Document> toDocument();
|
||||
exml::Document toDocument();
|
||||
/**
|
||||
* @brief Cast the element in a Document if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::Document> toDocument() const;
|
||||
const exml::Document toDocument() const;
|
||||
/**
|
||||
* @brief Cast the element in a Attribute if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::Attribute> toAttribute();
|
||||
exml::Attribute toAttribute();
|
||||
/**
|
||||
* @brief Cast the element in a Attribute if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::Attribute> toAttribute() const;
|
||||
const exml::Attribute toAttribute() const;
|
||||
/**
|
||||
* @brief Cast the element in a Comment if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::Comment> toComment();
|
||||
exml::Comment toComment();
|
||||
/**
|
||||
* @brief Cast the element in a Comment if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::Comment> toComment() const;
|
||||
const exml::Comment toComment() const;
|
||||
/**
|
||||
* @brief Cast the element in a Declaration if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::Declaration> toDeclaration();
|
||||
exml::Declaration toDeclaration();
|
||||
/**
|
||||
* @brief Cast the element in a Declaration if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::Declaration> toDeclaration() const;
|
||||
const exml::Declaration toDeclaration() const;
|
||||
/**
|
||||
* @brief Cast the element in a Element if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::Element> toElement();
|
||||
exml::Element toElement();
|
||||
/**
|
||||
* @brief Cast the element in a Element if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::Element> toElement() const;
|
||||
const exml::Element toElement() const;
|
||||
/**
|
||||
* @brief Cast the element in a Text if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::Text> toText();
|
||||
exml::Text toText();
|
||||
/**
|
||||
* @brief Cast the element in a Text if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::Text> toText() const;
|
||||
|
||||
const exml::Text toText() const;
|
||||
/**
|
||||
* @brief check if the node is a exml::Document
|
||||
* @return true if the node is a exml::Document
|
||||
@ -236,10 +163,11 @@ namespace exml {
|
||||
* @return true if the node is a exml::Text
|
||||
*/
|
||||
bool isText() const;
|
||||
|
||||
/**
|
||||
* @brief clear the Node
|
||||
*/
|
||||
virtual void clear();
|
||||
};
|
||||
//! @not_in_doc
|
||||
std::ostream& operator <<(std::ostream& _os, const exml::Node& _obj);
|
||||
}
|
||||
|
156
exml/Text.cpp
156
exml/Text.cpp
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -7,147 +7,33 @@
|
||||
*/
|
||||
|
||||
#include <exml/Text.h>
|
||||
#include <exml/internal/Text.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/Document.h>
|
||||
#include <regex>
|
||||
|
||||
// transform the Text with :
|
||||
// "<" == "<"
|
||||
// ">" == ">"
|
||||
// "&" == "&"
|
||||
// "'" == "'"
|
||||
// """ == """
|
||||
static std::string replaceSpecialChar(const std::string& _inval) {
|
||||
std::string out;
|
||||
static std::regex regexLT("<");
|
||||
static std::regex regexGT(">");
|
||||
static std::regex regexAPOS("'");
|
||||
static std::regex regexQUOT(""");
|
||||
static std::regex regexAMP("&");
|
||||
exml::Text::Text(ememory::SharedPtr<exml::internal::Node> _internalNode) :
|
||||
exml::Node(_internalNode) {
|
||||
if (m_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (m_data->isText() == false) {
|
||||
// try to set wrong type inside ... ==> remove it ...
|
||||
m_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
exml::Text::Text(const exml::Text& _obj) :
|
||||
exml::Node(_obj.m_data) {
|
||||
|
||||
out = std::regex_replace(_inval, regexLT, std::string("<"));
|
||||
out = std::regex_replace(out, regexGT, std::string(">"));
|
||||
out = std::regex_replace(out, regexAPOS, std::string("'"));
|
||||
out = std::regex_replace(out, regexQUOT, std::string("\""));
|
||||
out = std::regex_replace(out, regexAMP, std::string("&"));
|
||||
//EXML_ERROR("INNN '"<< _inval << "' => '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
static std::string replaceSpecialCharOut(const std::string& _inval) {
|
||||
std::string out;
|
||||
static std::regex regexLT("<");
|
||||
static std::regex regexGT(">;");
|
||||
static std::regex regexAMP("&");
|
||||
static std::regex regexAPOS("'");
|
||||
static std::regex regexQUOT("\"");
|
||||
|
||||
out = std::regex_replace(_inval, regexAMP, std::string("&"));
|
||||
out = std::regex_replace(out, regexQUOT, std::string("""));
|
||||
out = std::regex_replace(out, regexAPOS, std::string("'"));
|
||||
out = std::regex_replace(out, regexGT, std::string(">"));
|
||||
out = std::regex_replace(out, regexLT, std::string("<"));
|
||||
//EXML_ERROR("OUTTT '"<< _inval << "' => '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
exml::Text::Text(const std::string& _data) :
|
||||
exml::Node() {
|
||||
m_data = exml::internal::Text::create(_data);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::Text> exml::Text::create(const std::string& _data) {
|
||||
return ememory::SharedPtr<exml::Text>(new exml::Text(_data));
|
||||
}
|
||||
|
||||
bool exml::Text::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
_data += replaceSpecialCharOut(m_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t exml::Text::countLines() const {
|
||||
int32_t count = 1;
|
||||
for (size_t iii=0; iii<m_value.size(); iii++) {
|
||||
if(m_value[iii] == '\n') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool exml::Text::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'text'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
|| _data[iii] == '<') {
|
||||
// search whitespace :
|
||||
size_t newEnd=iii;
|
||||
for (int64_t jjj=(int64_t)iii-1; jjj>(int64_t)_pos; --jjj) {
|
||||
if(isWhiteChar(_data[jjj]) == true) {
|
||||
newEnd = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// find end of value:
|
||||
m_value = std::string(_data, _pos, newEnd-(_pos));
|
||||
EXML_VERBOSE(" find text '" << m_value << "'");
|
||||
_pos = iii-1;
|
||||
m_value = replaceSpecialChar(m_value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Text got end of file without finding end node");
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<exml::TextCDATA> exml::TextCDATA::create() {
|
||||
return ememory::SharedPtr<exml::TextCDATA>(new exml::TextCDATA());
|
||||
}
|
||||
|
||||
bool exml::TextCDATA::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
_data += "<![CDATA[" + m_value +"]]>";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::TextCDATA::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'text::CDATA'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos; iii+2<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == ']'
|
||||
&& _data[iii+1] == ']'
|
||||
&& _data[iii+2] == '>') {
|
||||
// find end of value:
|
||||
_filePos += 2;
|
||||
m_value = std::string(_data, _pos, iii-(_pos));
|
||||
EXML_VERBOSE(" find text CDATA '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "text CDATA got end of file without finding end node");
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
exml::Text& exml::Text::operator= (const exml::Text& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
58
exml/Text.h
58
exml/Text.h
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
@ -15,59 +15,27 @@ namespace exml {
|
||||
* @brief Text node interface (internal data between two balise : <XXX> ALL here </XXX>
|
||||
*/
|
||||
class Text : public exml::Node {
|
||||
protected:
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _internalNode Internal Node to set data
|
||||
*/
|
||||
Text() { };
|
||||
Text(ememory::SharedPtr<exml::internal::Node> _internalNode);
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
Text(const exml::Text& _obj);
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _data String data of the current Text
|
||||
*/
|
||||
Text(const std::string& _data) : exml::Node(_data) { };
|
||||
public:
|
||||
Text(const std::string& _data="");
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @param[in] _data Data in the Text area
|
||||
* @return Shared pointer on the Text element
|
||||
* @brief Copy constructor
|
||||
* @param[in] _obj Object to copy
|
||||
*/
|
||||
static ememory::SharedPtr<exml::Text> create(const std::string& _data="");
|
||||
/**
|
||||
* @brief count the number of line in the current text
|
||||
* @return The number of lines
|
||||
*/
|
||||
int32_t countLines() const;
|
||||
public:
|
||||
enum nodeType getType() const override{
|
||||
return nodeType_text;
|
||||
};
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::Text> toText() override {
|
||||
return std::static_pointer_cast<exml::Text>(shared_from_this());
|
||||
};
|
||||
ememory::SharedPtr<const exml::Text> toText() const override {
|
||||
return std::static_pointer_cast<const exml::Text>(shared_from_this());
|
||||
};
|
||||
};
|
||||
/**
|
||||
* @brief Text node interface for balise CDATA <![CDATA[*******]]>
|
||||
*/
|
||||
class TextCDATA : public exml::Text {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TextCDATA() { };
|
||||
public:
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @return Shared pointer on the Text CDATA element
|
||||
*/
|
||||
static ememory::SharedPtr<TextCDATA> create();
|
||||
public:
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
exml::Text& operator= (const exml::Text& _obj);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
|
122
exml/details/iterator.hxx
Normal file
122
exml/details/iterator.hxx
Normal file
@ -0,0 +1,122 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#include <exml/iterator.h>
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>::iterator(EXML_BASE_T& _obj, size_t _pos) :
|
||||
m_data(_obj),
|
||||
m_id(_pos) {
|
||||
m_id = std::avg(size_t(0), m_id, m_data.size());
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>::iterator(const EXML_BASE_T& _obj, size_t _pos) :
|
||||
m_data(const_cast<EXML_BASE_T&>(_obj)),
|
||||
m_id(_pos) {
|
||||
m_id = std::avg(size_t(0), m_id, m_data.size());
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>::iterator(const exml::iterator<EXML_BASE_T,EXML_RETURN_T>& _obj) :
|
||||
m_data(_obj.m_data),
|
||||
m_id(_obj.m_id) {
|
||||
m_id = std::avg(size_t(0), m_id, m_data.size());
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>& exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator= (const exml::iterator<EXML_BASE_T,EXML_RETURN_T>& _obj) {
|
||||
m_data = _obj.m_data;
|
||||
m_id = _obj.m_id;
|
||||
m_id = std::avg(size_t(0), m_id, m_data.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>& exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator+= (int32_t _val) {
|
||||
int64_t val = m_id;
|
||||
val += _val;
|
||||
m_id = std::avg(int64_t(0), val, int64_t(m_data.size()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator+ (int32_t _val) const {
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> result(*this);
|
||||
result += _val;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>& exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator-= (int32_t _val) {
|
||||
int64_t val = m_id;
|
||||
val -= _val;
|
||||
m_id = std::avg(int64_t(0), val, int64_t(m_data.size()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator- (int32_t _val) const {
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> result = *this;
|
||||
result -= _val;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>& exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator++() {
|
||||
int64_t val = m_id;
|
||||
++val;
|
||||
m_id = std::avg(int64_t(0), val, int64_t(m_data.size()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator++(int) {
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> result = *this;
|
||||
++(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T>& exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator--() {
|
||||
int64_t val = m_id;
|
||||
--val;
|
||||
m_id = std::avg(int64_t(0), val, int64_t(m_data.size()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator--(int) {
|
||||
exml::iterator<EXML_BASE_T,EXML_RETURN_T> result = *this;
|
||||
--(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
bool exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator== (const exml::iterator<EXML_BASE_T,EXML_RETURN_T>& _obj) const {
|
||||
//EXML_WARNING("compare : " << _obj.m_id << " == " << m_id );
|
||||
return ( _obj.m_id == m_id
|
||||
&& &_obj.m_data == &m_data);
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
bool exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator!= (const exml::iterator<EXML_BASE_T,EXML_RETURN_T>& _obj) const {
|
||||
//EXML_WARNING("compare : " << _obj.m_id << " != " << m_id );
|
||||
return ( _obj.m_id != m_id
|
||||
|| &_obj.m_data != &m_data);
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
const EXML_RETURN_T exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator *() const noexcept {
|
||||
return m_data[m_id];
|
||||
}
|
||||
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
EXML_RETURN_T exml::iterator<EXML_BASE_T,EXML_RETURN_T>::operator *() noexcept {
|
||||
return m_data[m_id];
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
|
128
exml/internal/Attribute.cpp
Normal file
128
exml/internal/Attribute.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/Attribute.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/internal/Document.h>
|
||||
|
||||
ememory::SharedPtr<exml::internal::Attribute> exml::internal::Attribute::create(const std::string& _name, const std::string& _value) {
|
||||
return ememory::SharedPtr<exml::internal::Attribute>(new exml::internal::Attribute(_name, _value));
|
||||
}
|
||||
|
||||
exml::internal::Attribute::Attribute(const std::string& _name, const std::string& _value) :
|
||||
exml::internal::Node(_value),
|
||||
m_name(_name) {
|
||||
|
||||
}
|
||||
|
||||
bool exml::internal::Attribute::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'attribute'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
size_t lastElementName = _pos;
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (checkAvaillable(_data[iii], false) == true) {
|
||||
lastElementName = iii;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_name = std::string(_data, _pos, lastElementName+1-(_pos));
|
||||
if (_caseSensitive == true) {
|
||||
m_name = etk::tolower(m_name);
|
||||
}
|
||||
// count white space :
|
||||
exml::FilePos tmpPos;
|
||||
int32_t white = countWhiteChar(_data, lastElementName+1, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
if (lastElementName+white+1 >= _data.size()) {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+1, _filePos, " parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
if (_data[lastElementName+white+1] != '=') {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+1, _filePos, " error attribute parsing == > missing '=' ...");
|
||||
return false;
|
||||
}
|
||||
white += countWhiteChar(_data, lastElementName+white+2, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
|
||||
if (lastElementName+white+2>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+2, _filePos, " parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
bool simpleQuoteCase = false;
|
||||
if (_data[lastElementName+white+2] == '\'') { // '
|
||||
simpleQuoteCase = true;
|
||||
}
|
||||
if ( _data[lastElementName+white+2] != '"'
|
||||
&& _data[lastElementName+white+2] != '\'') { // '
|
||||
// parse with no element " == > direct value separate with space ...
|
||||
++_filePos;
|
||||
size_t lastAttributePos = lastElementName+white+2;
|
||||
for (size_t iii=lastElementName+white+2; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
CREATE_ERROR(_doc, _data, iii, _filePos, "unexpected '\\n' in an attribute parsing");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii] != ' '
|
||||
&& _data[iii] != '/'
|
||||
&& _data[iii] != '?'
|
||||
&& _data[iii] != '>') {
|
||||
lastAttributePos = iii+1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = std::string(_data, lastElementName+white+2, lastAttributePos-(lastElementName+white+2));
|
||||
|
||||
EXML_PARSE_ATTRIBUTE(m_pos << " attribute : " << m_name << "=\"" << m_value << "\"");
|
||||
|
||||
_pos = lastAttributePos-1;
|
||||
return true;
|
||||
}
|
||||
size_t lastAttributePos = lastElementName+white+3;
|
||||
for (size_t iii=lastElementName+white+3; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
_filePos.check(_data[iii]);
|
||||
if ( (_data[iii] != '"' && simpleQuoteCase == false)
|
||||
|| (_data[iii] != '\'' && simpleQuoteCase == true) ) { // '
|
||||
lastAttributePos = iii+1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = std::string(_data, lastElementName+white+3, lastAttributePos-(lastElementName+white+3));
|
||||
|
||||
EXML_PARSE_ATTRIBUTE(m_pos << " attribute : " << m_name << "=\"" << m_value << "\"");
|
||||
|
||||
_pos = lastAttributePos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::internal::Attribute::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
_data += " ";
|
||||
_data += m_name;
|
||||
_data += "=\"";
|
||||
_data += m_value;
|
||||
_data += "\"";
|
||||
return true;
|
||||
}
|
||||
|
||||
void exml::internal::Attribute::clear() {
|
||||
m_name = "";
|
||||
}
|
||||
|
67
exml/internal/Attribute.h
Normal file
67
exml/internal/Attribute.h
Normal file
@ -0,0 +1,67 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/internal/Node.h>
|
||||
#include <vector>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
/**
|
||||
* @brief Single attribute element
|
||||
*/
|
||||
class Attribute : public exml::internal::Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _name Name of the attribute.
|
||||
* @param[in] _value Value of the attribute.
|
||||
*/
|
||||
Attribute(const std::string& _name="", const std::string& _value="");
|
||||
public:
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @param[in] _name Name of the attribute
|
||||
* @param[in] _value Value of the attribute
|
||||
* @return Shared pointer on the Attribute element
|
||||
*/
|
||||
static ememory::SharedPtr<Attribute> create(const std::string& _name="", const std::string& _value="");
|
||||
protected:
|
||||
std::string m_name; //!< Name of the attribute
|
||||
public:
|
||||
/**
|
||||
* @brief set the name of the attribute
|
||||
* @param[in] _name New name of the attribute
|
||||
*/
|
||||
virtual void setName(const std::string& _name) {
|
||||
m_name = _name;
|
||||
};
|
||||
/**
|
||||
* @brief get the current name of the Attribute
|
||||
* @return String of the attribute
|
||||
*/
|
||||
virtual const std::string& getName() const {
|
||||
return m_name;
|
||||
};
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return exml::nodeType_attribute;
|
||||
};
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::internal::Attribute> toAttribute() override {
|
||||
return std::static_pointer_cast<exml::internal::Attribute>(shared_from_this());
|
||||
};
|
||||
ememory::SharedPtr<const exml::internal::Attribute> toAttribute() const override {
|
||||
return std::static_pointer_cast<const exml::internal::Attribute>(shared_from_this());
|
||||
};
|
||||
void clear() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
127
exml/internal/AttributeList.cpp
Normal file
127
exml/internal/AttributeList.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/AttributeList.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
ememory::SharedPtr<exml::internal::Attribute> exml::internal::AttributeList::getAttr(int32_t _id) {
|
||||
if (_id <0 || (size_t)_id>m_listAttribute.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listAttribute[_id];
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Attribute> exml::internal::AttributeList::getAttr(int32_t _id) const {
|
||||
if (_id <0 || (size_t)_id>m_listAttribute.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listAttribute[_id];
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> exml::internal::AttributeList::getAttrPair(int32_t _id) const {
|
||||
ememory::SharedPtr<const exml::internal::Attribute> att = getAttr(_id);
|
||||
if (att == nullptr) {
|
||||
return std::make_pair<std::string, std::string>("","");
|
||||
}
|
||||
return std::make_pair(att->getName(),att->getValue());
|
||||
}
|
||||
|
||||
|
||||
void exml::internal::AttributeList::appendAttribute(const ememory::SharedPtr<exml::internal::Attribute>& _attr) {
|
||||
if (_attr == nullptr) {
|
||||
EXML_ERROR("Try to set an empty node");
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (m_listAttribute[iii] == _attr) {
|
||||
EXML_ERROR("Try to add a node that is already added befor !!!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_listAttribute.push_back(_attr);
|
||||
}
|
||||
|
||||
const std::string& exml::internal::AttributeList::getAttribute(const std::string& _name) const {
|
||||
static const std::string errorReturn("");
|
||||
if (_name.size() == 0) {
|
||||
return errorReturn;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if( m_listAttribute[iii] != nullptr
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
return m_listAttribute[iii]->getValue();
|
||||
}
|
||||
}
|
||||
return errorReturn;
|
||||
}
|
||||
|
||||
|
||||
bool exml::internal::AttributeList::existAttribute(const std::string& _name) const {
|
||||
if (_name.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); ++iii) {
|
||||
if( m_listAttribute[iii] != nullptr
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::internal::AttributeList::removeAttribute(const std::string& _name) {
|
||||
if (_name.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
auto it = m_listAttribute.begin();
|
||||
while (it != m_listAttribute.end()) {
|
||||
if (*it == nullptr) {
|
||||
it = m_listAttribute.erase(it);
|
||||
continue;
|
||||
}
|
||||
if((*it)->getName() == _name) {
|
||||
it = m_listAttribute.erase(it);
|
||||
return true;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void exml::internal::AttributeList::setAttribute(const std::string& _name, const std::string& _value) {
|
||||
// check if attribute already det :
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); ++iii) {
|
||||
if( m_listAttribute[iii] != nullptr
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
// update the value :
|
||||
m_listAttribute[iii]->setValue(_value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ememory::SharedPtr<exml::internal::Attribute> attr = exml::internal::Attribute::create(_name, _value);
|
||||
if (attr == nullptr) {
|
||||
EXML_ERROR("memory allocation error...");
|
||||
}
|
||||
m_listAttribute.push_back(attr);
|
||||
}
|
||||
|
||||
bool exml::internal::AttributeList::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
for (size_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (m_listAttribute[iii] != nullptr) {
|
||||
m_listAttribute[iii]->iGenerate(_data, _indent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void exml::internal::AttributeList::clear() {
|
||||
exml::internal::Node::clear();
|
||||
m_listAttribute.clear();
|
||||
}
|
||||
|
||||
|
94
exml/internal/AttributeList.h
Normal file
94
exml/internal/AttributeList.h
Normal file
@ -0,0 +1,94 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/internal/Node.h>
|
||||
#include <vector>
|
||||
#include <exml/internal/Attribute.h>
|
||||
#include <utility>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
/**
|
||||
* @brief List of all attribute element in a node
|
||||
*/
|
||||
class AttributeList : public exml::internal::Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _value Node value;
|
||||
*/
|
||||
AttributeList(const std::string& _value="") :
|
||||
exml::internal::Node(_value) {
|
||||
|
||||
};
|
||||
protected:
|
||||
std::vector<ememory::SharedPtr<exml::internal::Attribute>> m_listAttribute; //!< list of all attribute
|
||||
public:
|
||||
/**
|
||||
* @brief get the number of attribute in the Node
|
||||
* @return Nulber of attribute >=0
|
||||
*/
|
||||
size_t sizeAttribute() const {
|
||||
return m_listAttribute.size();
|
||||
};
|
||||
/**
|
||||
* @brief add attribute on the List
|
||||
* @param[in] _attr Pointer on the attribute
|
||||
*/
|
||||
void appendAttribute(const ememory::SharedPtr<exml::internal::Attribute>& _attr);
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Pointer on the attribute or NULL
|
||||
*/
|
||||
ememory::SharedPtr<Attribute> getAttr(int32_t _id);
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Pointer on the attribute or NULL
|
||||
*/
|
||||
ememory::SharedPtr<const Attribute> getAttr(int32_t _id) const;
|
||||
/**
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Name and value of the attribute
|
||||
*/
|
||||
std::pair<std::string, std::string> getAttrPair(int32_t _id) const;
|
||||
/**
|
||||
* @brief get the attribute value with searching in the List with his name
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return Value of the attribute or no data in the string
|
||||
*/
|
||||
const std::string& getAttribute(const std::string& _name) const;
|
||||
/**
|
||||
* @brief check if an attribute exist or not with his name.
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return true if the attribute exist or False
|
||||
*/
|
||||
bool existAttribute(const std::string& _name) const;
|
||||
/**
|
||||
* @brief Set A new attribute or replace data of the previous one
|
||||
* @param[in] _name Name of the attribute
|
||||
* @param[in] _value Value of the attribute
|
||||
*/
|
||||
void setAttribute(const std::string& _name, const std::string& _value);
|
||||
/**
|
||||
* @brief Remove an attribute form the list
|
||||
* @param[in] _name Name of the attribute
|
||||
* @return true The attribute has been removed
|
||||
* @return false An error occured.
|
||||
*/
|
||||
bool removeAttribute(const std::string& _name);
|
||||
public:
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
void clear() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
72
exml/internal/Comment.cpp
Normal file
72
exml/internal/Comment.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/Comment.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/internal/Document.h>
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Comment> exml::internal::Comment::create(const std::string& _value) {
|
||||
return ememory::SharedPtr<exml::internal::Comment>(new exml::internal::Comment(_value));
|
||||
}
|
||||
|
||||
bool exml::internal::Comment::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'comment'");
|
||||
m_pos = _filePos;
|
||||
exml::FilePos tmpPos;
|
||||
int32_t white = countWhiteChar(_data, _pos, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos+white; iii+2<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '-'
|
||||
&& _data[iii+1] == '-'
|
||||
&& _data[iii+2] == '>') {
|
||||
_filePos += 2;
|
||||
// search whitespace :
|
||||
int32_t newEnd=iii;
|
||||
for( int32_t jjj=iii-1; jjj>_pos; jjj--) {
|
||||
if(isWhiteChar(_data[jjj]) == true) {
|
||||
newEnd = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// find end of value:
|
||||
m_value = std::string(_data, _pos+white, newEnd-(_pos+white));
|
||||
EXML_VERBOSE(" find comment '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_pos = _data.size();
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "comment got end of file without finding end node");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::internal::Comment::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
addIndent(_data, _indent);
|
||||
_data += "<!--";
|
||||
_data += m_value;
|
||||
_data += "-->\n";
|
||||
return true;
|
||||
}
|
49
exml/internal/Comment.h
Normal file
49
exml/internal/Comment.h
Normal file
@ -0,0 +1,49 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/internal/Node.h>
|
||||
#include <vector>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
/**
|
||||
* @brief Comment node: <!-- ... -->
|
||||
*/
|
||||
class Comment : public exml::internal::Node {
|
||||
public:
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @return Shared pointer on the Comment element
|
||||
* @param[in] _value comment value
|
||||
*/
|
||||
static ememory::SharedPtr<exml::internal::Comment> create(const std::string& _value="");
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _value comment value
|
||||
*/
|
||||
Comment(const std::string& _value) :
|
||||
exml::internal::Node(_value) {
|
||||
|
||||
}
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return nodeType_comment;
|
||||
}
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::internal::Comment> toComment() override {
|
||||
return std::static_pointer_cast<exml::internal::Comment>(shared_from_this());
|
||||
}
|
||||
ememory::SharedPtr<const exml::internal::Comment> toComment() const override {
|
||||
return std::static_pointer_cast<const exml::internal::Comment>(shared_from_this());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
99
exml/internal/Declaration.cpp
Normal file
99
exml/internal/Declaration.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/Declaration.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/internal/Document.h>
|
||||
|
||||
/* basic declaration have 3 attributes:
|
||||
version
|
||||
encoding
|
||||
standalone
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
*/
|
||||
|
||||
ememory::SharedPtr<exml::internal::Declaration> exml::internal::Declaration::create(const std::string& _name) {
|
||||
return ememory::SharedPtr<exml::internal::Declaration>(new exml::internal::Declaration(_name));
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::DeclarationXML> exml::internal::DeclarationXML::create(const std::string& _version, const std::string& _format, bool _standalone) {
|
||||
return ememory::SharedPtr<exml::internal::DeclarationXML>(new exml::internal::DeclarationXML(_version, _format, _standalone));
|
||||
}
|
||||
|
||||
exml::internal::DeclarationXML::DeclarationXML(const std::string& _version, const std::string& _format, bool _standalone) :
|
||||
exml::internal::Declaration("xml") {
|
||||
if (_version.size()!=0) {
|
||||
setAttribute("version", _version);
|
||||
}
|
||||
if (_format!="UTF-8") {
|
||||
setAttribute("encoding", "UTF-8");
|
||||
} else {
|
||||
EXML_ERROR("Actually does not supported other charset than UTF8");
|
||||
setAttribute("encoding", "UTF-8");
|
||||
}
|
||||
if (_standalone == true) {
|
||||
setAttribute("standalone", "true");
|
||||
} else {
|
||||
setAttribute("standalone", "true");
|
||||
}
|
||||
}
|
||||
|
||||
bool exml::internal::Declaration::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
addIndent(_data, _indent);
|
||||
_data += "<?";
|
||||
_data += m_value;
|
||||
exml::internal::AttributeList::iGenerate(_data, _indent);
|
||||
_data += "?>\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::internal::Declaration::iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'declaration' : '" << m_value << "'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos; iii+1<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
|| _data[iii] == '<') {
|
||||
// an error occured :
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, " find '>' or '<' instead of '?>'");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii] == '?'
|
||||
&& _data[iii+1] == '>') {
|
||||
++_filePos;
|
||||
// find end of declaration:
|
||||
_pos = iii+1;
|
||||
return true;
|
||||
}
|
||||
if (checkAvaillable(_data[iii], true) == true) {
|
||||
// we find an attibute == > create a new and parse it :
|
||||
ememory::SharedPtr<exml::internal::Attribute> attribute = exml::internal::Attribute::create();
|
||||
if (attribute == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
if (attribute->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listAttribute.push_back(attribute);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Text got end of file without finding end node");
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
71
exml/internal/Declaration.h
Normal file
71
exml/internal/Declaration.h
Normal file
@ -0,0 +1,71 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/internal/AttributeList.h>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
/**
|
||||
* @brief Declaration node: <?XXXXXX ... >
|
||||
*/
|
||||
class Declaration : public exml::internal::AttributeList {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _name name of the declaration (xml, xml:xxxx ...)
|
||||
*/
|
||||
Declaration(const std::string& _name="") :
|
||||
exml::internal::AttributeList(_name) {
|
||||
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* @brief Factory to create declaration
|
||||
* @param[in] _name name of the declaration (xml, xml:xxxx ...)
|
||||
* @return a structure declaration
|
||||
*/
|
||||
static ememory::SharedPtr<Declaration> create(const std::string& _name="");
|
||||
public:
|
||||
enum nodeType getType() const override{
|
||||
return nodeType_declaration;
|
||||
};
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) override;
|
||||
ememory::SharedPtr<exml::internal::Declaration> toDeclaration() override {
|
||||
return std::static_pointer_cast<exml::internal::Declaration>(shared_from_this());
|
||||
};
|
||||
ememory::SharedPtr<const exml::internal::Declaration> toDeclaration() const override {
|
||||
return std::static_pointer_cast<const exml::internal::Declaration>(shared_from_this());
|
||||
};
|
||||
};
|
||||
/**
|
||||
* @brief Declaration node: <?XML ... >
|
||||
*/
|
||||
class DeclarationXML : public exml::internal::Declaration {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the generic declaration : <?xml version="" format="UTF-8"?>
|
||||
* @param[in] _version Xml version.
|
||||
* @param[in] _format charset of the XML
|
||||
* @param[in] _standalone this document is standalone
|
||||
*/
|
||||
DeclarationXML(const std::string& _version, const std::string& _format = "UTF-8", bool _standalone = true);
|
||||
public:
|
||||
/**
|
||||
* @brief Factory to create XML declaration
|
||||
* @param[in] _version Xml version.
|
||||
* @param[in] _format charset of the XML
|
||||
* @param[in] _standalone this document is standalone
|
||||
* @return a structure declaration
|
||||
*/
|
||||
static ememory::SharedPtr<DeclarationXML> create(const std::string& _version, const std::string& _format = "UTF-8", bool _standalone = true);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
149
exml/internal/Document.cpp
Normal file
149
exml/internal/Document.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/Document.h>
|
||||
#include <exml/debug.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
|
||||
ememory::SharedPtr<exml::internal::Document> exml::internal::Document::create() {
|
||||
return ememory::SharedPtr<exml::internal::Document>(new exml::internal::Document());
|
||||
}
|
||||
|
||||
exml::internal::Document::Document() :
|
||||
m_caseSensitive(false),
|
||||
m_writeErrorWhenDetexted(true),
|
||||
m_comment(""),
|
||||
m_Line(""),
|
||||
m_filePos(0,0) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool exml::internal::Document::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] != nullptr) {
|
||||
m_listSub[iii]->iGenerate(_data, _indent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::internal::Document::parse(const std::string& _data) {
|
||||
EXML_VERBOSE("Start parsing document (type: string) size=" << _data.size());
|
||||
clear();
|
||||
// came from char == > force in utf8 ...
|
||||
exml::FilePos filePos(1,0);
|
||||
m_pos = filePos;
|
||||
int32_t parsePos = 0;
|
||||
return subParse(_data, parsePos, m_caseSensitive, filePos, *this, true);
|
||||
}
|
||||
|
||||
bool exml::internal::Document::generate(std::string& _data) {
|
||||
_data = "";
|
||||
return iGenerate(_data,0);
|
||||
}
|
||||
|
||||
bool exml::internal::Document::load(const std::string& _file) {
|
||||
// Start loading the XML :
|
||||
EXML_VERBOSE("open file (xml) \"" << _file << "\"");
|
||||
clear();
|
||||
etk::FSNode tmpFile(_file);
|
||||
if (tmpFile.exist() == false) {
|
||||
EXML_ERROR("File Does not exist : " << _file);
|
||||
return false;
|
||||
}
|
||||
int64_t fileSize = tmpFile.fileSize();
|
||||
if (fileSize == 0) {
|
||||
EXML_ERROR("This file is empty : " << _file);
|
||||
return false;
|
||||
}
|
||||
if (tmpFile.fileOpenRead() == false) {
|
||||
EXML_ERROR("Can not open (r) the file : " << _file);
|
||||
return false;
|
||||
}
|
||||
// allocate data
|
||||
std::vector<char> fileBuffer;
|
||||
fileBuffer.resize(fileSize+5, 0);
|
||||
// load data from the file :
|
||||
tmpFile.fileRead(&fileBuffer[0], 1, fileSize);
|
||||
// close the file:
|
||||
tmpFile.fileClose();
|
||||
|
||||
// convert in UTF8 :
|
||||
std::string tmpDataUnicode(&fileBuffer[0]);
|
||||
// parse the data :
|
||||
bool ret = parse(tmpDataUnicode);
|
||||
//Display();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool exml::internal::Document::store(const std::string& _file) {
|
||||
std::string createData;
|
||||
if (generate(createData) == false) {
|
||||
EXML_ERROR("Error while creating the XML : " << _file);
|
||||
return false;
|
||||
}
|
||||
etk::FSNode tmpFile(_file);
|
||||
if (tmpFile.fileOpenWrite() == false) {
|
||||
EXML_ERROR("Can not open (w) the file : " << _file);
|
||||
return false;
|
||||
}
|
||||
if (tmpFile.fileWrite((char*)createData.c_str(), sizeof(char), createData.size()) != (int64_t)createData.size()) {
|
||||
EXML_ERROR("Error while writing output XML file : " << _file);
|
||||
tmpFile.fileClose();
|
||||
return false;
|
||||
}
|
||||
tmpFile.fileClose();
|
||||
return true;
|
||||
}
|
||||
|
||||
void exml::internal::Document::display() {
|
||||
std::string tmpp;
|
||||
iGenerate(tmpp, 0);
|
||||
EXML_INFO("Generated XML : \n" << tmpp);
|
||||
}
|
||||
|
||||
std::string createPosPointer(const std::string& _line, int32_t _pos) {
|
||||
std::string out;
|
||||
size_t iii;
|
||||
for (iii=0; (int64_t)iii<_pos && iii<_line.size(); iii++) {
|
||||
if (_line[iii] == '\t') {
|
||||
out += "\t";
|
||||
} else {
|
||||
out += " ";
|
||||
}
|
||||
}
|
||||
for (; (int64_t)iii<_pos; iii++) {
|
||||
out += " ";
|
||||
}
|
||||
out += "^";
|
||||
return out;
|
||||
}
|
||||
|
||||
void exml::internal::Document::displayError() {
|
||||
if (m_comment.size() == 0) {
|
||||
EXML_ERROR("No error detected ???");
|
||||
return;
|
||||
}
|
||||
EXML_ERROR(m_filePos << " " << m_comment << "\n"
|
||||
<< m_Line << "\n"
|
||||
<< createPosPointer(m_Line, m_filePos.getCol()) );
|
||||
#ifdef ENABLE_CRITICAL_WHEN_ERROR
|
||||
EXML_CRITICAL("detect error");
|
||||
#endif
|
||||
}
|
||||
|
||||
void exml::internal::Document::createError(const std::string& _data, int32_t _pos, const exml::FilePos& _filePos, const std::string& _comment) {
|
||||
m_comment = _comment;
|
||||
m_Line = etk::extract_line(_data, _pos);
|
||||
m_filePos = _filePos;
|
||||
if (m_writeErrorWhenDetexted== true) {
|
||||
displayError();
|
||||
}
|
||||
}
|
||||
|
128
exml/internal/Document.h
Normal file
128
exml/internal/Document.h
Normal file
@ -0,0 +1,128 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/internal/Element.h>
|
||||
#include <vector>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
/**
|
||||
* @brief Basic document element of a document
|
||||
*/
|
||||
class Document : public exml::internal::Element {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Document();
|
||||
/**
|
||||
* @brief Factory on a document
|
||||
* @return an local created xml document
|
||||
*/
|
||||
static ememory::SharedPtr<exml::internal::Document> create();
|
||||
private:
|
||||
bool m_caseSensitive; //!< check the case sensitive of the nodes and attribute
|
||||
public:
|
||||
/**
|
||||
* @brief Enable or diasable the case sensitive (must be done before the call of parsing)
|
||||
* @param[in] _val true if enable; false else.
|
||||
*/
|
||||
virtual void setCaseSensitive(bool _val) {
|
||||
m_caseSensitive = _val;
|
||||
};
|
||||
/**
|
||||
* @brief get the status of case sensitive mode.
|
||||
* @return true if case sensitive is active
|
||||
*/
|
||||
virtual bool getCaseSensitive() const {
|
||||
return m_caseSensitive;
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* @brief parse a string that contain an XML
|
||||
* @param[in] _data Data to parse
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool parse(const std::string& _data);
|
||||
/**
|
||||
* @brief generate a string that contain the created XML
|
||||
* @param[out] _data Data where the xml is stored
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool generate(std::string& _data);
|
||||
/**
|
||||
* @brief Load the file that might contain the xml
|
||||
* @param[in] _file Filename of the xml (compatible with etk FSNode naming)
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool load(const std::string& _file);
|
||||
/**
|
||||
* @brief Store the Xml in the file
|
||||
* @param[in] _file Filename of the xml (compatible with etk FSNode naming)
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool store(const std::string& _file);
|
||||
/**
|
||||
* @brief Display the Document on console
|
||||
*/
|
||||
void display();
|
||||
private:
|
||||
bool m_writeErrorWhenDetexted; //!< Request print error in parsing just when detected
|
||||
std::string m_comment; //!< Comment on the error
|
||||
std::string m_Line; //!< Parse line error (copy)
|
||||
exml::FilePos m_filePos; //!< position of the error
|
||||
public:
|
||||
/**
|
||||
* @brief Request display error when detected (not print only at the end ...)
|
||||
*/
|
||||
void displayErrorWhenDetected() {
|
||||
m_writeErrorWhenDetexted = true;
|
||||
}
|
||||
/**
|
||||
* @brief Request NOT display error when detected.
|
||||
*/
|
||||
void notDisplayErrorWhenDetected() {
|
||||
m_writeErrorWhenDetexted = false;
|
||||
}
|
||||
/**
|
||||
* @brief Create an error in the parsing (call by the syetm for error management)
|
||||
* @param[in] _data string of chat is wrong
|
||||
* @param[in] _pos Position in the file
|
||||
* @param[in] _filePos human position of the error
|
||||
* @param[in] _comment Error string to display
|
||||
*/
|
||||
void createError(const std::string& _data, int32_t _pos, const exml::FilePos& _filePos, const std::string& _comment);
|
||||
/**
|
||||
* @brief request display in log of the error
|
||||
*/
|
||||
void displayError();
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return nodeType_document;
|
||||
}
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::internal::Document> toDocument() override {
|
||||
return std::static_pointer_cast<exml::internal::Document>(shared_from_this());
|
||||
}
|
||||
ememory::SharedPtr<const exml::internal::Document> toDocument() const override {
|
||||
return std::static_pointer_cast<const exml::internal::Document>(shared_from_this());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#define CREATE_ERROR(doc,data,pos,filePos,comment) \
|
||||
do { \
|
||||
EXML_ERROR(comment); \
|
||||
(doc).createError((data),(pos),(filePos),(comment)); \
|
||||
} while (0)
|
489
exml/internal/Element.cpp
Normal file
489
exml/internal/Element.cpp
Normal file
@ -0,0 +1,489 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/Element.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/internal/Text.h>
|
||||
#include <exml/internal/Comment.h>
|
||||
#include <exml/internal/Attribute.h>
|
||||
#include <exml/internal/Declaration.h>
|
||||
#include <exml/internal/Document.h>
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Element> exml::internal::Element::create(const std::string& _value) {
|
||||
return ememory::SharedPtr<exml::internal::Element>(new exml::internal::Element(_value));
|
||||
}
|
||||
|
||||
enum exml::nodeType exml::internal::Element::getType(int32_t _id) const {
|
||||
ememory::SharedPtr<const exml::internal::Node> tmpp = getNode(_id);
|
||||
if (tmpp == nullptr) {
|
||||
return exml::nodeType_unknow;
|
||||
}
|
||||
return tmpp->getType();
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Node> exml::internal::Element::getNode(int32_t _id) {
|
||||
if (_id <0 || (size_t)_id>m_listSub.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listSub[_id];
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Node> exml::internal::Element::getNode(int32_t _id) const {
|
||||
if (_id <0 || (size_t)_id>m_listSub.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listSub[_id];
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<exml::internal::Element> exml::internal::Element::getElement(int32_t _id) {
|
||||
ememory::SharedPtr<exml::internal::Node> tmpp = getNode(_id);
|
||||
if (tmpp == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return tmpp->toElement();
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Element> exml::internal::Element::getElement(int32_t _id) const {
|
||||
ememory::SharedPtr<const exml::internal::Node> tmpp = getNode(_id);
|
||||
if (tmpp == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return tmpp->toElement();
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Element> exml::internal::Element::getNamed(const std::string& _name) {
|
||||
if (_name.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if( m_listSub[iii] != nullptr
|
||||
&& m_listSub[iii]->getType() == exml::nodeType_element
|
||||
&& m_listSub[iii]->getValue() == _name) {
|
||||
if (m_listSub[iii] == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listSub[iii]->toElement();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Element> exml::internal::Element::getNamed(const std::string& _name) const {
|
||||
if (_name.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if( m_listSub[iii] != nullptr
|
||||
&& m_listSub[iii]->getType() == exml::nodeType_element
|
||||
&& m_listSub[iii]->getValue() == _name) {
|
||||
if (m_listSub[iii] == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_listSub[iii]->toElement();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void exml::internal::Element::append(const ememory::SharedPtr<exml::internal::Node>& _node) {
|
||||
if (_node == nullptr) {
|
||||
EXML_ERROR("Try to set an empty node");
|
||||
return;
|
||||
}
|
||||
if (_node->getType() == exml::nodeType_attribute) {
|
||||
appendAttribute(_node->toAttribute());
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] == _node) {
|
||||
EXML_ERROR("Try to add a node that is already added before !!!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_listSub.push_back(_node);
|
||||
}
|
||||
|
||||
std::string exml::internal::Element::getText() const {
|
||||
std::string res;
|
||||
if (m_listSub.size() == 1) {
|
||||
if (m_listSub[0]->getType() == nodeType_text) {
|
||||
res = m_listSub[0]->getValue();
|
||||
} else {
|
||||
m_listSub[0]->iGenerate(res, 0);
|
||||
}
|
||||
} else {
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] != nullptr) {
|
||||
m_listSub[iii]->iGenerate(res, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool exml::internal::Element::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
addIndent(_data, _indent);
|
||||
_data += "<";
|
||||
_data += m_value;
|
||||
exml::internal::AttributeList::iGenerate(_data, _indent);
|
||||
|
||||
if (m_listSub.size()>0) {
|
||||
if( m_listSub.size() == 1
|
||||
&& m_listSub[0] != nullptr
|
||||
&& m_listSub[0]->getType() == exml::nodeType_text
|
||||
&& std::dynamic_pointer_cast<exml::internal::Text>(m_listSub[0])->countLines() == 1) {
|
||||
_data += ">";
|
||||
m_listSub[0]->iGenerate(_data,0);
|
||||
EXML_VERBOSE(" generate : '" << _data << "'");
|
||||
} else {
|
||||
_data += ">\n";
|
||||
|
||||
for (size_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] != nullptr) {
|
||||
m_listSub[iii]->iGenerate(_data, _indent+1);
|
||||
}
|
||||
}
|
||||
addIndent(_data, _indent);
|
||||
}
|
||||
_data += "</";
|
||||
_data += m_value;
|
||||
_data += ">\n";
|
||||
} else {
|
||||
_data += "/>\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool exml::internal::Element::subParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc, bool _mainNode) {
|
||||
EXML_PARSE_ELEMENT(" start subParse ... " << _pos << " " << _filePos);
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
exml::FilePos tmpPos;
|
||||
if (_data[iii] == '<') {
|
||||
int32_t white = countWhiteChar(_data, iii+1, tmpPos);
|
||||
if (iii+white+1>=_data.size()) {
|
||||
_filePos+=tmpPos;
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<' char == > invalide XML");
|
||||
_pos = iii+white;
|
||||
return false;
|
||||
}
|
||||
// Detect type of the element:
|
||||
if(_data[iii+white+1] == '>') {
|
||||
_filePos+=tmpPos;
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find '>' with no element in the element...");
|
||||
_pos = iii+white+1;
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+1] == '?') {
|
||||
++tmpPos;
|
||||
// TODO : white space ...
|
||||
if(checkAvaillable(_data[iii+white+2], true) == false) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find unavaillable name in the Declaration node...");
|
||||
_pos = iii+white+1;
|
||||
return false;
|
||||
}
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
size_t endPosName = iii+white+1;
|
||||
// generate element name ...
|
||||
for (size_t jjj=iii+white+2; jjj<_data.size(); jjj++) {
|
||||
if(checkAvaillable(_data[jjj], false) == true) {
|
||||
// we find the end ...
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
std::string tmpname = std::string(_data, iii+white+2, endPosName+1-(iii+white+2));
|
||||
if (_caseSensitive == true) {
|
||||
tmpname = etk::tolower(tmpname);
|
||||
}
|
||||
// Find declaration balise
|
||||
ememory::SharedPtr<exml::internal::Declaration> declaration = exml::internal::Declaration::create(tmpname);
|
||||
if (declaration == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation Error...");
|
||||
return false;
|
||||
}
|
||||
_filePos += tmpPos;
|
||||
_pos = endPosName+1;
|
||||
if (declaration->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(declaration);
|
||||
continue;
|
||||
}
|
||||
if(_data[iii+white+1] == '!') {
|
||||
++tmpPos;
|
||||
// Find special block element
|
||||
if (iii+white+2>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+2] == '-') {
|
||||
++tmpPos;
|
||||
if (iii+white+3>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!-' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+3] != '-') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Element parse with '<!-") + _data[iii+3] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
++tmpPos;
|
||||
// find comment:
|
||||
ememory::SharedPtr<exml::internal::Comment> comment = exml::internal::Comment::create();
|
||||
if (comment == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+white+4;
|
||||
_filePos += tmpPos;
|
||||
if (comment->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(comment);
|
||||
} else if (_data[iii+white+2] == '[') {
|
||||
++tmpPos;
|
||||
if (iii+white+8>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<![' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii+white+3] != 'C'
|
||||
|| _data[iii+white+4] != 'D'
|
||||
|| _data[iii+white+5] != 'A'
|
||||
|| _data[iii+white+6] != 'T'
|
||||
|| _data[iii+white+7] != 'A'
|
||||
|| _data[iii+white+8] != '[') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Element parse with '<![") + _data[iii+white+3] + _data[iii+white+4] + _data[iii+white+5] + _data[iii+white+6] + _data[iii+white+7] + _data[iii+white+8] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
tmpPos+=6;
|
||||
// find text:
|
||||
ememory::SharedPtr<exml::internal::TextCDATA> text = exml::internal::TextCDATA::create();
|
||||
if (text == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+9+white;
|
||||
_filePos += tmpPos;
|
||||
if (text->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(text);
|
||||
} else {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("End file with '<!") + _data[iii+white+2] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(_data[iii+white+1] == '/') {
|
||||
++tmpPos;
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
size_t endPosName = iii+white+1;
|
||||
// generate element name ...
|
||||
for (size_t jjj=iii+white+2; jjj<_data.size(); jjj++) {
|
||||
if(checkAvaillable(_data[jjj], false) == true) {
|
||||
// we find the end ...
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
std::string tmpname = std::string(_data, iii+white+2, endPosName+1-(iii+white+2));
|
||||
if (_caseSensitive == true) {
|
||||
tmpname = etk::tolower(tmpname);
|
||||
}
|
||||
if( tmpname == m_value) {
|
||||
// find end of node :
|
||||
// find > element ...
|
||||
for (size_t jjj=endPosName+1; jjj<_data.size(); jjj++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[jjj], _filePos);
|
||||
#endif
|
||||
if (tmpPos.check(_data[jjj]) == true) {
|
||||
continue;
|
||||
}
|
||||
if(_data[jjj] == '>') {
|
||||
_pos = jjj;
|
||||
_filePos += tmpPos;
|
||||
return true;
|
||||
} else if( _data[jjj] != '\r'
|
||||
&& _data[jjj] != ' '
|
||||
&& _data[jjj] != '\t') {
|
||||
_filePos += tmpPos;
|
||||
CREATE_ERROR(_doc, _data, jjj, _filePos, std::string("End node error : have data inside end node other than [ \\n\\t\\r] ") + m_value + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("End node error : '") + tmpname + "' != '" + m_value + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (_data[iii+white+1] == '>') {
|
||||
// end of something == > this is really bad
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find '>' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkAvaillable(_data[iii+white+1], true) == true) {
|
||||
++tmpPos;
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
size_t endPosName = iii+white+1;
|
||||
// generate element name ...
|
||||
for (size_t jjj=iii+white+2; jjj<_data.size(); jjj++) {
|
||||
if(checkAvaillable(_data[jjj], false) == true) {
|
||||
// we find the end ...
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
std::string tmpname = std::string(_data, iii+white+1, endPosName+1-(iii+white+1));
|
||||
if (_caseSensitive == true) {
|
||||
etk::tolower(tmpname);
|
||||
}
|
||||
//EXML_INFO("find node named : '" << tmpname << "'");
|
||||
// find text:
|
||||
ememory::SharedPtr<exml::internal::Element> element = exml::internal::Element::create(tmpname);
|
||||
if (element == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = endPosName+1;
|
||||
_filePos += tmpPos;
|
||||
if (element->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(element);
|
||||
continue;
|
||||
}
|
||||
_filePos+=tmpPos;
|
||||
// here we have an error :
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Find an ununderstanding element : '") + _data[iii+white+1] + "'");
|
||||
return false;
|
||||
} else {
|
||||
if (_data[iii] == '>') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find elemement '>' == > no reason to be here ...");
|
||||
return false;
|
||||
}
|
||||
// might to be data text ...
|
||||
if( _data[iii] == '\n'
|
||||
|| _data[iii] == ' '
|
||||
|| _data[iii] == '\t'
|
||||
|| _data[iii] == '\r') {
|
||||
// empty spaces == > nothing to do ....
|
||||
} else {
|
||||
// find data == > parse it...
|
||||
ememory::SharedPtr<exml::internal::Text> text = exml::internal::Text::create();
|
||||
if (text == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
_filePos += tmpPos;
|
||||
if (text->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.push_back(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_mainNode == true) {
|
||||
return true;
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Did not find end of the exml::internal::Element : '") + m_value + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::internal::Element::iParse(const std::string& _data,
|
||||
int32_t& _pos,
|
||||
bool _caseSensitive,
|
||||
exml::FilePos& _filePos,
|
||||
exml::internal::Document& _doc) {
|
||||
EXML_PARSE_ELEMENT("start parse : 'element' named='" << m_value << "'");
|
||||
// note : When start parsing the upper element must have set the value of the element and set the position after this one
|
||||
m_pos=_filePos;
|
||||
// find a normal node ...
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if(_data[iii] == '>') {
|
||||
// we find the end ...
|
||||
_pos = iii+1;
|
||||
return exml::internal::Element::subParse(_data, _pos, _caseSensitive, _filePos, _doc, false);
|
||||
}
|
||||
if (_data[iii] == '/') {
|
||||
// standalone node or error...
|
||||
if (iii+1>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find end of files ... == > bad case");
|
||||
return false;
|
||||
}
|
||||
// TODO : Can have white spaces ....
|
||||
if (_data[iii+1] == '>') {
|
||||
_pos = iii+1;
|
||||
return true;
|
||||
}
|
||||
// error
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find / without > char ...");
|
||||
return false;
|
||||
}
|
||||
if (checkAvaillable(_data[iii], true) == true) {
|
||||
// we find an attibute == > create a new and parse it :
|
||||
ememory::SharedPtr<exml::internal::Attribute> attribute = exml::internal::Attribute::create();
|
||||
if (attribute == nullptr) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
if (attribute->iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listAttribute.push_back(attribute);
|
||||
continue;
|
||||
}
|
||||
if (isWhiteChar(_data[iii]) == false) {
|
||||
CREATE_ERROR(_doc, _data, iii, _filePos, std::string("Find an unknow element : '") + _data[iii] + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, std::string("Unexpecting end of parsing exml::internal::Element : '") + m_value + "' == > check if the '/>' is set or the end of element");
|
||||
return false;
|
||||
}
|
||||
|
||||
void exml::internal::Element::clear() {
|
||||
exml::internal::AttributeList::clear();
|
||||
m_listSub.clear();
|
||||
}
|
||||
|
||||
|
136
exml/internal/Element.h
Normal file
136
exml/internal/Element.h
Normal file
@ -0,0 +1,136 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/internal/Node.h>
|
||||
#include <vector>
|
||||
#include <exml/internal/AttributeList.h>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
/**
|
||||
* @brief Basic element Node of an XML document <YYYYY>
|
||||
*/
|
||||
class Element : public exml::internal::AttributeList {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Element() { };
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _value Element name;
|
||||
*/
|
||||
Element(const std::string& _value) :
|
||||
exml::internal::AttributeList(_value) {
|
||||
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* @brief factory of an exml::internal::Element
|
||||
* @param[in] _value Name of the node.
|
||||
* @return Shared pointer on the Element
|
||||
*/
|
||||
static ememory::SharedPtr<Element> create(const std::string& _value="");
|
||||
protected:
|
||||
std::vector<ememory::SharedPtr<exml::internal::Node>> m_listSub; //!< List of subNodes
|
||||
public:
|
||||
/**
|
||||
* @brief get the number of sub element in the node (can be exml::internal::Comment ; exml::internal::Element ; exml::internal::Text :exml::internal::Declaration).
|
||||
* @return a number >=0.
|
||||
*/
|
||||
size_t size() const {
|
||||
return m_listSub.size();
|
||||
};
|
||||
/**
|
||||
* @brief add a node at the element (not exml::internal::Attribute (move in the attribute automaticly).
|
||||
* @param[in] _node Pointer of the node to add.
|
||||
*/
|
||||
void append(const ememory::SharedPtr<exml::internal::Node>& _node);
|
||||
/**
|
||||
* @brief get the type of the element id.
|
||||
* @param[in] _id Id of the element.
|
||||
* @return the Current type of the element or exml::internal::typeUnknow.
|
||||
*/
|
||||
enum nodeType getType(int32_t _id) const;
|
||||
/**
|
||||
* @brief get the Node pointer of the element id.
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on node.
|
||||
*/
|
||||
ememory::SharedPtr<Node> getNode(int32_t _id);
|
||||
/**
|
||||
* @brief get the Node pointer of the element id.
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on node.
|
||||
*/
|
||||
ememory::SharedPtr<const Node> getNode(int32_t _id) const;
|
||||
/**
|
||||
* @brief get the element casted in Element (if the node is not an element return NULL).
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<Element> getElement(int32_t _id); // TODO : DEPRECATED ... not use anymore ...
|
||||
/**
|
||||
* @brief get the element casted in Element (if the node is not an element return NULL).
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<const Element> getElement(int32_t _id) const;// TODO : DEPRECATED ... not use anymore ...
|
||||
/**
|
||||
* @brief get an element with his name (work only with exml::internal::Element)
|
||||
* @param[in] _name Name of the element that is requested
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<Element> getNamed(const std::string& _name);
|
||||
/**
|
||||
* @brief get an element with his name (work only with exml::internal::Element)
|
||||
* @param[in] _name Name of the element that is requested
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
ememory::SharedPtr<const Element> getNamed(const std::string& _name) const;
|
||||
/**
|
||||
* @brief get the internal data of the element (if the element has some sub node thay are converted in xml string == > like this it is not needed to use <![CDATA[...]]>
|
||||
* @return the curent data string. if Only one text node, then we get the parssed data (no & ...) if more than one node, then we transform &,",',<,> in xml normal text...
|
||||
*/
|
||||
std::string getText() const;
|
||||
protected:
|
||||
/**
|
||||
* @brief Parse sub node string
|
||||
* @param[in] _data all file string data
|
||||
* @param[in,out] _pos Position to start parsing in the file and return the end of parsing
|
||||
* @param[in] _caseSensitive Case sensitive parsing (usefull for html)
|
||||
* @param[in] _filePos Current File position of the parsing
|
||||
* @param[in] _doc Document base reference
|
||||
* @param[in] _mainNode if true, this is the first root node
|
||||
* @return true parsing is done OK
|
||||
* @return false An error appear in the parsing
|
||||
*/
|
||||
bool subParse(const std::string& _data,
|
||||
int32_t& _pos,
|
||||
bool _caseSensitive,
|
||||
exml::FilePos& _filePos,
|
||||
exml::internal::Document& _doc,
|
||||
bool _mainNode=false);
|
||||
public:
|
||||
enum nodeType getType() const override {
|
||||
return nodeType_element;
|
||||
}
|
||||
bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::internal::Element> toElement() override {
|
||||
return std::static_pointer_cast<exml::internal::Element>(shared_from_this());
|
||||
}
|
||||
ememory::SharedPtr<const exml::internal::Element> toElement() const override {
|
||||
return std::static_pointer_cast<const exml::internal::Element>(shared_from_this());
|
||||
}
|
||||
void clear() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
203
exml/internal/Node.cpp
Normal file
203
exml/internal/Node.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/Node.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
exml::internal::Node::Node(const std::string& _value) :
|
||||
m_pos(0,0),
|
||||
m_value(_value) {
|
||||
// nothing to do.
|
||||
}
|
||||
|
||||
|
||||
void exml::internal::Node::addIndent(std::string& _data, int32_t _indent) const {
|
||||
for (int32_t iii=0; iii<_indent; iii++) {
|
||||
_data += "\t";
|
||||
}
|
||||
}
|
||||
|
||||
void exml::internal::Node::drawElementParsed(char32_t _val, const exml::FilePos& _filePos) const {
|
||||
if (_val == '\n') {
|
||||
EXML_DEBUG(_filePos << " parse '\\n'");
|
||||
} else if (_val == '\t') {
|
||||
EXML_DEBUG(_filePos << " parse '\\t'");
|
||||
} else {
|
||||
EXML_DEBUG(_filePos << " parse '" << _val << "'");
|
||||
}
|
||||
}
|
||||
|
||||
bool exml::internal::Node::checkAvaillable(char32_t _val, bool _firstChar) const {
|
||||
if( _val == '!'
|
||||
|| _val == '"'
|
||||
|| _val == '#'
|
||||
|| _val == '$'
|
||||
|| _val == '%'
|
||||
|| _val == '&'
|
||||
|| _val == '\'' // '
|
||||
|| _val == '('
|
||||
|| _val == ')'
|
||||
|| _val == '*'
|
||||
|| _val == '+'
|
||||
|| _val == ','
|
||||
|| _val == '/'
|
||||
|| _val == ';'
|
||||
|| _val == '<'
|
||||
|| _val == '='
|
||||
|| _val == '>'
|
||||
|| _val == '?'
|
||||
|| _val == '@'
|
||||
|| _val == '['
|
||||
|| _val == '\\'
|
||||
|| _val == ']'
|
||||
|| _val == '^'
|
||||
|| _val == '`'
|
||||
|| _val == '{'
|
||||
|| _val == '|'
|
||||
|| _val == '}'
|
||||
|| _val == '~'
|
||||
|| _val == ' '
|
||||
|| _val == '\n'
|
||||
|| _val == '\t'
|
||||
|| _val == '\r') {
|
||||
return false;
|
||||
}
|
||||
if (_firstChar == true) {
|
||||
if( _val == '-'
|
||||
|| _val == '.'
|
||||
|| ( _val >= '0'
|
||||
&& _val <= '9') ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32_t exml::internal::Node::countWhiteChar(const std::string& _data, int32_t _pos, exml::FilePos& _filePos) const {
|
||||
_filePos.clear();
|
||||
int32_t white=0;
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
if(isWhiteChar(_data[iii]) == true) {
|
||||
white++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
--_filePos;
|
||||
return white;
|
||||
}
|
||||
|
||||
bool exml::internal::Node::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
const exml::FilePos& exml::internal::Node::getPos() const {
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
void exml::internal::Node::clear() {
|
||||
m_value = "";
|
||||
m_pos.clear();
|
||||
}
|
||||
|
||||
void exml::internal::Node::setValue(std::string _value) {
|
||||
m_value = _value;
|
||||
}
|
||||
|
||||
const std::string& exml::internal::Node::getValue() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
enum exml::nodeType exml::internal::Node::getType() const {
|
||||
return nodeType_node;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Document> exml::internal::Node::toDocument() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Document> exml::internal::Node::toDocument() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Attribute> exml::internal::Node::toAttribute() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Attribute> exml::internal::Node::toAttribute() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Comment> exml::internal::Node::toComment() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Comment> exml::internal::Node::toComment() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Declaration> exml::internal::Node::toDeclaration() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Declaration> exml::internal::Node::toDeclaration() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Element> exml::internal::Node::toElement() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Element> exml::internal::Node::toElement() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Text> exml::internal::Node::toText() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<const exml::internal::Text> exml::internal::Node::toText() const{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool exml::internal::Node::isDocument() const {
|
||||
return getType() == exml::nodeType_document;
|
||||
}
|
||||
|
||||
bool exml::internal::Node::isAttribute() const {
|
||||
return getType() == exml::nodeType_attribute;
|
||||
}
|
||||
|
||||
bool exml::internal::Node::isComment() const {
|
||||
return getType() == exml::nodeType_comment;
|
||||
}
|
||||
|
||||
bool exml::internal::Node::isDeclaration() const {
|
||||
return getType() == exml::nodeType_declaration;
|
||||
}
|
||||
|
||||
bool exml::internal::Node::isElement() const {
|
||||
return getType() == exml::nodeType_element;
|
||||
}
|
||||
|
||||
bool exml::internal::Node::isText() const {
|
||||
return getType() == exml::nodeType_text;
|
||||
}
|
||||
|
235
exml/internal/Node.h
Normal file
235
exml/internal/Node.h
Normal file
@ -0,0 +1,235 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ememory/memory.h>
|
||||
#include <etk/types.h>
|
||||
#include <etk/math/Vector2D.h>
|
||||
#include <exml/FilePos.h>
|
||||
#include <exml/nodeType.h>
|
||||
|
||||
/**
|
||||
* @brief exml namespace containing all function for XML interpretor
|
||||
*/
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
//#define ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
//#define ENABLE_CRITICAL_WHEN_ERROR
|
||||
#if 1
|
||||
#define EXML_PARSE_ELEMENT EXML_VERBOSE
|
||||
#else
|
||||
#define EXML_PARSE_ELEMENT EXML_DEBUG
|
||||
#endif
|
||||
#if 1
|
||||
#define EXML_PARSE_ATTRIBUTE EXML_VERBOSE
|
||||
#else
|
||||
#define EXML_PARSE_ATTRIBUTE EXML_DEBUG
|
||||
#endif
|
||||
class Document;
|
||||
class Attribute;
|
||||
class Comment;
|
||||
class Declaration;
|
||||
class Element;
|
||||
class Text;
|
||||
|
||||
/**
|
||||
* @brief Basic main object of all xml elements.
|
||||
*/
|
||||
class Node : public ememory::EnableSharedFromThis<Node>{
|
||||
protected:
|
||||
/**
|
||||
* @brief basic element of a xml structure
|
||||
*/
|
||||
Node() :
|
||||
m_pos(0,0) {
|
||||
|
||||
};
|
||||
/**
|
||||
* @brief basic element of a xml structure
|
||||
* @param[in] _value value of the node
|
||||
*/
|
||||
Node(const std::string& _value);
|
||||
public:
|
||||
/**
|
||||
* @brief Virtualize destructor
|
||||
*/
|
||||
virtual ~Node() = default;
|
||||
public:
|
||||
/**
|
||||
* @brief parse the Current node [pure VIRUAL]
|
||||
* @param[in] _data data string to parse.
|
||||
* @param[in,out] _pos position in the string to start parse, return the position end of parsing.
|
||||
* @param[in] _caseSensitive Request a parsion of element that is not case sensitive (all element is in low case)
|
||||
* @param[in,out] _filePos file parsing position (line x col x)
|
||||
* @param[in,out] _doc Base document reference
|
||||
* @return false if an error occured.
|
||||
*/
|
||||
virtual bool iParse(const std::string& _data, int32_t& _pos, bool _caseSensitive, exml::FilePos& _filePos, exml::internal::Document& _doc) = 0;
|
||||
/**
|
||||
* @brief generate a string with the tree of the xml
|
||||
* @param[in,out] _data string where to add the elements
|
||||
* @param[in] _indent current indentation of the file
|
||||
* @return false if an error occured.
|
||||
*/
|
||||
virtual bool iGenerate(std::string& _data, int32_t _indent) const;
|
||||
protected:
|
||||
exml::FilePos m_pos; //!< position in the readed file == > not correct when the file is generated
|
||||
public:
|
||||
/**
|
||||
* @brief get the current position where the element is in the file
|
||||
* @return The file position reference
|
||||
*/
|
||||
const exml::FilePos& getPos() const;
|
||||
protected:
|
||||
std::string m_value; //!< value of the node (for element this is the name, for text it is the inside text ...)
|
||||
public:
|
||||
/**
|
||||
* @brief set the value of the node.
|
||||
* @param[in] _value New value of the node.
|
||||
*/
|
||||
virtual void setValue(std::string _value);
|
||||
/**
|
||||
* @brief get the current element Value.
|
||||
* @return the reference of the string value.
|
||||
*/
|
||||
virtual const std::string& getValue() const;
|
||||
public:
|
||||
/**
|
||||
* @brief get the node type.
|
||||
* @return the type of the Node.
|
||||
*/
|
||||
virtual enum nodeType getType() const;
|
||||
protected:
|
||||
/**
|
||||
* @brief add indentation of the string input.
|
||||
* @param[in,out] _data String where the indentation is done.
|
||||
* @param[in] _indent Number of tab to add at the string.
|
||||
*/
|
||||
void addIndent(std::string& _data, int32_t _indent) const;
|
||||
/**
|
||||
* @brief Display the cuurent element that is curently parse.
|
||||
* @param[in] _val Char that is parsed.
|
||||
* @param[in] _filePos Position of the char in the file.
|
||||
*/
|
||||
void drawElementParsed(char32_t _val, const exml::FilePos& _filePos) const;
|
||||
/**
|
||||
* @brief check if an element or attribute is availlable (not : !"#$%&'()*+,/;<=>?@[\]^`{|}~ \\n\\t\\r and for first char : not -.0123456789).
|
||||
* @param[in] _val Value to check the conformity.
|
||||
* @param[in] _firstChar True if the element check is the first char.
|
||||
* @return true The value can be a part of attribute name
|
||||
* @return false The value can NOT be a part of attribute name
|
||||
*/
|
||||
bool checkAvaillable(char32_t _val, bool _firstChar) const;
|
||||
/**
|
||||
* @brief count the number of white char in the string from the specify position (stop at the first element that is not a white char)
|
||||
* @param[in] _data Data to parse.
|
||||
* @param[in] _pos Start position in the string.
|
||||
* @param[out] _filePos new poistion of te file to add.
|
||||
* @return number of white element.
|
||||
*/
|
||||
int32_t countWhiteChar(const std::string& _data, int32_t _pos, exml::FilePos& _filePos) const;
|
||||
public:
|
||||
/**
|
||||
* @brief Cast the element in a Document if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::internal::Document> toDocument();
|
||||
/**
|
||||
* @brief Cast the element in a Document if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::internal::Document> toDocument() const;
|
||||
/**
|
||||
* @brief Cast the element in a Attribute if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::internal::Attribute> toAttribute();
|
||||
/**
|
||||
* @brief Cast the element in a Attribute if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::internal::Attribute> toAttribute() const;
|
||||
/**
|
||||
* @brief Cast the element in a Comment if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::internal::Comment> toComment();
|
||||
/**
|
||||
* @brief Cast the element in a Comment if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::internal::Comment> toComment() const;
|
||||
/**
|
||||
* @brief Cast the element in a Declaration if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::internal::Declaration> toDeclaration();
|
||||
/**
|
||||
* @brief Cast the element in a Declaration if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::internal::Declaration> toDeclaration() const;
|
||||
/**
|
||||
* @brief Cast the element in a Element if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::internal::Element> toElement();
|
||||
/**
|
||||
* @brief Cast the element in a Element if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::internal::Element> toElement() const;
|
||||
/**
|
||||
* @brief Cast the element in a Text if it is possible.
|
||||
* @return pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<exml::internal::Text> toText();
|
||||
/**
|
||||
* @brief Cast the element in a Text if it is possible.
|
||||
* @return CONST pointer on the class or nullptr.
|
||||
*/
|
||||
virtual ememory::SharedPtr<const exml::internal::Text> toText() const;
|
||||
|
||||
/**
|
||||
* @brief check if the node is a exml::internal::Document
|
||||
* @return true if the node is a exml::internal::Document
|
||||
*/
|
||||
bool isDocument() const;
|
||||
/**
|
||||
* @brief check if the node is a exml::internal::Attribute
|
||||
* @return true if the node is a exml::internal::Attribute
|
||||
*/
|
||||
bool isAttribute() const;
|
||||
/**
|
||||
* @brief check if the node is a exml::internal::Comment
|
||||
* @return true if the node is a exml::internal::Comment
|
||||
*/
|
||||
bool isComment() const;
|
||||
/**
|
||||
* @brief check if the node is a exml::internal::Declaration
|
||||
* @return true if the node is a exml::internal::Declaration
|
||||
*/
|
||||
bool isDeclaration() const;
|
||||
/**
|
||||
* @brief check if the node is a exml::internal::Element
|
||||
* @return true if the node is a exml::internal::Element
|
||||
*/
|
||||
bool isElement() const;
|
||||
/**
|
||||
* @brief check if the node is a exml::internal::Text
|
||||
* @return true if the node is a exml::internal::Text
|
||||
*/
|
||||
bool isText() const;
|
||||
|
||||
/**
|
||||
* @brief clear the Node
|
||||
*/
|
||||
virtual void clear();
|
||||
};
|
||||
}
|
||||
}
|
161
exml/internal/Text.cpp
Normal file
161
exml/internal/Text.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/internal/Text.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/internal/Document.h>
|
||||
#include <regex>
|
||||
|
||||
// transform the Text with :
|
||||
// "<" == "<"
|
||||
// ">" == ">"
|
||||
// "&" == "&"
|
||||
// "'" == "'"
|
||||
// """ == """
|
||||
static std::string replaceSpecialChar(const std::string& _inval) {
|
||||
std::string out;
|
||||
static std::regex regexLT("<");
|
||||
static std::regex regexGT(">");
|
||||
static std::regex regexAPOS("'");
|
||||
static std::regex regexQUOT(""");
|
||||
static std::regex regexAMP("&");
|
||||
|
||||
out = std::regex_replace(_inval, regexLT, std::string("<"));
|
||||
out = std::regex_replace(out, regexGT, std::string(">"));
|
||||
out = std::regex_replace(out, regexAPOS, std::string("'"));
|
||||
out = std::regex_replace(out, regexQUOT, std::string("\""));
|
||||
out = std::regex_replace(out, regexAMP, std::string("&"));
|
||||
//EXML_ERROR("INNN '"<< _inval << "' => '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
static std::string replaceSpecialCharOut(const std::string& _inval) {
|
||||
std::string out;
|
||||
static std::regex regexLT("<");
|
||||
static std::regex regexGT(">;");
|
||||
static std::regex regexAMP("&");
|
||||
static std::regex regexAPOS("'");
|
||||
static std::regex regexQUOT("\"");
|
||||
|
||||
out = std::regex_replace(_inval, regexAMP, std::string("&"));
|
||||
out = std::regex_replace(out, regexQUOT, std::string("""));
|
||||
out = std::regex_replace(out, regexAPOS, std::string("'"));
|
||||
out = std::regex_replace(out, regexGT, std::string(">"));
|
||||
out = std::regex_replace(out, regexLT, std::string("<"));
|
||||
//EXML_ERROR("OUTTT '"<< _inval << "' => '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool isWhiteChar(char32_t _val) {
|
||||
if( _val == ' '
|
||||
|| _val == '\t'
|
||||
|| _val == '\n'
|
||||
|| _val == '\r') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<exml::internal::Text> exml::internal::Text::create(const std::string& _data) {
|
||||
return ememory::SharedPtr<exml::internal::Text>(new exml::internal::Text(_data));
|
||||
}
|
||||
|
||||
bool exml::internal::Text::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
_data += replaceSpecialCharOut(m_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t exml::internal::Text::countLines() const {
|
||||
int32_t count = 1;
|
||||
for (size_t iii=0; iii<m_value.size(); iii++) {
|
||||
if(m_value[iii] == '\n') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool exml::internal::Text::iParse(const std::string& _data,
|
||||
int32_t& _pos,
|
||||
bool _caseSensitive,
|
||||
exml::FilePos& _filePos,
|
||||
exml::internal::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'text'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
|| _data[iii] == '<') {
|
||||
// search whitespace :
|
||||
size_t newEnd=iii;
|
||||
for (int64_t jjj=(int64_t)iii-1; jjj>(int64_t)_pos; --jjj) {
|
||||
if(isWhiteChar(_data[jjj]) == true) {
|
||||
newEnd = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// find end of value:
|
||||
m_value = std::string(_data, _pos, newEnd-(_pos));
|
||||
EXML_VERBOSE(" find text '" << m_value << "'");
|
||||
_pos = iii-1;
|
||||
m_value = replaceSpecialChar(m_value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Text got end of file without finding end node");
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<exml::internal::TextCDATA> exml::internal::TextCDATA::create() {
|
||||
return ememory::SharedPtr<exml::internal::TextCDATA>(new exml::internal::TextCDATA());
|
||||
}
|
||||
|
||||
bool exml::internal::TextCDATA::iGenerate(std::string& _data, int32_t _indent) const {
|
||||
_data += "<![CDATA[" + m_value +"]]>";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::internal::TextCDATA::iParse(const std::string& _data,
|
||||
int32_t& _pos,
|
||||
bool _caseSensitive,
|
||||
exml::FilePos& _filePos,
|
||||
exml::internal::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'text::CDATA'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (size_t iii=_pos; iii+2<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == ']'
|
||||
&& _data[iii+1] == ']'
|
||||
&& _data[iii+2] == '>') {
|
||||
// find end of value:
|
||||
_filePos += 2;
|
||||
m_value = std::string(_data, _pos, iii-(_pos));
|
||||
EXML_VERBOSE(" find text CDATA '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "text CDATA got end of file without finding end node");
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
83
exml/internal/Text.h
Normal file
83
exml/internal/Text.h
Normal file
@ -0,0 +1,83 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exml/internal/Node.h>
|
||||
#include <vector>
|
||||
|
||||
namespace exml {
|
||||
namespace internal {
|
||||
/**
|
||||
* @brief Text node interface (internal data between two balise : <XXX> ALL here </XXX>
|
||||
*/
|
||||
class Text : public exml::internal::Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Text() { };
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _data String data of the current Text
|
||||
*/
|
||||
Text(const std::string& _data) : exml::internal::Node(_data) { };
|
||||
public:
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @param[in] _data Data in the Text area
|
||||
* @return Shared pointer on the Text element
|
||||
*/
|
||||
static ememory::SharedPtr<exml::internal::Text> create(const std::string& _data="");
|
||||
/**
|
||||
* @brief count the number of line in the current text
|
||||
* @return The number of lines
|
||||
*/
|
||||
int32_t countLines() const;
|
||||
public:
|
||||
enum nodeType getType() const override{
|
||||
return nodeType_text;
|
||||
};
|
||||
bool iParse(const std::string& _data,
|
||||
int32_t& _pos,
|
||||
bool _caseSensitive,
|
||||
exml::FilePos& _filePos,
|
||||
exml::internal::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
ememory::SharedPtr<exml::internal::Text> toText() override {
|
||||
return std::static_pointer_cast<exml::internal::Text>(shared_from_this());
|
||||
};
|
||||
ememory::SharedPtr<const exml::internal::Text> toText() const override {
|
||||
return std::static_pointer_cast<const exml::internal::Text>(shared_from_this());
|
||||
};
|
||||
};
|
||||
/**
|
||||
* @brief Text node interface for balise CDATA <![CDATA[*******]]>
|
||||
*/
|
||||
class TextCDATA : public exml::internal::Text {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TextCDATA() { };
|
||||
public:
|
||||
/**
|
||||
* @brief defined factory
|
||||
* @return Shared pointer on the Text CDATA element
|
||||
*/
|
||||
static ememory::SharedPtr<TextCDATA> create();
|
||||
public:
|
||||
bool iParse(const std::string& _data,
|
||||
int32_t& _pos,
|
||||
bool _caseSensitive,
|
||||
exml::FilePos& _filePos,
|
||||
exml::internal::Document& _doc) override;
|
||||
bool iGenerate(std::string& _data, int32_t _indent) const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
101
exml/iterator.h
Normal file
101
exml/iterator.h
Normal file
@ -0,0 +1,101 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ememory/memory.h>
|
||||
#include <etk/types.h>
|
||||
|
||||
namespace exml {
|
||||
/**
|
||||
* iterator on elements.
|
||||
*/
|
||||
template<class EXML_BASE_T, class EXML_RETURN_T>
|
||||
class iterator {
|
||||
private:
|
||||
EXML_BASE_T& m_data; //!< Reference on the exml::Element
|
||||
size_t m_id; //!< Id of the element that we are parsing
|
||||
public:
|
||||
iterator(EXML_BASE_T& _obj, size_t _pos);
|
||||
iterator(const EXML_BASE_T& _obj, size_t _pos);
|
||||
iterator(const iterator& _obj);
|
||||
/**
|
||||
* @brief Operator+= Addition value
|
||||
* @param[in] _val Value to addition
|
||||
* @return Local reference of the iterator additionned
|
||||
*/
|
||||
iterator& operator= (const iterator& _obj);
|
||||
/**
|
||||
* @brief Operator+= Addition value
|
||||
* @param[in] _val Value to addition
|
||||
* @return Local reference of the iterator additionned
|
||||
*/
|
||||
iterator& operator+= (int32_t _val);
|
||||
/**
|
||||
* @brief Operator+ Addition a value
|
||||
* @param[in] _val Value to addition
|
||||
* @return New iterator containing the value
|
||||
*/
|
||||
iterator operator+ (int32_t _val) const;
|
||||
/**
|
||||
* @brief Operator-= Decrement a value
|
||||
* @param[in] _val Value to addition
|
||||
* @return Local reference of the iterator decremented
|
||||
*/
|
||||
iterator& operator-= (int32_t _val);
|
||||
/**
|
||||
* @brief Operator- Decrement a value
|
||||
* @param[in] _val Value to addition
|
||||
* @return New iterator containing the value
|
||||
*/
|
||||
iterator operator- (int32_t _val) const;
|
||||
/**
|
||||
* @brief Operator++ Pre-incrementation of this iterator
|
||||
* @return Local reference of the iterator incremented
|
||||
*/
|
||||
iterator& operator++();
|
||||
/**
|
||||
* @brief Operator++ Post-incrementation of this iterator
|
||||
* @return New iterator containing the last value
|
||||
*/
|
||||
iterator operator++(int);
|
||||
/**
|
||||
* @brief Operator++ Pre-decrementation of this iterator
|
||||
* @return Local reference of the iterator incremented
|
||||
*/
|
||||
iterator& operator--();
|
||||
/**
|
||||
* @brief Operator++ Post-decrementation of this iterator
|
||||
* @return New iterator containing the last value
|
||||
*/
|
||||
iterator operator--(int);
|
||||
/**
|
||||
* @brief Equality compare operator with an other iterator.
|
||||
* @param[in] _obj Reference on the comparing iterator
|
||||
* @return true The iterators are identical
|
||||
* @return false The iterators are NOT identical
|
||||
*/
|
||||
bool operator== (const iterator& _obj) const;
|
||||
/**
|
||||
* @brief In-Equality compare operator with an other iterator.
|
||||
* @param[in] _obj Reference on the comparing iterator
|
||||
* @return true The iterators are NOT identical
|
||||
* @return false The iterators are identical
|
||||
*/
|
||||
bool operator!= (const iterator& _obj) const;
|
||||
/**
|
||||
* @brief Get the property Value
|
||||
* @return Const reference on the value.
|
||||
*/
|
||||
const EXML_RETURN_T operator *() const noexcept;
|
||||
/**
|
||||
* @brief Get the property Value
|
||||
* @return Const reference on the value.
|
||||
*/
|
||||
EXML_RETURN_T operator *() noexcept;
|
||||
};
|
||||
}
|
43
exml/nodeType.cpp
Normal file
43
exml/nodeType.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/nodeType.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
|
||||
|
||||
std::ostream& exml::operator <<(std::ostream& _os, enum exml::nodeType _obj) {
|
||||
switch (_obj) {
|
||||
case nodeType_unknow:
|
||||
_os << "exml::nodeType_unknow";
|
||||
break;
|
||||
case nodeType_node:
|
||||
_os << "exml::nodeType_node";
|
||||
break;
|
||||
case nodeType_document:
|
||||
_os << "exml::nodeType_document";
|
||||
break;
|
||||
case nodeType_declaration:
|
||||
_os << "exml::nodeType_declaration";
|
||||
break;
|
||||
case nodeType_attribute:
|
||||
_os << "exml::nodeType_attribute";
|
||||
break;
|
||||
case nodeType_element:
|
||||
_os << "exml::nodeType_element";
|
||||
break;
|
||||
case nodeType_comment:
|
||||
_os << "exml::nodeType_comment";
|
||||
break;
|
||||
case nodeType_text:
|
||||
_os << "exml::nodeType_text";
|
||||
break;
|
||||
}
|
||||
return _os;
|
||||
}
|
||||
|
32
exml/nodeType.h
Normal file
32
exml/nodeType.h
Normal file
@ -0,0 +1,32 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
|
||||
/**
|
||||
* @brief exml namespace containing all function for XML interpretor
|
||||
*/
|
||||
namespace exml {
|
||||
/**
|
||||
* @brief Type of the XML elements.
|
||||
*/
|
||||
enum nodeType {
|
||||
nodeType_unknow, //!< might be an error ...
|
||||
nodeType_node, //!< might be an error ...
|
||||
nodeType_document, //!< all the file main access
|
||||
nodeType_declaration, //!< <?xml ... ?>
|
||||
nodeType_attribute, //!< the <Element ATTRIBUTE="ATTRIBUTE_VALUE" />
|
||||
nodeType_element, //!< the <XXX> ... </XXX>
|
||||
nodeType_comment, //!< comment node : <!-- -->
|
||||
nodeType_text, //!< <XXX> InsideText </XXX>
|
||||
};
|
||||
//! @not_in_doc
|
||||
std::ostream& operator <<(std::ostream& _os, enum nodeType _obj);
|
||||
}
|
||||
|
36
lutin_exml-sample.py
Normal file
36
lutin_exml-sample.py
Normal file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
import datetime
|
||||
|
||||
def get_type():
|
||||
return "BINARY"
|
||||
|
||||
def get_sub_type():
|
||||
return "SAMPLE"
|
||||
|
||||
def get_desc():
|
||||
return "e-signal sample 1"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_src_file([
|
||||
'sample/main.cpp',
|
||||
'sample/read.cpp',
|
||||
'sample/write.cpp'
|
||||
])
|
||||
my_module.add_module_depend(['exml', 'test-debug'])
|
||||
return my_module
|
||||
|
@ -31,6 +31,7 @@ def create(target, module_name):
|
||||
my_module.add_src_file([
|
||||
'exml/debug.cpp',
|
||||
'exml/FilePos.cpp',
|
||||
'exml/nodeType.cpp',
|
||||
'exml/Attribute.cpp',
|
||||
'exml/AttributeList.cpp',
|
||||
'exml/Comment.cpp',
|
||||
@ -38,11 +39,23 @@ def create(target, module_name):
|
||||
'exml/Document.cpp',
|
||||
'exml/Element.cpp',
|
||||
'exml/Node.cpp',
|
||||
'exml/Text.cpp'
|
||||
'exml/Text.cpp',
|
||||
])
|
||||
my_module.add_src_file([
|
||||
'exml/internal/Attribute.cpp',
|
||||
'exml/internal/AttributeList.cpp',
|
||||
'exml/internal/Comment.cpp',
|
||||
'exml/internal/Declaration.cpp',
|
||||
'exml/internal/Document.cpp',
|
||||
'exml/internal/Element.cpp',
|
||||
'exml/internal/Node.cpp',
|
||||
'exml/internal/Text.cpp'
|
||||
])
|
||||
my_module.add_header_file([
|
||||
'exml/FilePos.h',
|
||||
'exml/nodeType.h',
|
||||
'exml/exml.h',
|
||||
'exml/iterator.h',
|
||||
'exml/Attribute.h',
|
||||
'exml/AttributeList.h',
|
||||
'exml/Comment.h',
|
||||
@ -50,7 +63,15 @@ def create(target, module_name):
|
||||
'exml/Document.h',
|
||||
'exml/Element.h',
|
||||
'exml/Node.h',
|
||||
'exml/Text.h'
|
||||
'exml/Text.h',
|
||||
'exml/internal/Attribute.h',
|
||||
'exml/internal/AttributeList.h',
|
||||
'exml/internal/Comment.h',
|
||||
'exml/internal/Declaration.h',
|
||||
'exml/internal/Document.h',
|
||||
'exml/internal/Element.h',
|
||||
'exml/internal/Node.h',
|
||||
'exml/internal/Text.h'
|
||||
])
|
||||
my_module.add_path(tools.get_current_path(__file__))
|
||||
return my_module
|
||||
|
34
sample/main.cpp
Normal file
34
sample/main.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <test-debug/debug.h>
|
||||
#include <etk/etk.h>
|
||||
#include "read.h"
|
||||
#include "write.h"
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
// the only one init for etk:
|
||||
etk::init(argc, argv);
|
||||
for (int32_t iii=0; iii<argc ; ++iii) {
|
||||
std::string data = argv[iii];
|
||||
if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
TEST_PRINT("Help : ");
|
||||
TEST_PRINT(" ./xxx [options]");
|
||||
TEST_PRINT(" -h/--help: this help");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
TEST_INFO("read [START] ***************************");
|
||||
appl::read();
|
||||
TEST_INFO("read [STOP ] ***************************");
|
||||
TEST_INFO("write [START] ***************************");
|
||||
appl::write();
|
||||
TEST_INFO("write [STOP ] ***************************");
|
||||
return 0;
|
||||
}
|
45
sample/read.cpp
Normal file
45
sample/read.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <test-debug/debug.h>
|
||||
#include <exml/exml.h>
|
||||
#include "read.h"
|
||||
|
||||
void appl::read() {
|
||||
exml::Document doc;
|
||||
TEST_INFO("parse");
|
||||
bool retParse = doc.parse("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"true\"?>"
|
||||
"<!-- my comment -->"
|
||||
"<exml attributeExample=\"my data attribute\">coucou</exml>");
|
||||
TEST_INFO("parse ret = " << retParse);
|
||||
TEST_INFO("Debug display of the tree:");
|
||||
doc.display();
|
||||
TEST_INFO("list of attribute:");
|
||||
for (auto it: doc.attributes) {
|
||||
TEST_INFO(" " << it);
|
||||
}
|
||||
TEST_INFO("list of sub-node:");
|
||||
for (const auto it: doc) {
|
||||
TEST_INFO(" " << it);
|
||||
if (it.isElement() == false) {
|
||||
continue;
|
||||
}
|
||||
exml::Element elem = it.toElement();
|
||||
if (elem.exist() == false) {
|
||||
continue;
|
||||
}
|
||||
TEST_INFO(" list of attribute:");
|
||||
for (auto itElem: elem.attributes) {
|
||||
TEST_INFO(" " << itElem);
|
||||
}
|
||||
TEST_INFO(" list of sub-node:");
|
||||
for (const auto itElem: elem) {
|
||||
TEST_INFO(" " << itElem);
|
||||
}
|
||||
}
|
||||
}
|
13
sample/read.h
Normal file
13
sample/read.h
Normal file
@ -0,0 +1,13 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace appl {
|
||||
void read();
|
||||
}
|
15
sample/write.cpp
Normal file
15
sample/write.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <test-debug/debug.h>
|
||||
#include <exml/exml.h>
|
||||
#include "write.h"
|
||||
|
||||
void appl::write() {
|
||||
|
||||
}
|
14
sample/write.h
Normal file
14
sample/write.h
Normal file
@ -0,0 +1,14 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2016, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace appl {
|
||||
void write();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
|
Loading…
Reference in New Issue
Block a user