unsigned get_version(quickbook::state& state, bool using_docinfo, value version) { unsigned result = 0; if (!version.empty()) { value_consumer version_values(version); bool before_docinfo = version_values.optional_consume( doc_info_tags::before_docinfo).check(); int major_verison = version_values.consume().get_int(); int minor_verison = version_values.consume().get_int(); version_values.finish(); if (before_docinfo || using_docinfo) { result = ((unsigned) major_verison * 100) + (unsigned) minor_verison; if(result < 100 || result > 107) { detail::outerr(state.current_file->path) << "Unknown version: " << major_verison << "." << minor_verison << std::endl; ++state.error_count; } } } return result; }
void traverse(const value& tree, const std::function<void (const path&, const value&)>& func, const path& base_path, bool leafs_only ) { if (!leafs_only || tree.empty() || (tree.kind() != kind::array && tree.kind() != kind::object)) func(base_path, tree); if (tree.kind() == kind::object) { for (const auto& field : tree.as_object()) { traverse(field.second, func, base_path + field.first, leafs_only ); } } else if (tree.kind() == kind::array) { for (value::size_type idx = 0; idx < tree.size(); ++idx) traverse(tree[idx], func, base_path + idx, leafs_only ); } }
bool dtree::num_equal::test(const value& val) const { if(val.empty()) return (as_number==0); else { if(val.is<std::string>()) return (val.as<std::string>()==as_string); else return (val.as<unsigned int>()==as_number); } }
std::string pre(quickbook::state& state, parse_iterator pos, value include_doc_id, bool nested_file) { // The doc_info in the file has been parsed. Here's what we'll do // *before* anything else. // // If there isn't a doc info block, then values will be empty, so most // of the following code won't actually do anything. value_consumer values = state.values.release(); // Skip over invalid attributes while (values.check(value::default_tag)) values.consume(); bool use_doc_info = false; std::string doc_type; value doc_title; if (values.check(doc_info_tags::type)) { doc_type = detail::to_s(values.consume(doc_info_tags::type).get_quickbook()); doc_title = values.consume(doc_info_tags::title); use_doc_info = !nested_file || qbk_version_n >= 106u; } else { if (!nested_file) { detail::outerr(state.current_file, pos.base()) << "No doc_info block." << std::endl; ++state.error_count; // Create a fake document info block in order to continue. doc_type = "article"; doc_title = qbk_value(state.current_file, pos.base(), pos.base(), doc_info_tags::type); use_doc_info = true; } } std::vector<std::string> duplicates; std::vector<value> escaped_attributes = consume_multiple_values(values, doc_info_tags::escaped_attribute); value qbk_version = consume_list(values, doc_attributes::qbk_version, &duplicates); value compatibility_mode = consume_list(values, doc_attributes::compatibility_mode, &duplicates); consume_multiple_values(values, doc_attributes::source_mode); value id = consume_value_in_list(values, doc_info_attributes::id, &duplicates); value dirname = consume_value_in_list(values, doc_info_attributes::dirname, &duplicates); value last_revision = consume_value_in_list(values, doc_info_attributes::last_revision, &duplicates); value purpose = consume_value_in_list(values, doc_info_attributes::purpose, &duplicates); std::vector<value> categories = consume_multiple_values(values, doc_info_attributes::category); value lang = consume_value_in_list(values, doc_info_attributes::lang, &duplicates); value version = consume_value_in_list(values, doc_info_attributes::version, &duplicates); std::vector<value> authors = consume_multiple_values(values, doc_info_attributes::authors); std::vector<value> copyrights = consume_multiple_values(values, doc_info_attributes::copyright); value license = consume_value_in_list(values, doc_info_attributes::license, &duplicates); std::vector<value> biblioids = consume_multiple_values(values, doc_info_attributes::biblioid); value xmlbase = consume_value_in_list(values, doc_info_attributes::xmlbase, &duplicates); values.finish(); if(!duplicates.empty()) { detail::outwarn(state.current_file->path) << (duplicates.size() > 1 ? "Duplicate attributes" : "Duplicate attribute") << ":" << boost::algorithm::join(duplicates, ", ") << "\n" ; } std::string include_doc_id_, id_; if (!include_doc_id.empty()) include_doc_id_ = detail::to_s(include_doc_id.get_quickbook()); if (!id.empty()) id_ = detail::to_s(id.get_quickbook()); // Quickbook version unsigned new_version = get_version(state, use_doc_info, qbk_version); if (new_version != qbk_version_n) { if (new_version >= 107u) { detail::outwarn(state.current_file->path) << "Quickbook " << (new_version / 100) << "." << (new_version % 100) << " is still under development and is " "likely to change in the future." << std::endl; } } if (new_version) { qbk_version_n = new_version; } else if (use_doc_info) { // hard code quickbook version to v1.1 qbk_version_n = 101; detail::outwarn(state.current_file, pos.base()) << "Quickbook version undefined. " "Version 1.1 is assumed" << std::endl; } state.current_file->version(qbk_version_n); // Compatibility Version unsigned compatibility_version = get_version(state, use_doc_info, compatibility_mode); if (!compatibility_version) { compatibility_version = use_doc_info ? qbk_version_n : state.document.compatibility_version(); } // Start file, finish here if not generating document info. if (!use_doc_info) { state.document.start_file(compatibility_version, include_doc_id_, id_, doc_title); return ""; } std::string id_placeholder = state.document.start_file_with_docinfo( compatibility_version, include_doc_id_, id_, doc_title); // Make sure we really did have a document info block. assert(doc_title.check() && !doc_type.empty()); // Set xmlbase std::string xmlbase_value; if (!xmlbase.empty()) { xinclude_path x = calculate_xinclude_path(xmlbase, state); if (!fs::is_directory(x.path)) { detail::outerr(xmlbase.get_file(), xmlbase.get_position()) << "xmlbase \"" << xmlbase.get_quickbook() << "\" isn't a directory." << std::endl; ++state.error_count; } else { xmlbase_value = x.uri; state.xinclude_base = x.path; } } // Warn about invalid fields if (doc_type != "library") { std::vector<std::string> invalid_attributes; if (!purpose.empty()) invalid_attributes.push_back("purpose"); if (!categories.empty()) invalid_attributes.push_back("category"); if (!dirname.empty()) invalid_attributes.push_back("dirname"); if(!invalid_attributes.empty()) { detail::outwarn(state.current_file->path) << (invalid_attributes.size() > 1 ? "Invalid attributes" : "Invalid attribute") << " for '" << doc_type << " document info': " << boost::algorithm::join(invalid_attributes, ", ") << "\n" ; } } // Write out header if (!nested_file) { state.out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" << "<!DOCTYPE " << doc_type << " PUBLIC \"-//Boost//DTD BoostBook XML V1.0//EN\"\n" << " \"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd\">\n" ; } state.out << '<' << doc_type << "\n" << " id=\"" << id_placeholder << "\"\n"; if(!lang.empty()) { state.out << " lang=\"" << doc_info_output(lang, 106) << "\"\n"; } if(doc_type == "library" && !doc_title.empty()) { state.out << " name=\"" << doc_info_output(doc_title, 106) << "\"\n"; } // Set defaults for dirname + last_revision if (!dirname.empty() || doc_type == "library") { state.out << " dirname=\""; if (!dirname.empty()) { state.out << doc_info_output(dirname, 106); } else if (!id_.empty()) { state.out << id_; } else if (!include_doc_id_.empty()) { state.out << include_doc_id_; } else if (!doc_title.empty()) { state.out << detail::make_identifier(doc_title.get_quickbook()); } else { state.out << "library"; } state.out << "\"\n"; } state.out << " last-revision=\""; if (!last_revision.empty()) { state.out << doc_info_output(last_revision, 106); } else { // default value for last-revision is now char strdate[64]; strftime( strdate, sizeof(strdate), (debug_mode ? "DEBUG MODE Date: %Y/%m/%d %H:%M:%S $" : "$" /* prevent CVS substitution */ "Date: %Y/%m/%d %H:%M:%S $"), current_gm_time ); state.out << strdate; } state.out << "\" \n"; if (!xmlbase.empty()) { state.out << " xml:base=\"" << xmlbase_value << "\"\n"; } state.out << " xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n"; std::ostringstream tmp; if(!authors.empty()) { tmp << " <authorgroup>\n"; BOOST_FOREACH(value_consumer author_values, authors) { while (author_values.check()) { value surname = author_values.consume(doc_info_tags::author_surname); value first = author_values.consume(doc_info_tags::author_first); tmp << " <author>\n" << " <firstname>" << doc_info_output(first, 106) << "</firstname>\n" << " <surname>" << doc_info_output(surname, 106) << "</surname>\n" << " </author>\n"; } } tmp << " </authorgroup>\n"; }
bool operator<(const value& x, const value& y) { if (x.empty() && y.empty()) return false; if (x.empty()) return true; // empty is < !empty return compare(x, y) < 0; }
bool operator==(const value& x, const value& y) { if (x.empty() && y.empty()) return true; if (x.empty() || y.empty()) return false; return compare(x, y) == 0; }
bool operator<(const value& x, const value& y) { if (x.empty() && y.empty()) return false; if (x.empty()) return true; // empty is < !empty return x.data().less(y.data()); }
bool operator==(const value& x, const value& y) { if (x.empty() && y.empty()) return true; if (x.empty() || y.empty()) return false; return x.data().equal(y.data()); }