X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fxml.cpp;h=e16a7840b6db099e1a8048da629bad979bff6b1c;hb=2dae4ab4f35458f3caa4f85f8c0e64e5fe9065d1;hp=16173d0949398d573002f0b84a47ce02fc8544fb;hpb=8dd2e7e6816a714b2c19eb7466dcb80fa582a0e4;p=features.git diff --git a/src/xml.cpp b/src/xml.cpp index 16173d0949..e16a7840b6 100644 --- a/src/xml.cpp +++ b/src/xml.cpp @@ -44,43 +44,50 @@ docstring escapeChar(char_type c, XMLStream::EscapeSettings e) { docstring str; switch (e) { // For HTML: always ESCAPE_NONE. For XML: it depends, hence the parameter. - case XMLStream::ESCAPE_NONE: - str += c; + case XMLStream::ESCAPE_NONE: + case XMLStream::ESCAPE_COMMENTS: + str += c; + break; + case XMLStream::ESCAPE_ALL: + if (c == '<') { + str += "<"; break; - case XMLStream::ESCAPE_ALL: - if (c == '<') { - str += "<"; - break; - } else if (c == '>') { - str += ">"; - break; - } - // fall through - case XMLStream::ESCAPE_AND: - if (c == '&') - str += "&"; - else - str +=c ; + } else if (c == '>') { + str += ">"; break; + } + // fall through + case XMLStream::ESCAPE_AND: + if (c == '&') + str += "&"; + else + str +=c ; + break; } return str; } -// escape what needs escaping -docstring xmlize(docstring const &str, XMLStream::EscapeSettings e) { - odocstringstream d; - docstring::const_iterator it = str.begin(); - docstring::const_iterator en = str.end(); - for (; it != en; ++it) - d << escapeChar(*it, e); - return d.str(); +docstring escapeChar(char c, XMLStream::EscapeSettings e) +{ + LATTEST(static_cast(c) < 0x80); + return escapeChar(static_cast(c), e); } -docstring escapeChar(char c, XMLStream::EscapeSettings e) { - LATTEST(static_cast(c) < 0x80); - return escapeChar(static_cast(c), e); +docstring escapeString(docstring const & raw, XMLStream::EscapeSettings e) +{ + docstring bin; + bin.reserve(raw.size() * 2); // crude approximation is sufficient + for (size_t i = 0; i != raw.size(); ++i) { + char_type c = raw[i]; + if (e == XMLStream::ESCAPE_COMMENTS && c == '-' && i > 0 && raw[i - 1] == '-') + bin += "-"; + else + bin += xml::escapeChar(c, e); + } + + return bin; } @@ -97,10 +104,11 @@ docstring cleanAttr(docstring const & str) } -docstring StartTag::writeTag() const { +docstring StartTag::writeTag() const +{ docstring output = '<' + tag_; if (!attr_.empty()) { - docstring attributes = xml::xmlize(attr_, XMLStream::ESCAPE_NONE); + docstring attributes = xml::escapeString(attr_, XMLStream::ESCAPE_NONE); attributes.erase(attributes.begin(), std::find_if(attributes.begin(), attributes.end(), [](int c) {return !std::isspace(c);})); if (!attributes.empty()) { @@ -112,27 +120,31 @@ docstring StartTag::writeTag() const { } -docstring StartTag::writeEndTag() const { +docstring StartTag::writeEndTag() const +{ return from_utf8(""); } -bool StartTag::operator==(FontTag const &rhs) const { +bool StartTag::operator==(FontTag const &rhs) const +{ return rhs == *this; } -docstring EndTag::writeEndTag() const { +docstring EndTag::writeEndTag() const +{ return from_utf8(""); } -docstring CompTag::writeTag() const { +docstring CompTag::writeTag() const +{ docstring output = '<' + from_utf8(tag_); if (!attr_.empty()) { // Erase the beginning of the attributes if it contains space characters: this function deals with that // automatically. - docstring attributes = xmlize(from_utf8(attr_), XMLStream::ESCAPE_NONE); + docstring attributes = escapeString(from_utf8(attr_), XMLStream::ESCAPE_NONE); attributes.erase(attributes.begin(), std::find_if(attributes.begin(), attributes.end(), [](int c) {return !std::isspace(c);})); if (!attributes.empty()) { @@ -155,19 +167,22 @@ bool FontTag::operator==(StartTag const & tag) const } // namespace xml -void XMLStream::writeError(std::string const &s) const { +void XMLStream::writeError(std::string const &s) const +{ LYXERR0(s); os_ << from_utf8("\n"); } -void XMLStream::writeError(docstring const &s) const { +void XMLStream::writeError(docstring const &s) const +{ LYXERR0(s); os_ << from_utf8("\n"); } -bool XMLStream::closeFontTags() { +bool XMLStream::closeFontTags() +{ if (isTagPending(xml::parsep_tag)) // we haven't had any content return true; @@ -208,14 +223,16 @@ bool XMLStream::closeFontTags() { } -void XMLStream::startDivision(bool keep_empty) { +void XMLStream::startDivision(bool keep_empty) +{ pending_tags_.push_back(makeTagPtr(xml::StartTag(xml::parsep_tag))); if (keep_empty) clearTagDeque(); } -void XMLStream::endDivision() { +void XMLStream::endDivision() +{ if (isTagPending(xml::parsep_tag)) { // this case is normal. it just means we didn't have content, // so the parsep_tag never got moved onto the tag stack. @@ -258,7 +275,8 @@ void XMLStream::endDivision() { } -void XMLStream::clearTagDeque() { +void XMLStream::clearTagDeque() +{ while (!pending_tags_.empty()) { TagPtr const & tag = pending_tags_.front(); if (*tag != xml::parsep_tag) @@ -270,24 +288,27 @@ void XMLStream::clearTagDeque() { } -XMLStream &XMLStream::operator<<(docstring const &d) { +XMLStream &XMLStream::operator<<(docstring const &d) +{ clearTagDeque(); - os_ << xml::xmlize(d, escape_); + os_ << xml::escapeString(d, escape_); escape_ = ESCAPE_ALL; return *this; } -XMLStream &XMLStream::operator<<(const char *s) { +XMLStream &XMLStream::operator<<(const char *s) +{ clearTagDeque(); docstring const d = from_ascii(s); - os_ << xml::xmlize(d, escape_); + os_ << xml::escapeString(d, escape_); escape_ = ESCAPE_ALL; return *this; } -XMLStream &XMLStream::operator<<(char_type c) { +XMLStream &XMLStream::operator<<(char_type c) +{ clearTagDeque(); os_ << xml::escapeChar(c, escape_); escape_ = ESCAPE_ALL; @@ -295,7 +316,8 @@ XMLStream &XMLStream::operator<<(char_type c) { } -XMLStream &XMLStream::operator<<(char c) { +XMLStream &XMLStream::operator<<(char c) +{ clearTagDeque(); os_ << xml::escapeChar(c, escape_); escape_ = ESCAPE_ALL; @@ -303,7 +325,8 @@ XMLStream &XMLStream::operator<<(char c) { } -XMLStream &XMLStream::operator<<(int i) { +XMLStream &XMLStream::operator<<(int i) +{ clearTagDeque(); os_ << i; escape_ = ESCAPE_ALL; @@ -311,13 +334,15 @@ XMLStream &XMLStream::operator<<(int i) { } -XMLStream &XMLStream::operator<<(EscapeSettings e) { +XMLStream &XMLStream::operator<<(EscapeSettings e) +{ escape_ = e; return *this; } -XMLStream &XMLStream::operator<<(xml::StartTag const &tag) { +XMLStream &XMLStream::operator<<(xml::StartTag const &tag) +{ if (tag.tag_.empty()) return *this; pending_tags_.push_back(makeTagPtr(tag)); @@ -327,7 +352,8 @@ XMLStream &XMLStream::operator<<(xml::StartTag const &tag) { } -XMLStream &XMLStream::operator<<(xml::ParTag const &tag) { +XMLStream &XMLStream::operator<<(xml::ParTag const &tag) +{ if (tag.tag_.empty()) return *this; pending_tags_.push_back(makeTagPtr(tag)); @@ -335,7 +361,8 @@ XMLStream &XMLStream::operator<<(xml::ParTag const &tag) { } -XMLStream &XMLStream::operator<<(xml::CompTag const &tag) { +XMLStream &XMLStream::operator<<(xml::CompTag const &tag) +{ if (tag.tag_.empty()) return *this; clearTagDeque(); @@ -344,7 +371,8 @@ XMLStream &XMLStream::operator<<(xml::CompTag const &tag) { } -XMLStream &XMLStream::operator<<(xml::FontTag const &tag) { +XMLStream &XMLStream::operator<<(xml::FontTag const &tag) +{ if (tag.tag_.empty()) return *this; pending_tags_.push_back(makeTagPtr(tag)); @@ -352,14 +380,16 @@ XMLStream &XMLStream::operator<<(xml::FontTag const &tag) { } -XMLStream &XMLStream::operator<<(xml::CR const &) { +XMLStream &XMLStream::operator<<(xml::CR const &) +{ clearTagDeque(); os_ << from_ascii("\n"); return *this; } -bool XMLStream::isTagOpen(xml::StartTag const &stag, int maxdepth) const { +bool XMLStream::isTagOpen(xml::StartTag const &stag, int maxdepth) const +{ auto sit = tag_stack_.begin(); auto sen = tag_stack_.cend(); for (; sit != sen && maxdepth != 0; ++sit) { @@ -371,7 +401,8 @@ bool XMLStream::isTagOpen(xml::StartTag const &stag, int maxdepth) const { } -bool XMLStream::isTagOpen(xml::EndTag const &etag, int maxdepth) const { +bool XMLStream::isTagOpen(xml::EndTag const &etag, int maxdepth) const +{ auto sit = tag_stack_.begin(); auto sen = tag_stack_.cend(); for (; sit != sen && maxdepth != 0; ++sit) { @@ -383,7 +414,8 @@ bool XMLStream::isTagOpen(xml::EndTag const &etag, int maxdepth) const { } -bool XMLStream::isTagPending(xml::StartTag const &stag, int maxdepth) const { +bool XMLStream::isTagPending(xml::StartTag const &stag, int maxdepth) const +{ auto sit = pending_tags_.begin(); auto sen = pending_tags_.cend(); for (; sit != sen && maxdepth != 0; ++sit) { @@ -400,7 +432,8 @@ bool XMLStream::isTagPending(xml::StartTag const &stag, int maxdepth) const { // sure of that, but we won't assert (yet) if we run into // a problem. we'll just output error messages and try our // best to make things work. -XMLStream &XMLStream::operator<<(xml::EndTag const &etag) { +XMLStream &XMLStream::operator<<(xml::EndTag const &etag) +{ if (etag.tag_.empty()) return *this; @@ -443,7 +476,7 @@ XMLStream &XMLStream::operator<<(xml::EndTag const &etag) { string estr = "Closing tag `" + to_utf8(etag.tag_) + "' when other tags are pending. Discarded pending tags:\n"; for (dit = pending_tags_.begin(); dit != den; ++dit) - estr += to_utf8(xml::xmlize((*dit)->writeTag(), XMLStream::ESCAPE_ALL)) + "\n"; + estr += to_utf8(xml::escapeString((*dit)->writeTag(), XMLStream::ESCAPE_ALL)) + "\n"; writeError(estr); // clear the pending tags... pending_tags_.clear(); @@ -540,18 +573,7 @@ XMLStream &XMLStream::operator<<(xml::EndTag const &etag) { } -docstring xml::escapeString(docstring const & raw, XMLStream::EscapeSettings e) -{ - docstring bin; - bin.reserve(raw.size() * 2); // crude approximation is sufficient - for (size_t i = 0; i != raw.size(); ++i) - bin += xml::escapeChar(raw[i], e); - - return bin; -} - - -docstring const xml::uniqueID(docstring const & label) +docstring xml::uniqueID(docstring const & label) { // thread-safe static atomic_uint seed(1000);