diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/xhtml-fragment.cxx | 49 | ||||
-rw-r--r-- | web/xhtml-fragment.hxx | 19 |
2 files changed, 51 insertions, 17 deletions
diff --git a/web/xhtml-fragment.cxx b/web/xhtml-fragment.cxx index 4d1c178..fe8a0a7 100644 --- a/web/xhtml-fragment.cxx +++ b/web/xhtml-fragment.cxx @@ -20,25 +20,38 @@ namespace web namespace xhtml { fragment:: - fragment (const string& text, const string& name) + fragment (const string& text, const string& name, size_t length) { // To parse the fragment make it a valid xml document, wrapping with the - // root element. + // root element. If requested, truncate the fragment before the + // first-level element when the content length limit is exceeded. // string doc ("<d>" + text + "</d>"); - parser p ( - doc.c_str (), - doc.size (), - name, - parser::receive_elements | parser::receive_characters | - parser::receive_attributes_event); + parser p (doc.c_str (), + doc.size (), + name, + parser::receive_elements | + parser::receive_characters | + parser::receive_attributes_event); + + size_t len (0); + size_t level (0); for (parser::event_type e: p) { switch (e) { case parser::start_element: + { + truncated = length != 0 && level == 1 && len >= length; + + if (truncated) + break; + + ++level; + } + // Fall through. case parser::start_attribute: { const auto& n (p.qname ()); @@ -51,6 +64,10 @@ namespace web break; } case parser::end_element: + { + --level; + } + // Fall through. case parser::end_attribute: { events_.emplace_back (e, ""); @@ -58,12 +75,25 @@ namespace web } case parser::characters: { - events_.emplace_back (e, p.value ()); + string& s (p.value ()); + + assert (!events_.empty ()); // Contains root element start. + + if (events_.back ().first != parser::start_attribute) + len += s.size (); + + events_.emplace_back (e, move (s)); break; } default: assert (false); } + + if (truncated) + { + events_.emplace_back (parser::end_element, ""); // Close root. + break; + } } // Unwrap the fragment removing the root element events. @@ -85,7 +115,6 @@ namespace web s.start_element (xmlns, e.second); break; } - case parser::start_attribute: { s.start_attribute (e.second); diff --git a/web/xhtml-fragment.hxx b/web/xhtml-fragment.hxx index 14b9a21..fd41967 100644 --- a/web/xhtml-fragment.hxx +++ b/web/xhtml-fragment.hxx @@ -22,16 +22,21 @@ namespace web class fragment { public: + bool truncated = false; + + public: fragment () = default; - // Parse string as XHTML document fragment. The fragment should be - // complete, in the sense that all elements should have closing tags. - // Elements and attributes are considered to be in the namespace of the - // entire XHTML document, so no namespace should be specified for them. - // Do not validate against XHTML vocabulary. Can throw xml::parsing - // exception. + // Parse string as an XHTML document fragment, truncating it if + // requested. The fragment should be complete, in the sense that all + // elements should have closing tags. Elements and attributes are + // considered to be in the namespace of the entire XHTML document, so no + // namespace should be specified for them. Do not validate against XHTML + // vocabulary. Can throw xml::parsing exception. // - fragment (const std::string& xhtml, const std::string& input_name); + fragment (const std::string& xhtml, + const std::string& input_name, + size_t length = 0); void operator() (xml::serializer&) const; |