21 size_t pos = _string.find(
'&');
22 if (pos == std::string::npos)
23 return std::string{_string};
25 ret.reserve(_string.size());
27 while (pos != std::string::npos)
29 ret += _string.substr(old, pos - old);
31 size_t end = _string.find(
';', pos + 1);
32 if (end == std::string::npos)
38 std::string_view tag = _string.substr(pos, end - pos + 1);
41 else if (tag ==
"<")
43 else if (tag ==
">")
45 else if (tag ==
"'")
47 else if (tag ==
""")
56 pos = _string.find(
'&', old);
58 ret += _string.substr(old, std::string::npos);
67 size_t pos = _string.find_first_of(
"&<>'\"");
68 if (pos == std::string::npos)
69 return std::string{_string};
71 ret.reserve(_string.size() * 2);
73 while (pos != std::string::npos)
75 ret += _string.substr(old, pos - old);
77 if (_string[pos] ==
'&')
79 else if (_string[pos] ==
'<')
81 else if (_string[pos] ==
'>')
83 else if (_string[pos] ==
'\'')
85 else if (_string[pos] ==
'\"')
89 pos = _string.find_first_of(
"&<>'\"", old);
91 ret += _string.substr(old, std::string::npos);
101 ElementEnumerator::ElementEnumerator(VectorElement::iterator _begin, VectorElement::iterator _end) :
109 if (m_current == m_end)
117 return m_current != m_end;
124 if ((*m_current)->getName() == _name)
132 assert(m_current != m_end);
133 return m_current->get();
138 assert(m_current != m_end);
139 return m_current->get();
153 void Element::save(std::ostream& _stream,
size_t _level)
156 for (
size_t tab = 0; tab < _level; ++tab)
169 for (
auto& attribute : mAttributes)
174 bool empty = mChildren.empty();
176 if (empty && mContent.empty())
191 if (!mContent.empty())
195 for (
size_t tab = 0; tab <= _level; ++tab)
204 for (
const auto& child : mChildren)
206 child->save(_stream, _level + 1);
211 for (
size_t tab = 0; tab < _level; ++tab)
214 _stream <<
"</" << mName <<
">\n";
220 return mChildren.emplace_back(std::make_unique<Element>(_name,
this, _type, _content)).get();
225 for (
auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
227 if (iter->get() == _child)
229 mChildren.erase(iter);
244 for (
const auto& attribute : mAttributes)
246 if (attribute.first == _name)
248 _value = attribute.second;
257 for (
const auto& attribute : mAttributes)
259 if (attribute.first == _name)
260 return attribute.second;
267 mAttributes.emplace_back(_key, _value);
272 for (
size_t index = 0; index < mAttributes.size(); ++index)
274 if (mAttributes[index].first == _key)
276 mAttributes.erase(mAttributes.begin() + index);
284 auto elem = std::make_unique<Element>(mName,
nullptr, mType, mContent);
285 elem->mAttributes = mAttributes;
287 for (
const auto& oldChild : mChildren)
289 auto child = oldChild->createCopy();
290 child->mParent = elem.get();
291 elem->mChildren.emplace_back(std::move(child));
299 for (
auto& attribute : mAttributes)
301 if (attribute.first == _key)
303 attribute.second = _value;
307 mAttributes.emplace_back(_key, _value);
312 if (mContent.empty())
319 mContent += _content;
350 return {mChildren.begin(), mChildren.end()};
358#if MYGUI_COMPILER == MYGUI_COMPILER_MSVC && !defined(STLPORT)
359 inline void open_stream(std::ofstream& _stream,
const std::wstring& _wide)
361 _stream.open(_wide.c_str());
363 inline void open_stream(std::ifstream& _stream,
const std::wstring& _wide)
365 _stream.open(_wide.c_str());
368 inline void open_stream(std::ofstream& _stream,
const std::wstring& _wide)
370 _stream.open(
UString(_wide).asUTF8_c_str());
372 inline void open_stream(std::ifstream& _stream,
const std::wstring& _wide)
374 _stream.open(UString(_wide).asUTF8_c_str());
385 std::ifstream stream;
386 stream.open(_filename.c_str());
388 if (!stream.is_open())
391 setLastFileError(_filename);
395 bool result =
open(stream);
404 std::ifstream stream;
407 if (!stream.is_open())
410 setLastFileError(_filename);
414 bool result =
open(stream);
422 auto data = std::make_unique<DataStream>(&_stream);
424 bool result =
open(data.get());
432 std::ofstream stream;
433 stream.open(_filename.c_str());
435 if (!stream.is_open())
438 setLastFileError(_filename);
442 bool result =
save(stream);
446 setLastFileError(_filename);
456 std::ofstream stream;
459 if (!stream.is_open())
462 setLastFileError(_filename);
466 bool result =
save(stream);
470 setLastFileError(_filename);
489 while (!_stream->
eof())
495 if (read[read.size() - 1] ==
'\r')
496 read.erase(read.size() - 1, 1);
506 if (!parseLine(line, currentNode))
531 _stream << (char)0xEFu;
532 _stream << (char)0xBBu;
533 _stream << (char)0xBFu;
535 mDeclaration->save(_stream, 0);
537 mRoot->save(_stream, 0);
550 bool Document::parseTag(
ElementPtr& _currentNode, std::string _content)
555 if (_content.empty())
560 _currentNode = _currentNode->
createChild(std::string_view{});
564 mRoot = std::make_unique<Element>(std::string_view{},
nullptr);
565 _currentNode = mRoot.get();
570 char symbol = _content[0];
571 bool tagDeclaration =
false;
576 if (_currentNode !=
nullptr)
585 tagDeclaration =
true;
586 _content.erase(0, 1);
593 if (_currentNode ==
nullptr)
599 start = _content.find_first_not_of(
" \t", 1);
600 if (start == std::string::npos)
607 size_t end = _content.find_last_not_of(
" \t");
608 _content = _content.substr(start, end - start + 1);
611 if (_currentNode->
getName() != _content)
617 _currentNode = _currentNode->
getParent();
622 std::string cut = _content;
623 start = _content.find_first_of(
" \t/?", 1);
624 if (start != std::string::npos)
626 cut = _content.substr(0, start);
627 _content = _content.substr(start);
649 _currentNode = mDeclaration.get();
660 _currentNode = mRoot.get();
665 start = _content.find_last_not_of(
" \t");
666 if (start == std::string::npos)
671 if ((_content[start] ==
'/') || (_content[start] ==
'?'))
675 _content[start] =
' ';
677 start = _content.find_last_not_of(
" \t");
678 if (start == std::string::npos)
681 _currentNode = _currentNode->
getParent();
690 start = _content.find(
'=');
691 if (start == std::string::npos)
697 size_t end = _content.find_first_of(
"\"\'", start + 1);
698 if (end == std::string::npos)
703 end = _content.find_first_of(
"\"\'", end + 1);
704 if (end == std::string::npos)
710 std::string key = _content.substr(0, start);
711 std::string value = _content.substr(start + 1, end - start);
714 if (!checkPair(key, value))
724 _content = _content.substr(end + 1);
727 start = _content.find_first_not_of(
" \t");
728 if (start == std::string::npos)
738 _currentNode = _currentNode->
getParent();
744 bool Document::checkPair(std::string& _key, std::string& _value)
750 size_t start = _key.find_first_of(
" \t\"\'&");
751 if (start != std::string::npos)
756 if (_value.size() < 2)
758 if (((_value[0] !=
'"') || (_value[_value.length() - 1] !=
'"')) &&
759 ((_value[0] !=
'\'') || (_value[_value.length() - 1] !=
'\'')))
767 size_t Document::find(std::string_view _text,
char _char,
size_t _start)
773 char buff[16] =
"\"_\0";
780 pos = _text.find_first_of(buff, pos);
783 if (pos == std::string::npos)
788 if (_text[pos] ==
'"')
808 void Document::clearDeclaration()
810 mDeclaration.reset();
813 void Document::clearRoot()
822 mDeclaration->addAttribute(
"version", _version);
823 mDeclaration->addAttribute(
"encoding", _encoding);
824 return mDeclaration.get();
834 bool Document::parseLine(std::string& _line,
ElementPtr& _element)
840 size_t start = find(_line,
'<');
841 if (start == std::string::npos)
846 if ((start + 3 < _line.size()) && (_line[start + 1] ==
'!') && (_line[start + 2] ==
'-') &&
847 (_line[start + 3] ==
'-'))
849 end = _line.find(
"-->", start + 4);
850 if (end == std::string::npos)
856 end = find(_line,
'>', start + 1);
857 if (end == std::string::npos)
861 size_t body = _line.find_first_not_of(
" \t<");
864 std::string_view body_str = std::string_view{_line}.substr(0, start);
868 if (_element !=
nullptr)
880 if (!parseTag(_element, _line.substr(start + 1, end - start - 1)))
885 _line = _line.substr(end + 1);
892 std::string_view error = mLastError.print();
926 void Document::setLastFileError(std::string_view _filename)
928 mLastErrorFile = _filename;
931 void Document::setLastFileError(
const std::wstring& _filename)
virtual void readline(std::string &_source, Char _delim='\n')=0
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
const std::wstring & asWStr() const
returns the current string in the native form of std::wstring
const std::string & asUTF8() const
returns the current string in UTF-8 form within a std::string
bool save(const std::string &_filename)
std::string getLastError() const
ElementPtr getRoot() const
ElementPtr createRoot(std::string_view _name)
ElementPtr createDeclaration(std::string_view _version="1.0", std::string_view _encoding="UTF-8")
bool open(const std::string &_filename)
ElementPtr operator->() const
const std::string & getContent() const
bool findAttribute(std::string_view _name, std::string &_value)
std::unique_ptr< Element > createCopy()
ElementEnumerator getElementEnumerator()
ElementType getType() const
void removeChild(ElementPtr _child)
ElementPtr getParent() const
Element(std::string_view _name, ElementPtr _parent, ElementType _type=ElementType::Normal, std::string_view _content={})
const std::string & getName() const
void addAttribute(std::string_view _key, const T &_value)
void setAttribute(std::string_view _key, std::string_view _value)
void removeAttribute(std::string_view _key)
void setContent(const T &_content)
void addContent(const T &_content)
const VectorAttributes & getAttributes() const
ElementPtr createChild(std::string_view _name, std::string_view _content={}, ElementType _type=ElementType::Normal)
std::string toString(T _value)
void trim(std::string &_str, bool _left=true, bool _right=true)
static std::string convert_from_xml(std::string_view _string, bool &_ok)
static std::string convert_to_xml(std::string_view _string)
std::vector< PairAttribute > VectorAttributes
void open_stream(std::ofstream &_stream, const std::wstring &_wide)
@ MoreThanOneXMLDeclaration
@ InconsistentOpenCloseElements