aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/xhtml-fragment.cxx49
-rw-r--r--web/xhtml-fragment.hxx19
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;