Loading src/html.cpp +310 −272 Original line number Diff line number Diff line Loading @@ -342,9 +342,10 @@ void libhtmlpp::HtmlString::_buildtreenode( Frame fr = stack.top(); stack.pop(); HtmlElement *opener_el = static_cast<HtmlElement*>(fr.open->element.get()); if (fr.open->nextel) { if (fr.open->nextel->element) { for (DocElements *cnex=fr.open->nextel.get(); cnex; cnex=cnex->nextel.get()) { if (fr.open->nextel->element && !fr.open->nextel->terminator) { opener_el->_childElement = std::move(fr.open->nextel->element); break; } } Loading Loading @@ -414,194 +415,28 @@ void libhtmlpp::HtmlString::_buildTree() { HTMLException excp; for(size_t ii=0; ii<_Data.size(); ++ii){ BUILDTREE_STARTLOOP: if(_Data[ii]==HTMLTAG_OPEN){ if( (ii + 3) < _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+3), "<!--")){ size_t start=ii+3; while(ii<_Data.size()){ if(std::equal(_Data.begin()+ii,_Data.begin()+(ii+3),"-->")) { addelement(&lastEl); lastEl->element=std::make_unique<CommentElement>(); std::copy(_Data.begin()+start,_Data.begin()+ii, std::back_inserter(static_cast<CommentElement*>(lastEl->element.get())->_Comment)); ii+=2; break; } ++ii; } ii+=CommentElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else if((ii+6) < _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+6),"<script")){ size_t start=ii; while(ii<_Data.size()){ if(_Data[ii]==HTMLTAG_CLOSE) { addelement(&lastEl); lastEl->element=std::make_unique<ScriptElement>(); std::vector<char> tel; std::copy(_Data.begin()+start,_Data.begin()+ii,std::back_inserter(tel)); _serialelize(tel,static_cast<ScriptElement*>(lastEl->element.get())); break; } ++ii; } size_t close=++ii; while(ii<_Data.size()){ if( std::equal(_Data.begin()+ii,_Data.begin()+(ii+7),"</script")) { std::copy(_Data.begin()+close,_Data.begin()+ii, std::back_inserter(static_cast<ScriptElement*>(lastEl->element.get())->_Script)); ii+=8; break; } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Missing </script closing tag."; } ii+=ScriptElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else if( (ii+3) < _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+3),"<svg")){ size_t start=ii; while(ii<_Data.size()){ if(_Data[ii]==HTMLTAG_CLOSE) { addelement(&lastEl); lastEl->element=std::make_unique<SvgElement>(); std::vector<char> tel; std::copy(_Data.begin()+start,_Data.begin()+ii,std::back_inserter(tel)); _serialelize(tel,(SvgElement*)lastEl->element.get()); break; } ++ii; } size_t close=++ii; while(ii<_Data.size()){ if( std::equal(_Data.begin()+ii,_Data.begin()+(ii+4),"</svg")) { std::copy(_Data.begin()+close,_Data.begin()+ii, std::back_inserter(static_cast<SvgElement*>(lastEl->element.get())->_Svg)); ii+=5; break; } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Missing </textarea closing tag."; } ii+=SvgElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else if( (ii + 9) <= _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+9),"<textarea")){ size_t start = ii; while(ii < _Data.size()){ if(_Data[ii] == HTMLTAG_CLOSE) { addelement(&lastEl); lastEl->element = std::make_unique<TextArea>(); std::vector<char> tel; std::copy(_Data.begin() + start, _Data.begin() + ii, std::back_inserter(tel)); _serialelize(tel, (TextArea*)lastEl->element.get()); break; } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Unclosed <svg tag."; } size_t close = ++ii; size_t lvl = 0; while(ii < _Data.size()){ if( (ii + 9) <= _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+9),"<textarea")){ ++lvl; } if( (ii + 10) <= _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+10),"</textarea")) { if(lvl == 0){ std::copy(_Data.begin() + close, _Data.begin() + ii, std::back_inserter(static_cast<TextArea*>(lastEl->element.get())->_Text)); ii += 10; break; ii+=TextArea::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else { --lvl; } } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Missing </textarea closing tag."; } }else { size_t start=ii; addelement(&lastEl); lastEl->element=std::make_unique<HtmlElement>(); bool term=false; while(ii<_Data.size()){ if(!term && _Data[ii]==HTMLTAG_TERMINATE){ lastEl->terminator=true; }else if(_Data[ii]==HTMLTAG_CLOSE) { std::vector<char> tel; std::copy(_Data.begin()+start,_Data.begin()+ii,std::back_inserter(tel)); _serialelize(tel,static_cast<HtmlElement*>(lastEl->element.get())); break; } if(_Data[ii]!=' ' && _Data[ii]!=HTMLTAG_OPEN){ term=true; } ++ii; } ii+=HtmlElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); } }else if(_Data[ii]!=' '){ std::vector<char> buf; bool empty=true; while(ii<_Data.size()){ switch(_Data[ii]){ case HTMLTAG_OPEN: { if(!buf.empty()){ addelement(&lastEl); lastEl->element=std::make_unique<TextElement>(); std::copy(buf.begin(),buf.end(),std::back_inserter((static_cast<TextElement*>(lastEl->element.get()))->_Text)); } goto BUILDTREE_STARTLOOP; }; case '\r':{ ++ii; }break; case '\n':{ ++ii; }break; case ' ':{ if(!empty) buf.push_back(_Data[ii++]); else ++ii; }break; default:{ buf.push_back(_Data[ii++]); empty=false; }break; } ii+=TextElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); } } } _buildtreenode(firstEl.get(),nullptr,_rootEl); } /** Loading @@ -615,95 +450,6 @@ std::ostream& operator<<(std::ostream& os, const libhtmlpp::HtmlString& p) { os << p.str(); return os; } /** * @brief Extracts tag name and attributes from a token vector into an HtmlElement. * @param in Token buffer containing a single open tag. * @param out Destination HtmlElement to populate. * @throws HTMLException if no tag could be determined. */ void libhtmlpp::HtmlString::_serialelize(std::vector<char> in, libhtmlpp::HtmlElement *out) { size_t st=0,et=0; for (size_t i = 0; i < in.size(); ++i) { switch (in[i]) { case '<': continue; case '/': continue; case ' ': continue; default: st=i; goto GETTAGEND; } } GETTAGEND: for(et=st; et<in.size(); et++){ if(in[et]==' ' || in[et]=='/' || in[et]=='>' || in[et]=='\r' || in[et]=='\n'){ break; } } std::string tag; std::copy(in.begin()+st,in.begin()+et,std::back_inserter(tag)); out->setTagname(tag); if (!out) { HTMLException excp; throw excp[HTMLException::Critical] << "no tag in element found!"; } for(size_t i=et; i<in.size(); i++){ if(in[i]=='>') return; size_t kstart=std::string::npos,kend=std::string::npos; if(in[i]!=' ' && in[i]!='\r' && in[i]!='\n'){ kstart=i; kend=in.size(); bool value=false; size_t vstart=std::string::npos,vend=std::string::npos; while(i<in.size()){ if (in[i]=='='){ value=true; kend=i++; break; } ++i; } if(value){ while(i<in.size()){ if(in[i]=='\"'){ if (vstart==std::string::npos){ vstart=++i; continue; }else{ vend=i; break; } } ++i; } } if(kstart !=std::string::npos){ std::string key,val; std::copy(in.begin()+kstart,in.begin()+kend,std::back_inserter(key)); if(vend!=std::string::npos && vstart!=std::string::npos){ std::copy(in.begin()+vstart,in.begin()+vend,std::back_inserter(val)); } out->setAttribute(key,val); } } } } void libhtmlpp::HtmlEncode(const std::string &input, std::string &output){ size_t ilen=input.length(); Loading Loading @@ -929,6 +675,116 @@ void libhtmlpp::HtmlElement::remove(libhtmlpp::Element* el){ } /** * @brief Extracts tag name and attributes from a token vector into an HtmlElement. * @param in Token buffer containing a single open tag. * @param out Destination HtmlElement to populate. * @throws HTMLException if no tag could be determined. */ void libhtmlpp::HtmlElement::_serialelize(std::vector<char> in) { size_t st=0,et=0; for (size_t i = 0; i < in.size(); ++i) { switch (in[i]) { case '<': continue; case '/': continue; case ' ': continue; default: st=i; goto GETTAGEND; } } GETTAGEND: for(et=st; et<in.size(); et++){ if(in[et]==' ' || in[et]=='/' || in[et]=='>' || in[et]=='\r' || in[et]=='\n'){ break; } } std::string tag; std::copy(in.begin()+st,in.begin()+et,std::back_inserter(tag)); setTagname(tag); if (_TagName.empty()) { HTMLException excp; throw excp[HTMLException::Critical] << "no tag in element found!"; } for(size_t i=et; i<in.size(); i++){ if(in[i]=='>') return; size_t kstart=std::string::npos,kend=std::string::npos; if(in[i]!=' ' && in[i]!='\r' && in[i]!='\n'){ kstart=i; kend=in.size(); bool value=false; size_t vstart=std::string::npos,vend=std::string::npos; while(i<in.size()){ if (in[i]=='='){ value=true; kend=i++; break; } ++i; } if(value){ while(i<in.size()){ if(in[i]=='\"'){ if (vstart==std::string::npos){ vstart=++i; continue; }else{ vend=i; break; } } ++i; } } if(kstart !=std::string::npos){ std::string key,val; std::copy(in.begin()+kstart,in.begin()+kend,std::back_inserter(key)); if(vend!=std::string::npos && vstart!=std::string::npos){ std::copy(in.begin()+vstart,in.begin()+vend,std::back_inserter(val)); } setAttribute(key,val); } } } } size_t libhtmlpp::HtmlElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start,bool &termination){ size_t startel=start; el=std::make_unique<HtmlElement>(); bool term=false; while(start<in.size()){ if(!term && in[start]==HTMLTAG_TERMINATE){ termination=true; }else if(in[start]==HTMLTAG_CLOSE) { std::vector<char> tel; std::copy(in.begin()+startel,in.begin()+start,std::back_inserter(tel)); reinterpret_cast<HtmlElement*>(el.get())->_serialelize(tel); return start; } if(in[start]!=' '){ term=true; } ++start; } return start; } namespace libhtmlpp { Loading Loading @@ -1275,6 +1131,39 @@ int libhtmlpp::TextElement::getType() const{ return ElementType::TextEl; } size_t libhtmlpp::TextElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start,bool &termination){ std::vector<char> buf; bool empty=true,end=false; while(start<in.size() && !end){ switch(in[start]){ case HTMLTAG_OPEN: { if(!buf.empty()){ el=std::make_unique<TextElement>(); std::copy(buf.begin(),buf.end(),std::back_inserter((static_cast<TextElement*>(el.get()))->_Text)); } end=true; break; }; case '\r':{ ++start; }break; case '\n':{ ++start; }break; case ' ':{ if(!empty) buf.push_back(in[start++]); else ++start; }break; default:{ buf.push_back(in[start++]); empty=false; }break; } } return start; } libhtmlpp::CommentElement::CommentElement() : Element(){ } Loading Loading @@ -1310,6 +1199,29 @@ int libhtmlpp::CommentElement::getType() const{ return ElementType::CommentEl; } size_t libhtmlpp::CommentElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start, bool& termination){ size_t startel=start+3; while(start<in.size()){ if(std::equal(in.begin()+start,in.begin()+(start+3),"-->")) { el=std::make_unique<CommentElement>(); std::copy(in.begin()+startel,in.begin()+start, std::back_inserter(static_cast<CommentElement*>(el.get())->_Comment)); start+=2; break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing --> closing tag."; } return start; } libhtmlpp::ScriptElement::ScriptElement() : HtmlElement("script"){ } Loading Loading @@ -1343,6 +1255,45 @@ int libhtmlpp::ScriptElement::getType() const{ return ElementType::ScriptEL; } size_t libhtmlpp::ScriptElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start, bool& termination){ size_t startel=start; while(start<in.size()){ if(in[start]==HTMLTAG_CLOSE) { el=std::make_unique<ScriptElement>(); std::vector<char> tel; std::copy(in.begin()+startel,in.begin()+start,std::back_inserter(tel)); static_cast<ScriptElement*>(el.get())->_serialelize(tel); break; } ++start; } size_t close=++start; while(start<in.size()){ if( std::equal(in.begin()+start,in.begin()+(start+7),"</script")) { std::copy(in.begin()+close,in.begin()+start, std::back_inserter(static_cast<ScriptElement*>(el.get())->_Script)); start+=8; break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing </script closing tag."; } return start; } libhtmlpp::SvgElement::SvgElement() : HtmlElement("svg"){ } Loading Loading @@ -1377,6 +1328,44 @@ int libhtmlpp::SvgElement::getType() const{ return ElementType::SvgEL; } size_t libhtmlpp::SvgElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start, bool& termination){ size_t startel=start; while(start<in.size()){ if(in[start]==HTMLTAG_CLOSE) { el=std::make_unique<SvgElement>(); std::vector<char> tel; std::copy(in.begin()+startel,in.begin()+start,std::back_inserter(tel)); static_cast<SvgElement*>(el.get())->_serialelize(tel); break; } ++start; } size_t close=++start; while(start<in.size()){ if( std::equal(in.begin()+start,in.begin()+(start+4),"</svg")) { std::copy(in.begin()+close,in.begin()+start, std::back_inserter(static_cast<SvgElement*>(el.get())->_Svg)); start+=5; break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing </svg closing tag."; } return start; } libhtmlpp::TextArea::TextArea() : HtmlElement("svg"){ } Loading Loading @@ -1411,6 +1400,57 @@ int libhtmlpp::TextArea::getType() const{ return ElementType::TextAreaEL; } size_t libhtmlpp::TextArea::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el,size_t start, bool& termination){ size_t startel = start; while(start < in.size()){ if(in[start] == HTMLTAG_CLOSE) { el = std::make_unique<TextArea>(); std::vector<char> tel; std::copy(in.begin() + startel, in.begin() + start, std::back_inserter(tel)); static_cast<TextArea*>(el.get())->_serialelize(tel); break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Unclosed <svg tag."; } size_t close = ++start; size_t lvl = 0; while(start < in.size()){ if( (start + 9) <= in.size() && std::equal(in.begin()+start,in.begin()+(start+9),"<textarea")){ ++lvl; } if( (start + 10) <= in.size() && std::equal(in.begin()+start,in.begin()+(start+10),"</textarea")) { if(lvl == 0){ std::copy(in.begin() + close, in.begin() + start, std::back_inserter(static_cast<TextArea*>(el.get())->_Text)); start += 10; break; }else{ --lvl; } } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing </textarea closing tag."; } return start; } libhtmlpp::HtmlPage::HtmlPage(){ } Loading Loading @@ -1655,9 +1695,7 @@ void libhtmlpp::print(const Element &element, HtmlString &output,bool formated) } //Container must be always terminated fuck html5 if(isContainer(static_cast<const HtmlElement*>(el)->getTagname()) && !static_cast<const HtmlElement*>(el)->_childElement){ if(isContainer(static_cast<const HtmlElement*>(el)->getTagname())){ output.append("</"); std::copy( static_cast<const HtmlElement*>(el)->_TagName.begin(), Loading src/html.h +11 −1 Original line number Diff line number Diff line Loading @@ -140,6 +140,8 @@ namespace libhtmlpp { int getType() const; void remove(Element* el); static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading @@ -152,6 +154,7 @@ namespace libhtmlpp { std::unique_ptr<Attributes> _nextAttr; }; void _serialelize(std::vector<char> in); private: //if text tagname must be zero std::vector<char> _TagName; Loading Loading @@ -183,6 +186,9 @@ namespace libhtmlpp { void setText(const std::string &txt); int getType() const; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::vector<char> _Text; friend class HtmlString; Loading @@ -206,6 +212,8 @@ namespace libhtmlpp { void setComment(const std::string &txt); int getType() const; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::vector<char> _Comment; friend class HtmlString; Loading Loading @@ -235,6 +243,7 @@ namespace libhtmlpp { void appendChild(const Element* el)=delete; void appendChild(const Element& el)=delete; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading Loading @@ -267,6 +276,7 @@ namespace libhtmlpp { void appendChild(const Element* el)=delete; void appendChild(const Element& el)=delete; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading Loading @@ -300,6 +310,7 @@ namespace libhtmlpp { void appendChild(const Element* el)=delete; void appendChild(const Element& el)=delete; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading Loading @@ -372,7 +383,6 @@ namespace libhtmlpp { private: std::unique_ptr<Element> _rootEl; void _serialelize(std::vector<char> in, HtmlElement* out); void _buildTree(); void _buildtreenode(DocElements *firstel,DocElements *lastel,std::unique_ptr<Element>&html); std::vector<char> _Data; Loading Loading
src/html.cpp +310 −272 Original line number Diff line number Diff line Loading @@ -342,9 +342,10 @@ void libhtmlpp::HtmlString::_buildtreenode( Frame fr = stack.top(); stack.pop(); HtmlElement *opener_el = static_cast<HtmlElement*>(fr.open->element.get()); if (fr.open->nextel) { if (fr.open->nextel->element) { for (DocElements *cnex=fr.open->nextel.get(); cnex; cnex=cnex->nextel.get()) { if (fr.open->nextel->element && !fr.open->nextel->terminator) { opener_el->_childElement = std::move(fr.open->nextel->element); break; } } Loading Loading @@ -414,194 +415,28 @@ void libhtmlpp::HtmlString::_buildTree() { HTMLException excp; for(size_t ii=0; ii<_Data.size(); ++ii){ BUILDTREE_STARTLOOP: if(_Data[ii]==HTMLTAG_OPEN){ if( (ii + 3) < _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+3), "<!--")){ size_t start=ii+3; while(ii<_Data.size()){ if(std::equal(_Data.begin()+ii,_Data.begin()+(ii+3),"-->")) { addelement(&lastEl); lastEl->element=std::make_unique<CommentElement>(); std::copy(_Data.begin()+start,_Data.begin()+ii, std::back_inserter(static_cast<CommentElement*>(lastEl->element.get())->_Comment)); ii+=2; break; } ++ii; } ii+=CommentElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else if((ii+6) < _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+6),"<script")){ size_t start=ii; while(ii<_Data.size()){ if(_Data[ii]==HTMLTAG_CLOSE) { addelement(&lastEl); lastEl->element=std::make_unique<ScriptElement>(); std::vector<char> tel; std::copy(_Data.begin()+start,_Data.begin()+ii,std::back_inserter(tel)); _serialelize(tel,static_cast<ScriptElement*>(lastEl->element.get())); break; } ++ii; } size_t close=++ii; while(ii<_Data.size()){ if( std::equal(_Data.begin()+ii,_Data.begin()+(ii+7),"</script")) { std::copy(_Data.begin()+close,_Data.begin()+ii, std::back_inserter(static_cast<ScriptElement*>(lastEl->element.get())->_Script)); ii+=8; break; } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Missing </script closing tag."; } ii+=ScriptElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else if( (ii+3) < _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+3),"<svg")){ size_t start=ii; while(ii<_Data.size()){ if(_Data[ii]==HTMLTAG_CLOSE) { addelement(&lastEl); lastEl->element=std::make_unique<SvgElement>(); std::vector<char> tel; std::copy(_Data.begin()+start,_Data.begin()+ii,std::back_inserter(tel)); _serialelize(tel,(SvgElement*)lastEl->element.get()); break; } ++ii; } size_t close=++ii; while(ii<_Data.size()){ if( std::equal(_Data.begin()+ii,_Data.begin()+(ii+4),"</svg")) { std::copy(_Data.begin()+close,_Data.begin()+ii, std::back_inserter(static_cast<SvgElement*>(lastEl->element.get())->_Svg)); ii+=5; break; } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Missing </textarea closing tag."; } ii+=SvgElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else if( (ii + 9) <= _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+9),"<textarea")){ size_t start = ii; while(ii < _Data.size()){ if(_Data[ii] == HTMLTAG_CLOSE) { addelement(&lastEl); lastEl->element = std::make_unique<TextArea>(); std::vector<char> tel; std::copy(_Data.begin() + start, _Data.begin() + ii, std::back_inserter(tel)); _serialelize(tel, (TextArea*)lastEl->element.get()); break; } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Unclosed <svg tag."; } size_t close = ++ii; size_t lvl = 0; while(ii < _Data.size()){ if( (ii + 9) <= _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+9),"<textarea")){ ++lvl; } if( (ii + 10) <= _Data.size() && std::equal(_Data.begin()+ii,_Data.begin()+(ii+10),"</textarea")) { if(lvl == 0){ std::copy(_Data.begin() + close, _Data.begin() + ii, std::back_inserter(static_cast<TextArea*>(lastEl->element.get())->_Text)); ii += 10; break; ii+=TextArea::parseElement(_Data,lastEl->element,ii,lastEl->terminator); }else { --lvl; } } ++ii; } if (ii == _Data.size()) { throw excp[HTMLException::Error] << "Parsing error: Missing </textarea closing tag."; } }else { size_t start=ii; addelement(&lastEl); lastEl->element=std::make_unique<HtmlElement>(); bool term=false; while(ii<_Data.size()){ if(!term && _Data[ii]==HTMLTAG_TERMINATE){ lastEl->terminator=true; }else if(_Data[ii]==HTMLTAG_CLOSE) { std::vector<char> tel; std::copy(_Data.begin()+start,_Data.begin()+ii,std::back_inserter(tel)); _serialelize(tel,static_cast<HtmlElement*>(lastEl->element.get())); break; } if(_Data[ii]!=' ' && _Data[ii]!=HTMLTAG_OPEN){ term=true; } ++ii; } ii+=HtmlElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); } }else if(_Data[ii]!=' '){ std::vector<char> buf; bool empty=true; while(ii<_Data.size()){ switch(_Data[ii]){ case HTMLTAG_OPEN: { if(!buf.empty()){ addelement(&lastEl); lastEl->element=std::make_unique<TextElement>(); std::copy(buf.begin(),buf.end(),std::back_inserter((static_cast<TextElement*>(lastEl->element.get()))->_Text)); } goto BUILDTREE_STARTLOOP; }; case '\r':{ ++ii; }break; case '\n':{ ++ii; }break; case ' ':{ if(!empty) buf.push_back(_Data[ii++]); else ++ii; }break; default:{ buf.push_back(_Data[ii++]); empty=false; }break; } ii+=TextElement::parseElement(_Data,lastEl->element,ii,lastEl->terminator); } } } _buildtreenode(firstEl.get(),nullptr,_rootEl); } /** Loading @@ -615,95 +450,6 @@ std::ostream& operator<<(std::ostream& os, const libhtmlpp::HtmlString& p) { os << p.str(); return os; } /** * @brief Extracts tag name and attributes from a token vector into an HtmlElement. * @param in Token buffer containing a single open tag. * @param out Destination HtmlElement to populate. * @throws HTMLException if no tag could be determined. */ void libhtmlpp::HtmlString::_serialelize(std::vector<char> in, libhtmlpp::HtmlElement *out) { size_t st=0,et=0; for (size_t i = 0; i < in.size(); ++i) { switch (in[i]) { case '<': continue; case '/': continue; case ' ': continue; default: st=i; goto GETTAGEND; } } GETTAGEND: for(et=st; et<in.size(); et++){ if(in[et]==' ' || in[et]=='/' || in[et]=='>' || in[et]=='\r' || in[et]=='\n'){ break; } } std::string tag; std::copy(in.begin()+st,in.begin()+et,std::back_inserter(tag)); out->setTagname(tag); if (!out) { HTMLException excp; throw excp[HTMLException::Critical] << "no tag in element found!"; } for(size_t i=et; i<in.size(); i++){ if(in[i]=='>') return; size_t kstart=std::string::npos,kend=std::string::npos; if(in[i]!=' ' && in[i]!='\r' && in[i]!='\n'){ kstart=i; kend=in.size(); bool value=false; size_t vstart=std::string::npos,vend=std::string::npos; while(i<in.size()){ if (in[i]=='='){ value=true; kend=i++; break; } ++i; } if(value){ while(i<in.size()){ if(in[i]=='\"'){ if (vstart==std::string::npos){ vstart=++i; continue; }else{ vend=i; break; } } ++i; } } if(kstart !=std::string::npos){ std::string key,val; std::copy(in.begin()+kstart,in.begin()+kend,std::back_inserter(key)); if(vend!=std::string::npos && vstart!=std::string::npos){ std::copy(in.begin()+vstart,in.begin()+vend,std::back_inserter(val)); } out->setAttribute(key,val); } } } } void libhtmlpp::HtmlEncode(const std::string &input, std::string &output){ size_t ilen=input.length(); Loading Loading @@ -929,6 +675,116 @@ void libhtmlpp::HtmlElement::remove(libhtmlpp::Element* el){ } /** * @brief Extracts tag name and attributes from a token vector into an HtmlElement. * @param in Token buffer containing a single open tag. * @param out Destination HtmlElement to populate. * @throws HTMLException if no tag could be determined. */ void libhtmlpp::HtmlElement::_serialelize(std::vector<char> in) { size_t st=0,et=0; for (size_t i = 0; i < in.size(); ++i) { switch (in[i]) { case '<': continue; case '/': continue; case ' ': continue; default: st=i; goto GETTAGEND; } } GETTAGEND: for(et=st; et<in.size(); et++){ if(in[et]==' ' || in[et]=='/' || in[et]=='>' || in[et]=='\r' || in[et]=='\n'){ break; } } std::string tag; std::copy(in.begin()+st,in.begin()+et,std::back_inserter(tag)); setTagname(tag); if (_TagName.empty()) { HTMLException excp; throw excp[HTMLException::Critical] << "no tag in element found!"; } for(size_t i=et; i<in.size(); i++){ if(in[i]=='>') return; size_t kstart=std::string::npos,kend=std::string::npos; if(in[i]!=' ' && in[i]!='\r' && in[i]!='\n'){ kstart=i; kend=in.size(); bool value=false; size_t vstart=std::string::npos,vend=std::string::npos; while(i<in.size()){ if (in[i]=='='){ value=true; kend=i++; break; } ++i; } if(value){ while(i<in.size()){ if(in[i]=='\"'){ if (vstart==std::string::npos){ vstart=++i; continue; }else{ vend=i; break; } } ++i; } } if(kstart !=std::string::npos){ std::string key,val; std::copy(in.begin()+kstart,in.begin()+kend,std::back_inserter(key)); if(vend!=std::string::npos && vstart!=std::string::npos){ std::copy(in.begin()+vstart,in.begin()+vend,std::back_inserter(val)); } setAttribute(key,val); } } } } size_t libhtmlpp::HtmlElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start,bool &termination){ size_t startel=start; el=std::make_unique<HtmlElement>(); bool term=false; while(start<in.size()){ if(!term && in[start]==HTMLTAG_TERMINATE){ termination=true; }else if(in[start]==HTMLTAG_CLOSE) { std::vector<char> tel; std::copy(in.begin()+startel,in.begin()+start,std::back_inserter(tel)); reinterpret_cast<HtmlElement*>(el.get())->_serialelize(tel); return start; } if(in[start]!=' '){ term=true; } ++start; } return start; } namespace libhtmlpp { Loading Loading @@ -1275,6 +1131,39 @@ int libhtmlpp::TextElement::getType() const{ return ElementType::TextEl; } size_t libhtmlpp::TextElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start,bool &termination){ std::vector<char> buf; bool empty=true,end=false; while(start<in.size() && !end){ switch(in[start]){ case HTMLTAG_OPEN: { if(!buf.empty()){ el=std::make_unique<TextElement>(); std::copy(buf.begin(),buf.end(),std::back_inserter((static_cast<TextElement*>(el.get()))->_Text)); } end=true; break; }; case '\r':{ ++start; }break; case '\n':{ ++start; }break; case ' ':{ if(!empty) buf.push_back(in[start++]); else ++start; }break; default:{ buf.push_back(in[start++]); empty=false; }break; } } return start; } libhtmlpp::CommentElement::CommentElement() : Element(){ } Loading Loading @@ -1310,6 +1199,29 @@ int libhtmlpp::CommentElement::getType() const{ return ElementType::CommentEl; } size_t libhtmlpp::CommentElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start, bool& termination){ size_t startel=start+3; while(start<in.size()){ if(std::equal(in.begin()+start,in.begin()+(start+3),"-->")) { el=std::make_unique<CommentElement>(); std::copy(in.begin()+startel,in.begin()+start, std::back_inserter(static_cast<CommentElement*>(el.get())->_Comment)); start+=2; break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing --> closing tag."; } return start; } libhtmlpp::ScriptElement::ScriptElement() : HtmlElement("script"){ } Loading Loading @@ -1343,6 +1255,45 @@ int libhtmlpp::ScriptElement::getType() const{ return ElementType::ScriptEL; } size_t libhtmlpp::ScriptElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start, bool& termination){ size_t startel=start; while(start<in.size()){ if(in[start]==HTMLTAG_CLOSE) { el=std::make_unique<ScriptElement>(); std::vector<char> tel; std::copy(in.begin()+startel,in.begin()+start,std::back_inserter(tel)); static_cast<ScriptElement*>(el.get())->_serialelize(tel); break; } ++start; } size_t close=++start; while(start<in.size()){ if( std::equal(in.begin()+start,in.begin()+(start+7),"</script")) { std::copy(in.begin()+close,in.begin()+start, std::back_inserter(static_cast<ScriptElement*>(el.get())->_Script)); start+=8; break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing </script closing tag."; } return start; } libhtmlpp::SvgElement::SvgElement() : HtmlElement("svg"){ } Loading Loading @@ -1377,6 +1328,44 @@ int libhtmlpp::SvgElement::getType() const{ return ElementType::SvgEL; } size_t libhtmlpp::SvgElement::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el, size_t start, bool& termination){ size_t startel=start; while(start<in.size()){ if(in[start]==HTMLTAG_CLOSE) { el=std::make_unique<SvgElement>(); std::vector<char> tel; std::copy(in.begin()+startel,in.begin()+start,std::back_inserter(tel)); static_cast<SvgElement*>(el.get())->_serialelize(tel); break; } ++start; } size_t close=++start; while(start<in.size()){ if( std::equal(in.begin()+start,in.begin()+(start+4),"</svg")) { std::copy(in.begin()+close,in.begin()+start, std::back_inserter(static_cast<SvgElement*>(el.get())->_Svg)); start+=5; break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing </svg closing tag."; } return start; } libhtmlpp::TextArea::TextArea() : HtmlElement("svg"){ } Loading Loading @@ -1411,6 +1400,57 @@ int libhtmlpp::TextArea::getType() const{ return ElementType::TextAreaEL; } size_t libhtmlpp::TextArea::parseElement(const std::vector<char> in, std::unique_ptr<libhtmlpp::Element>& el,size_t start, bool& termination){ size_t startel = start; while(start < in.size()){ if(in[start] == HTMLTAG_CLOSE) { el = std::make_unique<TextArea>(); std::vector<char> tel; std::copy(in.begin() + startel, in.begin() + start, std::back_inserter(tel)); static_cast<TextArea*>(el.get())->_serialelize(tel); break; } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Unclosed <svg tag."; } size_t close = ++start; size_t lvl = 0; while(start < in.size()){ if( (start + 9) <= in.size() && std::equal(in.begin()+start,in.begin()+(start+9),"<textarea")){ ++lvl; } if( (start + 10) <= in.size() && std::equal(in.begin()+start,in.begin()+(start+10),"</textarea")) { if(lvl == 0){ std::copy(in.begin() + close, in.begin() + start, std::back_inserter(static_cast<TextArea*>(el.get())->_Text)); start += 10; break; }else{ --lvl; } } ++start; } if (start == in.size()) { HTMLException excp; throw excp[HTMLException::Error] << "Parsing error: Missing </textarea closing tag."; } return start; } libhtmlpp::HtmlPage::HtmlPage(){ } Loading Loading @@ -1655,9 +1695,7 @@ void libhtmlpp::print(const Element &element, HtmlString &output,bool formated) } //Container must be always terminated fuck html5 if(isContainer(static_cast<const HtmlElement*>(el)->getTagname()) && !static_cast<const HtmlElement*>(el)->_childElement){ if(isContainer(static_cast<const HtmlElement*>(el)->getTagname())){ output.append("</"); std::copy( static_cast<const HtmlElement*>(el)->_TagName.begin(), Loading
src/html.h +11 −1 Original line number Diff line number Diff line Loading @@ -140,6 +140,8 @@ namespace libhtmlpp { int getType() const; void remove(Element* el); static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading @@ -152,6 +154,7 @@ namespace libhtmlpp { std::unique_ptr<Attributes> _nextAttr; }; void _serialelize(std::vector<char> in); private: //if text tagname must be zero std::vector<char> _TagName; Loading Loading @@ -183,6 +186,9 @@ namespace libhtmlpp { void setText(const std::string &txt); int getType() const; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::vector<char> _Text; friend class HtmlString; Loading @@ -206,6 +212,8 @@ namespace libhtmlpp { void setComment(const std::string &txt); int getType() const; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::vector<char> _Comment; friend class HtmlString; Loading Loading @@ -235,6 +243,7 @@ namespace libhtmlpp { void appendChild(const Element* el)=delete; void appendChild(const Element& el)=delete; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading Loading @@ -267,6 +276,7 @@ namespace libhtmlpp { void appendChild(const Element* el)=delete; void appendChild(const Element& el)=delete; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading Loading @@ -300,6 +310,7 @@ namespace libhtmlpp { void appendChild(const Element* el)=delete; void appendChild(const Element& el)=delete; static size_t parseElement(const std::vector<char> in,std::unique_ptr<libhtmlpp::Element> &el,size_t start,bool &termination); protected: std::unique_ptr<Element> _childElement=nullptr; Loading Loading @@ -372,7 +383,6 @@ namespace libhtmlpp { private: std::unique_ptr<Element> _rootEl; void _serialelize(std::vector<char> in, HtmlElement* out); void _buildTree(); void _buildtreenode(DocElements *firstel,DocElements *lastel,std::unique_ptr<Element>&html); std::vector<char> _Data; Loading