#include #include #include "encoder_impl.hpp" namespace quickbook { template std::string encode_impl(Iter first, Iter last) { std::string r; for(;first != last; ++first) { switch (*first) { case '<': r += "<"; break; case '>': r += ">"; break; case '&': r += "&"; break; case '"': r += """; break; default: r += *first; break; } } return r; } std::string boostbook_encoder::encode(raw_string const& x) { return encode_impl(x.begin(), x.end()); } std::string boostbook_encoder::encode(std::string const& x) { return encode_impl(x.begin(), x.end()); } std::string boostbook_encoder::encode(char const* x) { char const* end = x; while(*end) ++end; return encode_impl(x, end); } std::string boostbook_encoder::encode(char c) { return encode_impl(&c, &c + 1); } namespace { struct boostbook_markup { char const* quickbook; char const* pre; char const* post; }; boostbook_markup markups[] = { { "", "", "" }, { "comment", "" }, { "paragraph", "\n", "\n" }, { "h1", "", "" }, { "h2", "", "" }, { "h3", "", "" }, { "h4", "", "" }, { "h5", "", "" }, { "h6", "", "" }, { "blurb", "\n", "\n" }, { "blockquote", "
", "
" }, { "preformatted", "", "" }, { "warning", "", "" }, { "caution", "", "" }, { "important", "", "" }, { "note", "", "" }, { "tip", "", "" }, { "list_item", "\n", "\n" }, { "bold", "", "" }, { "italic", "", "" }, { "underline", "", "" }, { "teletype", "", "" }, { "strikethrough", "", "" }, { "quote", "", "" }, { "url", "" }, { "link", "" }, { "funcref", "" }, { "classref", "" }, { "memberref", "" }, { "enumref", "" }, { "macroref", "" }, { "headerref", "" }, { "conceptref", "" }, { "globalref", "" }, { "footnote", "", "" }, { "escape", "", "" }, { "replaceable", "", "" }, { "varlistentry", "", "\n" }, { "varlistterm", "", "" }, { "varlistitem", "", "" }, { "header", "", "\n" }, { "row", "", "\n" }, { "cell", "", "" }, { "programlisting", "", "\n" }, { "code", "", "" }, { "hr", "", "" }, { "break", "", "" }, }; std::map markup_map; struct initialize { initialize() { BOOST_FOREACH(boostbook_markup m, markups) { markup_map[m.quickbook] = m; } } } initialize_instance; boostbook_markup get_markup(std::string const& x) { std::map::const_iterator pos = markup_map.find(x); BOOST_ASSERT(pos != markup_map.end()); return pos->second; } } void boostbook_encoder::operator()(quickbook::state& state, std::string const& x) { state.phrase << x; } void boostbook_encoder::operator()(quickbook::state& state, char x) { state.phrase << encode(x); } void boostbook_encoder::operator()(quickbook::state& state, unicode_char const& x) { std::string::const_iterator first = x.value.begin(), last = x.value.end(); while(first != last && *first == '0') ++first; // Just ignore \u0000 // Maybe I should issue a warning? if(first == last) return; std::string hex_digits(first, last); if(hex_digits.size() == 2 && *first > '0' && *first <= '7') { using namespace std; (*this)(state, strtol(hex_digits.c_str(), 0, 16)); } else { state.phrase << "&#x" << hex_digits << ";"; } } void boostbook_encoder::operator()(quickbook::state& state, anchor const& x) { state.phrase << "\n"; } void boostbook_encoder::operator()(quickbook::state& state, link const& x) { boostbook_markup m = get_markup(x.type); state.phrase << m.pre; state.phrase << encode(x.destination); state.phrase << "\">"; state.phrase << x.content; state.phrase << m.post; } void boostbook_encoder::operator()(quickbook::state& state, formatted const& x) { boostbook_markup m = get_markup(x.type); state.phrase << m.pre << x.content << m.post; } void boostbook_encoder::operator()(quickbook::state& state, break_ const& x) { boostbook_markup m = get_markup("break"); state.phrase << m.pre; } void boostbook_encoder::operator()(quickbook::state& state, image2 const& x) { state.phrase << ""; state.phrase << "first == "alt") continue; state.phrase << " " << attr_first->first << "=\"" << encode(attr_first->second) << "\""; } state.phrase << ">"; image2::attribute_map::const_iterator it = x.attributes.find("alt"); if(it != x.attributes.end()) { // Also add a textobject -- use the basename of the image file. // This will mean we get "alt" attributes of the HTML img. state.phrase << ""; state.phrase << encode(it->second); state.phrase << ""; } state.phrase << ""; } void boostbook_encoder::operator()(quickbook::state& state, hr) { state.phrase << get_markup("hr").pre; } void boostbook_encoder::operator()(quickbook::state& state, begin_section2 const& x) { state.phrase << "\n
\n"; if(x.linkend.empty()) { state.phrase << "" << x.content << "\n" ; } else { state.phrase << "" << "<link linkend=\"" << encode(x.linkend) << "\">" << x.content << "</link>" << "\n" ; } } void boostbook_encoder::operator()(quickbook::state& state, end_section2 const& x) { state.phrase << "
"; } void boostbook_encoder::operator()(quickbook::state& state, heading2 const& x) { state.phrase << "" << ""; if(x.linkend.empty()) { state.phrase << x.content; } else { state.phrase << "" << x.content << ""; } state.phrase << ""; } void boostbook_encoder::operator()(quickbook::state& state, variablelist const& x) { state.phrase << "\n"; state.phrase << ""; state.phrase << encode(x.title); state.phrase << "\n"; boostbook_markup m = get_markup("varlistentry"); for(std::vector::const_iterator it = x.entries.begin(); it != x.entries.end(); ++it) { state.phrase << m.pre; std::for_each(it->begin(), it->end(), encode_action(state, *this)); state.phrase << m.post; } state.phrase << "\n"; } void boostbook_encoder::operator()(quickbook::state& state, table2 const& x) { if (x.title) { state.phrase << "\n"; state.phrase << ""; state.phrase << encode(*x.title); state.phrase << ""; } else { state.phrase << "\n"; } // This is a bit odd for backwards compatability: the old version just // used the last count that was calculated. state.phrase << "\n"; boostbook_markup m = get_markup("row"); if (x.head) { state.phrase << ""; state.phrase << m.pre; std::for_each(x.head->begin(), x.head->end(), encode_action(state, *this)); state.phrase << m.post; state.phrase << "\n"; } state.phrase << "\n"; for(std::vector::const_iterator it = x.rows.begin(); it != x.rows.end(); ++it) { state.phrase << m.pre; std::for_each(it->begin(), it->end(), encode_action(state, *this)); state.phrase << m.post; } state.phrase << "\n" << "\n"; if (x.title) { state.phrase << "
\n"; } else { state.phrase << "\n"; } } void boostbook_encoder::operator()(quickbook::state& state, xinclude2 const& x) { state.phrase << "\n\n"; } void boostbook_encoder::operator()(quickbook::state& state, list2 const& x) { state.phrase << std::string(x.mark == '#' ? "\n" : "\n"); for(std::vector::const_iterator it = x.items.begin(), end = x.items.end(); it != end; ++it) { state.phrase << "\n" << it->content; if(!it->sublist.items.empty()) (*this)(state, it->sublist); state.phrase << std::string("\n"); } state.phrase << std::string(x.mark == '#' ? "\n" : "\n"); } void boostbook_encoder::operator()(quickbook::state& state, callout_link const& x) { state.phrase << "" ; } void boostbook_encoder::operator()(quickbook::state& state, callout_list const& x) { state.phrase << ""; BOOST_FOREACH(callout_item const& c, x) { state.phrase << "" << c.content << ""; } state.phrase << ""; } void boostbook_encoder::operator()(quickbook::state& state, code_token const& x) { std::string type = x.type; if(type == "space") { state.phrase << x.text; } else { state.phrase << "" << encode(x.text) << ""; } } void boostbook_encoder::operator()(quickbook::state& state, doc_info const& info) { // if we're ignoring the document info, we're done. if (info.ignore) return; state.phrase << "\n" << ""; // Document tag state.phrase << '<' << info.doc_type << " id=\"" << encode(info.doc_id) << "\"\n"; if(info.doc_type == "library") { state.phrase << " name=\"" << encode(info.doc_title) << "\"\n"; } if(!info.doc_dirname.empty()) { state.phrase << " dirname=\"" << encode(info.doc_dirname) << "\"\n"; } state.phrase << "last-revision=\"" << encode(info.doc_last_revision) << "\"" << " xmlns:xi=\"http://www.w3.org/2001/XInclude\""; state.phrase << ">"; // end document tag. // Title tag std::string title; if(info.doc_title.begin() != info.doc_title.end()) { title = "" + encode(info.doc_title); if (!info.doc_version.empty()) title += ' ' + info.doc_version.value; title += "\n"; } // For 'library', the title comes after the info block. if(info.doc_type != "library") state.phrase << title; // Info tag state.phrase << "<" << info.doc_type << "info>\n"; if(!info.doc_authors.empty()) { state.phrase << "\n"; BOOST_FOREACH(doc_info::author const& author, info.doc_authors) { state.phrase << "\n" << "" << author.first << "\n" << "" << author.second << "\n" << "\n"; } state.phrase << "\n"; } BOOST_FOREACH(doc_info::copyright_entry const& copyright, info.doc_copyrights) { state.phrase << "\n"; BOOST_FOREACH(unsigned int year, copyright.first) { state.phrase << "" << year << "\n"; } state.phrase << "" << copyright.second << "\n" << "\n" ; } if (!boost::apply_visitor(empty_visitor(), info.doc_license)) { state.phrase << "\n" << "\n" << boost::apply_visitor(encode_raw_visitor(*this), info.doc_license) << "\n" << "\n" << "\n" << "\n" ; } if (!boost::apply_visitor(empty_visitor(), info.doc_purpose)) { state.phrase << "<" << info.doc_type << "purpose>\n" << boost::apply_visitor(encode_raw_visitor(*this), info.doc_purpose) << "\n" << "\n" ; } BOOST_FOREACH(raw_string const& category, info.doc_categories) { state.phrase << "<" << info.doc_type << "category name=\"category:" << encode(category) << "\">\n" << "\n" ; } state.phrase << "\n" ; if(info.doc_type == "library") state.phrase << title; } void boostbook_encoder::operator()(quickbook::state& state, doc_info_post const& x) { // if we're ignoring the document info, do nothing. if (x.info.ignore) return; // We've finished generating our output. Here's what we'll do // *after* everything else. state.phrase << ""; } }