| // Boost.Geometry (aka GGL, Generic Geometry Library) |
| // |
| // Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands. |
| // Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland. |
| |
| // This file was modified by Oracle on 2014, 2015. |
| // Modifications copyright (c) 2014-2015, Oracle and/or its affiliates. |
| |
| // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle |
| |
| // Use, modification and distribution is subject to the Boost Software License, |
| // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // |
| #ifndef QUICKBOOK_OUTPUT_HPP |
| #define QUICKBOOK_OUTPUT_HPP |
| |
| |
| #include <string> |
| #include <vector> |
| |
| #include <boost/algorithm/string.hpp> |
| |
| #include <doxygen_elements.hpp> |
| #include <parameter_predicates.hpp> |
| |
| std::string qbk_escaped(std::string const& s) |
| { |
| // Replace _ by unicode to avoid accidental quickbook underlining. |
| // 1) do NOT do this in quickbook markup, so not within [] |
| // (e.g. to avoid [include get_point.qbk] having unicoded) |
| // 2) \[ and \] should not count as [] |
| std::size_t const len = s.length(); |
| int counter = 0; |
| std::string result = ""; |
| for (std::size_t i = 0; i < len; i++) |
| { |
| switch(s[i]) |
| { |
| case '[' : counter++; break; |
| case ']' : counter--; break; |
| case '\\' : |
| { |
| result += s[i]; |
| if (i + 1 < len) |
| { |
| result += s[i + 1]; |
| } |
| i++; |
| continue; |
| } |
| case '_' : |
| if (counter == 0) |
| { |
| result += "\\u005f"; |
| continue; |
| } |
| } |
| result += s[i]; |
| } |
| |
| return result; |
| } |
| |
| |
| inline void next_item(std::string const& first, std::string const& indent, |
| std::size_t items_per_line, |
| std::size_t& index, std::ostream& out) |
| { |
| if (index > 0) |
| { |
| if (index % items_per_line == 0) |
| { |
| out << "," << std::endl << indent; |
| } |
| else |
| { |
| out << ", "; |
| } |
| } |
| else |
| { |
| std::cout << first; |
| } |
| index++; |
| } |
| |
| void quickbook_template_parameter_list(std::vector<parameter> const& parameters, |
| std::string const& related_name, |
| std::ostream& out) |
| { |
| if (!parameters.empty()) |
| { |
| std::string const header = "template<"; |
| std::size_t index = 0; |
| std::string const indent(header.length(), ' '); |
| out << header; |
| BOOST_FOREACH(parameter const& p, parameters) |
| { |
| if (p.fulltype.empty()) |
| { |
| std::cerr << "Warning: template parameter " << p.name << " has no type in " << related_name << std::endl; |
| } |
| |
| next_item("", indent, 4, index, out); |
| out << p.fulltype; |
| } |
| out << ">" << std::endl; |
| } |
| } |
| |
| |
| void quickbook_synopsis(function const& f, std::ostream& out) |
| { |
| out << "``"; |
| quickbook_template_parameter_list(f.template_parameters, f.name, out); |
| |
| switch(f.type) |
| { |
| case function_constructor_destructor : |
| out << f.name; |
| break; |
| case function_member : |
| out << f.return_type << " " << f.name; |
| break; |
| case function_free : |
| out << f.definition; |
| break; |
| case function_define : |
| out << "#define " << f.name; |
| break; |
| case function_unknown : |
| // do nothing |
| break; |
| } |
| |
| // Output the parameters |
| // Because we want to be able to skip, we cannot use the argstring |
| { |
| std::size_t index = 0; |
| std::string const indent(f.name.length() + f.return_type.length() + 2, ' '); |
| BOOST_FOREACH(parameter const& p, f.parameters) |
| { |
| if (! p.skip) |
| { |
| next_item("(", indent, 3, index, out); |
| |
| out << p.fulltype << (p.fulltype.empty() ? "" : " ") |
| << p.name |
| << (p.default_value.empty() ? "" : " = ") |
| << p.default_value; |
| } |
| } |
| if (index > 0) |
| { |
| out << ")"; |
| } |
| else if (f.type != function_define) |
| { |
| out << "()"; |
| } |
| } |
| |
| out << "``" |
| << std::endl |
| << std::endl; |
| } |
| |
| |
| void quickbook_synopsis(enumeration const& e, std::ostream& out) |
| { |
| out << "``enum " << e.name; |
| bool first = true; |
| |
| bool has_many_values = e.enumeration_values.size() > 4; |
| |
| BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) |
| { |
| if (has_many_values) |
| { |
| if (first) |
| { |
| out << std::endl << "{"; |
| } |
| else |
| { |
| out << ","; |
| } |
| out << std::endl << " " << value.name; |
| } |
| else |
| { |
| out << (first ? " {" : ", ") << value.name; |
| } |
| if (! value.initializer.empty()) |
| { |
| // Doxygen 1.6 does not include "=" in the <initializer> tag, Doxygen 1.8 does. |
| // We just remove the "=" to have consistent output |
| out << " = " << boost::trim_copy(boost::replace_all_copy(value.initializer, "=", "")); |
| } |
| first = false; |
| } |
| if (! first) |
| { |
| if (has_many_values) |
| { |
| out << std::endl; |
| } |
| out << "};"; |
| } |
| out << "``" |
| << std::endl |
| << std::endl; |
| } |
| |
| inline bool includes(std::string const& filename, std::string const& header) |
| { |
| std::string result; |
| |
| std::ifstream cpp_file(filename.c_str()); |
| if (cpp_file.is_open()) |
| { |
| while (! cpp_file.eof() ) |
| { |
| std::string line; |
| std::getline(cpp_file, line); |
| boost::trim(line); |
| if (boost::starts_with(line, "#include") |
| && boost::contains(line, header)) |
| { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| |
| std::string fix_location(std::string const& raw_location) |
| { |
| if ( raw_location.find("detail/") == std::string::npos |
| || raw_location.find("/interface.hpp") == std::string::npos ) |
| { |
| return raw_location; |
| } |
| |
| std::string fixed_location(raw_location); |
| |
| fixed_location.erase(fixed_location.find("detail/"), 7u); |
| fixed_location.erase(fixed_location.find("/interface"), 10u); |
| |
| return fixed_location; |
| } |
| |
| |
| std::string fix_include_header(std::string const& header) |
| { |
| if ( header.find("geometry/geometry.hpp") == std::string::npos ) |
| { |
| return header; |
| } |
| |
| std::string fixed_header(header); |
| |
| fixed_header.erase(fixed_header.find("geometry/"), 9u); |
| |
| return fixed_header; |
| } |
| |
| |
| void quickbook_header(std::string const& raw_location, |
| configuration const& config, |
| std::ostream& out) |
| { |
| std::string location = fix_location(raw_location); |
| |
| if (! location.empty()) |
| { |
| std::vector<std::string> including_headers; |
| |
| // Select headerfiles containing to this location |
| BOOST_FOREACH(std::string const& header, config.convenience_headers) |
| { |
| if (includes(config.convenience_header_path + header, location)) |
| { |
| including_headers.push_back(header); |
| } |
| } |
| |
| out << "[heading Header]" << std::endl; |
| if (! including_headers.empty()) |
| { |
| out << "Either" |
| << (including_headers.size() > 1 ? " one of" : "") |
| << std::endl << std::endl; |
| BOOST_FOREACH(std::string const& header, including_headers) |
| { |
| out << "`#include <" << fix_include_header(config.start_include + header) << ">`" << std::endl << std::endl; |
| } |
| |
| out << std::endl << "Or" << std::endl << std::endl; |
| } |
| out << "`#include <" << location << ">`" << std::endl; |
| out << std::endl; |
| } |
| } |
| |
| |
| void quickbook_markup(std::vector<markup> const& qbk_markup, |
| markup_order_type order, markup_type type, |
| std::ostream& out) |
| { |
| bool has_output = false; |
| BOOST_FOREACH(markup const& inc, qbk_markup) |
| { |
| if (inc.type == type && inc.order == order) |
| { |
| out << inc.value << std::endl; |
| has_output = true; |
| } |
| } |
| if (has_output) |
| { |
| out << std::endl; |
| } |
| } |
| |
| |
| |
| void quickbook_string_with_heading_if_present(std::string const& heading, |
| std::string const& contents, std::ostream& out) |
| { |
| if (! contents.empty()) |
| { |
| out << "[heading " << heading << "]" << std::endl |
| << qbk_escaped(contents) << std::endl |
| << std::endl; |
| } |
| } |
| |
| inline std::string to_section_name(std::string const& name) |
| { |
| // Make section-name lowercase and remove :: because these are filenames |
| return boost::to_lower_copy(boost::replace_all_copy(name, "::", "_")); |
| } |
| |
| void quickbook_output_function_parameters(function const& f, std::ostream& out) |
| { |
| BOOST_FOREACH(parameter const& p, f.parameters) |
| { |
| if (! p.skip) |
| { |
| out << "[* " << p.fulltype << "]: ['" << p.name << "]: " << p.brief_description << std::endl << std::endl; |
| } |
| } |
| out << std::endl; |
| out << std::endl; |
| } |
| |
| void quickbook_output_function_return(function const& f, std::ostream& out) |
| { |
| if (! f.return_description.empty()) |
| { |
| out << f.return_description << std::endl; |
| } |
| |
| out << std::endl; |
| } |
| |
| inline std::string namespace_skipped(std::string const& name, configuration const& config) |
| { |
| return config.skip_namespace.empty() |
| ? name |
| : boost::replace_all_copy(name, config.skip_namespace, "") |
| ; |
| } |
| |
| inline std::string output_if_different(std::string const& s, std::string const& s2) |
| { |
| return boost::equals(s, s2) |
| ? "" |
| : s + " " |
| ; |
| } |
| |
| inline void quickbook_output_indexterm(std::string const& term, std::ostream& out |
| //, std::string const& secondary = "" |
| ) |
| { |
| out << "'''"; |
| if (boost::contains(term, "::")) |
| { |
| // "Unnamespace" it and add all terms (also namespaces) |
| std::vector<std::string> splitted; |
| std::string for_split = boost::replace_all_copy(term, "::", ":"); |
| boost::split(splitted, for_split, boost::is_any_of(":"), boost::token_compress_on); |
| BOOST_FOREACH(std::string const& part, splitted) |
| { |
| out << "<indexterm><primary>" << part << "</primary></indexterm>"; |
| } |
| } |
| else |
| { |
| out << "<indexterm><primary>" << term; |
| /*if (! secondary.empty()) |
| { |
| out << "<secondary>" << secondary << "</secondary>"; |
| }*/ |
| out << "</primary></indexterm>"; |
| } |
| out << "'''" << std::endl; |
| } |
| |
| void quickbook_output(function const& f, configuration const& config, std::ostream& out) |
| { |
| // Write the parsed function |
| int arity = (int)f.parameters.size(); |
| |
| std::string additional_description; |
| |
| if (! f.additional_description.empty()) |
| { |
| additional_description = " ("; |
| additional_description += f.additional_description; |
| additional_description += ")"; |
| } |
| |
| out << "[section:" << to_section_name(f.name); |
| // Make section name unique if necessary by arity and additional description |
| if (! f.unique) |
| { |
| out << "_" << arity; |
| if (! f.additional_description.empty()) |
| { |
| out << "_" << boost::to_lower_copy(boost::replace_all_copy(f.additional_description, " ", "_")); |
| } |
| } |
| out << " " << f.name |
| << additional_description |
| << "]" << std::endl |
| << std::endl; |
| |
| quickbook_output_indexterm(f.name, out); |
| |
| out << qbk_escaped(f.brief_description) << std::endl; |
| out << std::endl; |
| |
| quickbook_string_with_heading_if_present("Description", f.detailed_description, out); |
| |
| // Synopsis |
| quickbook_markup(f.qbk_markup, markup_before, markup_synopsis, out); |
| out << "[heading Synopsis]" << std::endl; |
| quickbook_synopsis(f, out); |
| quickbook_markup(f.qbk_markup, markup_after, markup_synopsis, out); |
| |
| |
| out << "[heading Parameters]" << std::endl |
| << std::endl; |
| |
| out << "[table" << std::endl << "["; |
| if (f.type != function_define) |
| { |
| out << "[Type] [Concept] "; |
| } |
| out << "[Name] [Description] ]" << std::endl; |
| |
| // First: output any template parameter which is NOT used in the normal parameter list |
| BOOST_FOREACH(parameter const& tp, f.template_parameters) |
| { |
| if (! tp.skip) |
| { |
| std::vector<parameter>::const_iterator it = std::find_if(f.parameters.begin(), f.parameters.end(), par_by_type(tp.name)); |
| |
| if (it == f.parameters.end()) |
| { |
| out << "[[" << tp.name << "] [" << tp.brief_description << "] [ - ] [Must be specified]]" << std::endl; |
| } |
| } |
| } |
| |
| BOOST_FOREACH(parameter const& p, f.parameters) |
| { |
| if (! p.skip) |
| { |
| out << "["; |
| std::vector<parameter>::const_iterator it = std::find_if(f.template_parameters.begin(), |
| f.template_parameters.end(), par_by_name(p.type)); |
| |
| if (f.type != function_define) |
| { |
| out << "[" << p.fulltype |
| << "] [" << (it == f.template_parameters.end() ? "" : it->brief_description) |
| << "] "; |
| } |
| out << "[" << p.name |
| << "] [" << p.brief_description |
| << "]]" |
| << std::endl; |
| } |
| } |
| out << "]" << std::endl |
| << std::endl |
| << std::endl; |
| |
| quickbook_string_with_heading_if_present("Returns", f.return_description, out); |
| |
| quickbook_header(f.location, config, out); |
| quickbook_markup(f.qbk_markup, markup_any, markup_default, out); |
| |
| out << std::endl; |
| out << "[endsect]" << std::endl; |
| out << std::endl; |
| } |
| |
| void quickbook_output(enumeration const& e, configuration const& config, std::ostream& out) |
| { |
| out << "[section:" << to_section_name(e.name); |
| out << " " << e.name |
| << "]" << std::endl |
| << std::endl; |
| |
| quickbook_output_indexterm(e.name, out); |
| BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) |
| { |
| quickbook_output_indexterm(value.name, out); |
| } |
| |
| out << e.brief_description << std::endl; |
| out << std::endl; |
| |
| quickbook_string_with_heading_if_present("Description", e.detailed_description, out); |
| |
| // Synopsis |
| quickbook_markup(e.qbk_markup, markup_before, markup_synopsis, out); |
| out << "[heading Synopsis]" << std::endl; |
| quickbook_synopsis(e, out); |
| quickbook_markup(e.qbk_markup, markup_after, markup_synopsis, out); |
| |
| |
| out << "[heading Values]" << std::endl |
| << std::endl; |
| |
| out << "[table" << std::endl << "["; |
| out << "[Value] [Description] ]" << std::endl; |
| |
| BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) |
| { |
| out << "[[" << value.name |
| << "] [" << value.brief_description |
| << "]]" |
| << std::endl; |
| } |
| out << "]" << std::endl |
| << std::endl |
| << std::endl; |
| |
| quickbook_header(e.location, config, out); |
| quickbook_markup(e.qbk_markup, markup_any, markup_default, out); |
| |
| out << std::endl; |
| out << "[endsect]" << std::endl; |
| out << std::endl; |
| } |
| |
| void quickbook_output_function(std::vector<function> const& functions, |
| function_type type, |
| std::string const& title, |
| configuration const& , std::ostream& out) |
| { |
| std::string returns = type == function_constructor_destructor ? "" : " [Returns]"; |
| out << "[heading " << title << "(s)]" << std::endl |
| << "[table" << std::endl |
| << "[[Function] [Description] [Parameters] " << returns << "]" << std::endl; |
| |
| BOOST_FOREACH(function const& f, functions) |
| { |
| if (f.type == type) |
| { |
| out << "[["; |
| quickbook_synopsis(f, out); |
| out << "] [" << f.brief_description << "] ["; |
| quickbook_output_function_parameters(f, out); |
| out << "]"; |
| if ( type != function_constructor_destructor ) |
| { |
| out << "[" << std::endl; |
| quickbook_output_function_return(f, out); |
| out << "]" << std::endl; |
| } |
| out << "]" << std::endl; |
| } |
| } |
| out << "]" << std::endl |
| << std::endl; |
| } |
| |
| void quickbook_output(class_or_struct const& cos, configuration const& config, std::ostream& out) |
| { |
| // Skip namespace |
| std::string short_name = namespace_skipped(cos.fullname, config); |
| |
| // Write the parsed function |
| out << "[section:" << to_section_name(short_name) << " " << short_name << "]" << std::endl |
| << std::endl; |
| |
| quickbook_output_indexterm(short_name, out); |
| |
| out << cos.brief_description << std::endl; |
| out << std::endl; |
| |
| quickbook_string_with_heading_if_present("Description", cos.detailed_description, out); |
| |
| quickbook_markup(cos.qbk_markup, markup_before, markup_synopsis, out); |
| out << "[heading Synopsis]" << std::endl |
| << "``"; |
| quickbook_template_parameter_list(cos.template_parameters, cos.name, out); |
| out << (cos.is_class ? "class" : "struct") |
| << " " << short_name << std::endl; |
| |
| if (! cos.base_classes.empty()) |
| { |
| out << " : "; |
| bool first = true; |
| BOOST_FOREACH(base_class const& bc, cos.base_classes) |
| { |
| if (! first) |
| { |
| out << std::endl << " , "; |
| } |
| out << output_if_different(bc.derivation, "private") |
| << output_if_different(bc.virtuality, "non-virtual") |
| << namespace_skipped(bc.name, config); |
| first = false; |
| } |
| out << std::endl; |
| } |
| |
| out << "{" << std::endl; |
| if (! cos.variables.empty() && config.output_member_variables) |
| { |
| size_t maxlength = 0; |
| BOOST_FOREACH(parameter const& p, cos.variables) |
| { |
| if (! p.skip) |
| { |
| size_t length = 6 + p.fulltype.size() + p.name.size(); |
| if (length > maxlength) maxlength = length; |
| } |
| } |
| BOOST_FOREACH(parameter const& p, cos.variables) |
| { |
| if (! p.skip) |
| { |
| size_t length = 4 + p.fulltype.size() + p.name.size(); |
| out << " " << p.fulltype << " " << p.name << ";"; |
| if (! p.brief_description.empty()) |
| { |
| while(length++ < maxlength) out << " "; |
| out << "// " << p.brief_description; |
| } |
| out << std::endl; |
| } |
| } |
| } |
| else |
| { |
| out << " // ..." << std::endl; |
| } |
| out << "};" << std::endl |
| << "``" << std::endl << std::endl; |
| quickbook_markup(cos.qbk_markup, markup_after, markup_synopsis, out); |
| |
| |
| |
| if (! cos.template_parameters.empty()) |
| { |
| bool has_default = false; |
| BOOST_FOREACH(parameter const& p, cos.template_parameters) |
| { |
| if (! p.default_value.empty()) |
| { |
| has_default = true; |
| } |
| } |
| |
| out << "[heading Template parameter(s)]" << std::endl |
| << "[table" << std::endl |
| << "[[Parameter]"; |
| if (has_default) |
| { |
| out << " [Default]"; |
| } |
| out << " [Description]]" << std::endl; |
| |
| BOOST_FOREACH(parameter const& p, cos.template_parameters) |
| { |
| out << "[[" << p.fulltype; |
| if (has_default) |
| { |
| out << "] [" << p.default_value; |
| } |
| out << "] [" << p.brief_description << "]]" << std::endl; |
| } |
| out << "]" << std::endl |
| << std::endl; |
| } |
| |
| |
| std::map<function_type, int> counts; |
| BOOST_FOREACH(function const& f, cos.functions) |
| { |
| counts[f.type]++; |
| } |
| |
| if (counts[function_constructor_destructor] > 0) |
| { |
| quickbook_output_function(cos.functions, function_constructor_destructor, "Constructor", config, out); |
| } |
| |
| if (counts[function_member] > 0) |
| { |
| quickbook_output_function(cos.functions, function_member, "Member Function", config, out); |
| } |
| |
| quickbook_header(cos.location, config, out); |
| quickbook_markup(cos.qbk_markup, markup_any, markup_default, out); |
| |
| out << "[endsect]" << std::endl |
| << std::endl; |
| } |
| |
| |
| // ----------------------------------------------------------------------------------------------- // |
| // ALT |
| // ----------------------------------------------------------------------------------------------- // |
| |
| std::string remove_template_parameters(std::string const& name) |
| { |
| std::string res; |
| std::string::size_type prev_i = 0, i = 0; |
| int blocks_counter = 0; |
| for ( ;; ) |
| { |
| std::string::size_type next_begin = name.find('<', i); |
| std::string::size_type next_end = name.find('>', i); |
| |
| if ( next_begin == next_end ) |
| { |
| res += name.substr(prev_i, next_begin - prev_i); |
| break; |
| } |
| else if ( next_begin < next_end ) |
| { |
| i = next_begin + 1; |
| if ( blocks_counter == 0 ) |
| res += name.substr(prev_i, next_begin - prev_i) + "<...>"; |
| blocks_counter++; |
| } |
| else |
| { |
| i = next_end + 1; |
| blocks_counter--; |
| if ( blocks_counter == 0 ) |
| prev_i = i; |
| } |
| } |
| |
| return res; |
| } |
| |
| std::string replace_brackets(std::string const& str) |
| { |
| return boost::replace_all_copy(boost::replace_all_copy(str, "[", "\\["), "]", "\\]"); |
| } |
| |
| void quickbook_output_enumerations(std::vector<enumeration> const& enumerations, |
| configuration const& , |
| std::ostream& out) |
| { |
| out << "[table" << std::endl |
| << "[[Enumeration][Description]]" << std::endl; |
| |
| for ( size_t i = 0 ; i < enumerations.size() ; ++i ) |
| { |
| enumeration const& e = enumerations[i]; |
| |
| out << "[[[link " << e.id << " `"; |
| out << e.name; |
| out << "`]][" << e.brief_description << "]]" << std::endl; |
| } |
| out << "]" << std::endl |
| << std::endl; |
| } |
| |
| void quickbook_synopsis_short(function const& f, std::ostream& out) |
| { |
| if ( f.type != function_unknown ) |
| out << f.name; |
| |
| bool first = true; |
| BOOST_FOREACH(parameter const& p, f.parameters) |
| { |
| if ( !p.skip && p.default_value.empty() ) |
| { |
| out << (first ? "(" : ", ") << remove_template_parameters(p.fulltype_without_links); |
| first = false; |
| } |
| } |
| |
| |
| if (! first) |
| out << ")"; |
| else if (f.type != function_define) |
| out << "()"; |
| } |
| |
| void quickbook_output_functions(std::vector<function> const& functions, |
| function_type type, |
| configuration const& , |
| std::ostream& out, |
| bool display_all = false, |
| std::string const& ColTitle = "Function") |
| { |
| bool show_modifiers = false; |
| BOOST_FOREACH(function const& f, functions) |
| { |
| if ( (display_all || f.type == type) && (f.is_const || f.is_static) && !f.brief_description.empty() ) |
| show_modifiers = true; |
| } |
| |
| out << "[table\n" |
| << "["; |
| if ( show_modifiers ) |
| out << "[Modifier]"; |
| out << "[" << ColTitle << "]"; |
| out << "[Description]"; |
| out << "]" << std::endl; |
| |
| for ( size_t i = 0 ; i < functions.size() ; ++i ) |
| { |
| function const& f = functions[i]; |
| |
| if ( f.brief_description.empty() ) |
| continue; |
| |
| if (display_all || f.type == type) |
| { |
| out << "["; |
| if ( show_modifiers ) |
| { |
| out << "["; |
| out << (f.is_static ? "`static`" : ""); |
| out << (f.is_const ? " `const`" : ""); |
| out << "]"; |
| } |
| out << "[[link " << f.id << " `"; |
| quickbook_synopsis_short(f, out); |
| out << "`]]"; |
| out << "[" << f.brief_description << "]"; |
| out << "]" << std::endl; |
| } |
| } |
| out << "]" << std::endl |
| << std::endl; |
| } |
| |
| void output_paragraphs_note_warning(element const& el, std::ostream & out) |
| { |
| // Additional paragraphs |
| if ( !el.paragraphs.empty() ) |
| { |
| BOOST_FOREACH(paragraph const& p, el.paragraphs) |
| { |
| if ( !p.title.empty() ) |
| out << "[heading " << p.title << "]" << std::endl; |
| else |
| out << "\n\n" << std::endl; |
| out << p.text << std::endl; |
| out << std::endl; |
| } |
| } |
| |
| // Note |
| if ( !el.note.empty() ) |
| { |
| out << "[note " << el.note << "]" << std::endl; |
| out << std::endl; |
| } |
| |
| // Warning |
| if ( !el.warning.empty() ) |
| { |
| out << "[warning " << el.warning << "]" << std::endl; |
| out << std::endl; |
| } |
| } |
| |
| void inline_str_with_links(std::string const& str, std::ostream & out) |
| { |
| typedef std::string::size_type ST; |
| |
| bool link_started = false; |
| bool first = true; |
| for ( ST i = 0 ; i < str.size() ; ++i ) |
| { |
| if ( !link_started ) |
| { |
| if ( str[i] == '[' && str.substr(i, 6) == "[link " ) |
| { |
| if ( !first ) |
| { |
| out << "`"; |
| first = true; |
| } |
| link_started = true; |
| out << "[^[link "; |
| i += 5; // (+ 6 - 1) |
| } |
| else |
| { |
| if ( first ) |
| { |
| out << "`"; |
| first = false; |
| } |
| out << str[i]; |
| } |
| } |
| else |
| { |
| if ( str[i] == '\\' ) |
| { |
| out << str[i]; |
| ++i; |
| if ( i < str.size() ) |
| out << str[i]; |
| } |
| else if ( str[i] == ']' ) |
| { |
| out << "]]"; |
| link_started = false; |
| } |
| else |
| out << str[i]; |
| } |
| } |
| |
| if ( !first ) |
| out << "`"; |
| if ( link_started ) |
| out << "]]"; |
| } |
| |
| void quickbook_template_parameter_list_alt(std::vector<parameter> const& parameters, std::ostream& out) |
| { |
| std::string next_param; |
| |
| if ( 2 < parameters.size() ) |
| next_param = std::string("`,`\n") + " "; |
| else |
| next_param = "`,` "; |
| |
| if (!parameters.empty()) |
| { |
| out << "`template<`" ; |
| bool first = true; |
| BOOST_FOREACH(parameter const& p, parameters) |
| { |
| out << (first ? "" : next_param.c_str()); |
| inline_str_with_links(p.fulltype, out); |
| |
| if ( !p.default_value.empty() ) |
| { |
| out << " = "; |
| // don't display default values from details |
| if ( p.default_value.find("detail") != std::string::npos ) |
| out << "/default/"; |
| else |
| inline_str_with_links(p.default_value, out); |
| } |
| |
| first = false; |
| } |
| out << "`>`"; |
| } |
| } |
| |
| void quickbook_synopsis_alt(function const& f, std::ostream& out) |
| { |
| out << "[pre\n"; |
| quickbook_template_parameter_list_alt(f.template_parameters, out); |
| out << "\n"; |
| |
| std::size_t offset = 1; // '(' |
| switch(f.type) |
| { |
| case function_constructor_destructor : |
| out << "`" << f.name << "`"; |
| offset += f.name.size(); |
| break; |
| case function_member : |
| case function_free : |
| // don't display return types from details |
| if ( f.return_type.find("detail") != std::string::npos ) |
| { |
| out << "/unspecified/"; |
| offset += 11; |
| } |
| else |
| { |
| inline_str_with_links(f.return_type, out); |
| offset += f.return_type_without_links.size(); |
| } |
| out << " `" << f.name << "`"; |
| offset += 1 + f.name.size(); |
| break; |
| case function_define : |
| out << "`#define " << f.name << "`"; |
| offset += 8 + f.name.size(); |
| break; |
| case function_unknown : |
| // do nothing |
| break; |
| } |
| |
| std::string par_end("`,` "); |
| if ( 2 < f.parameters.size() ) |
| par_end = std::string("`,`\n") + std::string(offset, ' '); |
| |
| // Output the parameters |
| // Because we want to be able to skip, we cannot use the argstring |
| { |
| bool first = true; |
| BOOST_FOREACH(parameter const& p, f.parameters) |
| { |
| if (! p.skip) |
| { |
| out << (first ? "`(`" : par_end); |
| if ( !p.fulltype.empty() ) |
| { |
| inline_str_with_links(p.fulltype, out); |
| out << " "; |
| } |
| if ( !p.name.empty() ) |
| out << "`" << p.name << "`"; |
| if ( !p.default_value.empty() ) |
| { |
| out << " = "; |
| // don't display default values from details |
| if ( p.default_value.find("detail") != std::string::npos ) |
| out << "/default/"; |
| else |
| inline_str_with_links(p.default_value, out); |
| } |
| first = false; |
| } |
| } |
| |
| if (! first) |
| out << "`)`\n"; |
| else if (f.type != function_define) |
| out << "`()`\n"; |
| } |
| |
| out << "]" |
| << std::endl |
| << std::endl; |
| } |
| |
| void quickbook_synopsis_alt(class_or_struct const& cos, configuration const& config, std::ostream & out) |
| { |
| std::string short_name = namespace_skipped(cos.fullname, config); |
| |
| out << "[pre\n"; |
| |
| quickbook_template_parameter_list_alt(cos.template_parameters, out); |
| out << "\n"; |
| |
| out << (cos.is_class ? "`class " : "`struct "); |
| { |
| std::string::size_type last_scope = std::string::npos; |
| std::string::size_type i = short_name.find("<"); |
| for(std::string::size_type j = short_name.find("::") ; j < i ; j = short_name.find("::", j+1)) |
| last_scope = j; |
| if ( last_scope == std::string::npos ) |
| out << short_name << "`" << std::endl; |
| else |
| out << short_name.substr(last_scope + 2) << "`" << std::endl; |
| } |
| |
| if (! cos.base_classes.empty()) |
| { |
| bool first = true; |
| BOOST_FOREACH(base_class const& bc, cos.base_classes) |
| { |
| // don't display base classes from details |
| if ( bc.name.find("detail") != std::string::npos ) |
| continue; |
| |
| if (first) |
| out << "` : "; |
| else |
| out << std::endl << " , "; |
| out << output_if_different(bc.derivation, "private") |
| << output_if_different(bc.virtuality, "non-virtual") |
| << namespace_skipped(bc.name, config); |
| first = false; |
| } |
| if (!first) |
| out << "`" << std::endl; |
| } |
| |
| out << "`{`" << std::endl |
| << "` // ...`" << std::endl |
| << "`};`" << std::endl |
| << "]" << std::endl << std::endl; |
| } |
| |
| void quickbook_synopsis_alt(enumeration const& e, std::ostream& out) |
| { |
| std::string values_separator = |
| e.enumeration_values.size() <= 2 ? |
| std::string(", ") : |
| ( std::string(",\n") + std::string(e.name.size() + 7, ' ') ); |
| |
| out << "``enum " << e.name << " "; |
| bool first = true; |
| BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) |
| { |
| out << (first ? "{" : values_separator.c_str()); |
| out << value.name; |
| if ( !value.initializer.empty() ) |
| { |
| out << " = " << boost::trim_copy(boost::replace_all_copy(value.initializer, "=", "")); |
| } |
| first = false; |
| } |
| if (! first) |
| { |
| out << "};"; |
| } |
| out << "``" |
| << std::endl |
| << std::endl; |
| } |
| |
| template <typename Range> |
| bool has_brief_description(Range const& rng) |
| { |
| typedef typename Range::value_type V; |
| BOOST_FOREACH(V const& bc, rng) |
| { |
| if ( !bc.brief_description.empty() ) |
| return true; |
| } |
| return false; |
| } |
| |
| template <typename Range> |
| bool has_brief_description(Range const& rng, function_type t) |
| { |
| typedef typename Range::value_type V; |
| BOOST_FOREACH(V const& bc, rng) |
| { |
| if ( bc.type == t && !bc.brief_description.empty() ) |
| return true; |
| } |
| return false; |
| } |
| |
| void quickbook_output_functions_details(std::vector<function> const& functions, |
| function_type type, |
| configuration const& , |
| std::ostream& out, |
| bool display_all = false) |
| { |
| for ( size_t i = 0 ; i < functions.size() ; ++i ) |
| { |
| function const& f = functions[i]; |
| |
| if ( f.brief_description.empty() ) |
| continue; |
| |
| if ( display_all || f.type == type ) |
| { |
| // Section |
| std::stringstream ss; |
| quickbook_synopsis_short(f, ss); |
| out << "[#" << f.id << "]" << std::endl; |
| out << "[section " << replace_brackets(ss.str()) << "]" << std::endl; |
| |
| quickbook_output_indexterm(f.name, out); |
| |
| // Brief description |
| out << f.brief_description << std::endl; |
| out << std::endl; |
| |
| // Detail description |
| if ( !f.detailed_description.empty() ) |
| { |
| out << "[heading Description]" << std::endl; |
| out << f.detailed_description; |
| } |
| |
| // Synopsis |
| quickbook_markup(f.qbk_markup, markup_before, markup_synopsis, out); |
| out << "[heading Synopsis]" << std::endl; |
| quickbook_synopsis_alt(f, out); |
| quickbook_markup(f.qbk_markup, markup_after, markup_synopsis, out); |
| |
| if ( f.is_static || f.is_virtual || f.is_explicit || f.is_const ) |
| { |
| out << "[heading Modifier(s)]" << std::endl; |
| out << "``" |
| << (f.is_static ? "static " : "") |
| << (f.is_virtual ? "virtual " : "") |
| << (f.is_explicit ? "explicit " : "") |
| << (f.is_const ? "const " : "") |
| << "``"; |
| } |
| |
| // Template parameters |
| if ( !f.template_parameters.empty() && has_brief_description(f.template_parameters) ) |
| { |
| out << "[heading Template parameter(s)]" << std::endl |
| << "[table" << std::endl |
| << "[[Parameter] [Description]]" << std::endl; |
| |
| BOOST_FOREACH(parameter const& p, f.template_parameters) |
| { |
| if ( p.brief_description.empty() ) |
| continue; |
| |
| out << "[[`"; |
| if ( p.fulltype.find("typename ") == 0 ) |
| out << p.fulltype.substr(9); |
| else if ( p.fulltype.find("class ") == 0 ) |
| out << p.fulltype.substr(6); |
| else |
| out << p.fulltype; |
| out << "`][" << p.brief_description << "]]" << std::endl; |
| } |
| out << "]" << std::endl |
| << std::endl; |
| } |
| |
| // Parameters |
| if ( !f.parameters.empty() && has_brief_description(f.parameters) ) |
| { |
| out << "[heading Parameter(s)]" << std::endl; |
| out << "[table " << std::endl; |
| out << "["; |
| if ( f.type != function_define ) |
| out << "[Type]"; |
| out << "[Name][Description]]" << std::endl; |
| BOOST_FOREACH(parameter const& p, f.parameters) |
| { |
| if (!p.skip) |
| { |
| out << "["; |
| if ( f.type != function_define ) |
| { |
| out << "["; |
| inline_str_with_links(p.fulltype, out); |
| out << "]"; |
| } |
| out << "[ `" << p.name << "` ][" << p.brief_description << "]]"<< std::endl; |
| } |
| } |
| out << "]" << std::endl; |
| } |
| |
| // Precondition |
| if ( !f.precondition.empty() ) |
| { |
| out << "[heading Precondition(s)]" << std::endl; |
| out << f.precondition << std::endl; |
| out << std::endl; |
| } |
| |
| // Return |
| if ( !f.return_description.empty() ) |
| { |
| out << "[heading Returns]" << std::endl; |
| out << f.return_description << std::endl; |
| } |
| |
| // Additional paragraphs, note, warning |
| output_paragraphs_note_warning(f, out); |
| |
| // QBK markup |
| quickbook_markup(f.qbk_markup, markup_any, markup_default, out); |
| |
| // Section end |
| out << "[endsect]" << std::endl |
| //<< "[br]" << std::endl |
| << std::endl; |
| } |
| } |
| } |
| |
| void quickbook_output_enumeration_details(enumeration const& e, configuration const& , std::ostream& out) |
| { |
| out << "[#" << e.id << "]\n"; |
| out << "[section " << e.name << "]" << std::endl |
| << std::endl; |
| |
| quickbook_output_indexterm(e.name, out); |
| BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) |
| { |
| quickbook_output_indexterm(value.name, out); |
| } |
| |
| out << e.brief_description << std::endl; |
| out << std::endl; |
| |
| if ( !e.detailed_description.empty() ) |
| { |
| out << "[heading Description]\n\n"; |
| out << e.detailed_description << "\n\n"; |
| } |
| |
| // Additional paragraphs, note, warning |
| output_paragraphs_note_warning(e, out); |
| |
| quickbook_markup(e.qbk_markup, markup_any, markup_default, out); |
| |
| // Synopsis |
| quickbook_markup(e.qbk_markup, markup_before, markup_synopsis, out); |
| out << "[heading Synopsis]" << std::endl; |
| quickbook_synopsis_alt(e, out); |
| quickbook_markup(e.qbk_markup, markup_after, markup_synopsis, out); |
| |
| |
| out << "[heading Values]" << std::endl |
| << std::endl; |
| |
| out << "[table" << std::endl << "["; |
| out << "[Value] [Description] ]" << std::endl; |
| |
| BOOST_FOREACH(enumeration_value const& value, e.enumeration_values) |
| { |
| out << "[[" << value.name << "] [" << value.brief_description << "]]\n"; |
| } |
| out << "]\n\n\n"; |
| |
| out << std::endl; |
| out << "[endsect]" << std::endl; |
| out << std::endl; |
| } |
| |
| void quickbook_output_alt(documentation const& doc, configuration const& config, std::ostream& out) |
| { |
| if ( !doc.group_id.empty() ) |
| { |
| std::cout << "[section:" << doc.group_id << " " << doc.group_title << "]" << std::endl; |
| } |
| |
| if ( !doc.enumerations.empty() ) |
| { |
| std::cout << "[heading Enumerations]\n"; |
| quickbook_output_enumerations(doc.enumerations, config, out); |
| } |
| |
| if ( !doc.defines.empty() ) |
| { |
| std::cout << "[heading Defines]\n"; |
| quickbook_output_functions(doc.defines, function_unknown, config, out, true, "Define"); |
| } |
| |
| if ( !doc.functions.empty() ) |
| { |
| std::cout << "[heading Functions]\n"; |
| quickbook_output_functions(doc.functions, function_unknown, config, out, true, "Function"); |
| } |
| |
| BOOST_FOREACH(enumeration const& e, doc.enumerations) |
| { |
| quickbook_output_enumeration_details(e, config, out); |
| } |
| |
| quickbook_output_functions_details(doc.defines, function_unknown, config, out, true); |
| quickbook_output_functions_details(doc.functions, function_unknown, config, out, true); |
| |
| if ( !doc.group_id.empty() ) |
| { |
| out << "[endsect]" << std::endl |
| << std::endl; |
| } |
| } |
| |
| void quickbook_output_alt(class_or_struct const& cos, configuration const& config, std::ostream& out) |
| { |
| // Skip namespace |
| std::string short_name = namespace_skipped(cos.fullname, config); |
| |
| BOOST_ASSERT(configuration::alt == config.output_style); |
| |
| if ( !cos.id.empty() ) |
| out << "[#" << cos.id << "]" << std::endl; |
| out << "[section " << short_name << "]" << std::endl << std::endl; |
| |
| // WARNING! Can't be used in the case of specializations |
| quickbook_output_indexterm(short_name, out); |
| |
| // Brief |
| |
| out << cos.brief_description << std::endl; |
| out << std::endl; |
| |
| // Description |
| |
| quickbook_string_with_heading_if_present("Description", cos.detailed_description, out); |
| |
| // Additional paragraphs, note, warning |
| output_paragraphs_note_warning(cos, out); |
| |
| // Markup |
| quickbook_markup(cos.qbk_markup, markup_any, markup_default, out); |
| |
| // Header |
| |
| quickbook_header(cos.location, config, out); |
| |
| // Class synposis |
| |
| quickbook_markup(cos.qbk_markup, markup_before, markup_synopsis, out); |
| out << "[heading Synopsis]" << std::endl; |
| quickbook_synopsis_alt(cos, config, out); |
| quickbook_markup(cos.qbk_markup, markup_after, markup_synopsis, out); |
| |
| // Template parameters |
| |
| if (! cos.template_parameters.empty()) |
| { |
| if ( has_brief_description(cos.template_parameters) ) |
| { |
| out << "[heading Template parameter(s)]" << std::endl |
| << "[table" << std::endl |
| << "[[Parameter] [Description]]" << std::endl; |
| |
| BOOST_FOREACH(parameter const& p, cos.template_parameters) |
| { |
| if ( p.brief_description.empty() ) |
| continue; |
| |
| out << "[[`"; |
| if ( p.fulltype.find("typename ") == 0 ) |
| out << p.fulltype.substr(9); |
| else if ( p.fulltype.find("class ") == 0 ) |
| out << p.fulltype.substr(6); |
| else |
| out << p.fulltype; |
| out << "`][" << p.brief_description << "]]" << std::endl; |
| } |
| out << "]" << std::endl |
| << std::endl; |
| } |
| } |
| |
| // Typedefs |
| |
| if ( !cos.typedefs.empty() ) |
| { |
| if ( has_brief_description(cos.typedefs) ) |
| { |
| out << "[heading Typedef(s)]" << std::endl |
| << "[table" << std::endl |
| << "[[Type]"; |
| out << " [Description]]" << std::endl; |
| |
| BOOST_FOREACH(base_element const& e, cos.typedefs) |
| { |
| if ( e.brief_description.empty() ) |
| continue; |
| |
| out << "[["; |
| if ( !e.id.empty() ) |
| out << "[#" << e.id << "]" << " "; |
| out << "`" << e.name << "`"; |
| out << "][" << e.brief_description << "]]" << std::endl; |
| } |
| out << "]" << std::endl |
| << std::endl; |
| } |
| } |
| |
| // Members |
| |
| bool display_ctors = has_brief_description(cos.functions, function_constructor_destructor); |
| bool display_members = has_brief_description(cos.functions, function_member); |
| |
| std::map<function_type, int> counts; |
| BOOST_FOREACH(function const& f, cos.functions) |
| { |
| counts[f.type]++; |
| } |
| |
| if (display_ctors && counts[function_constructor_destructor] > 0) |
| { |
| out << "[heading Constructor(s) and destructor]" << std::endl; |
| quickbook_output_functions(cos.functions, function_constructor_destructor, config, out); |
| } |
| |
| if (display_members && counts[function_member] > 0) |
| { |
| out << "[heading Member(s)]" << std::endl; |
| quickbook_output_functions(cos.functions, function_member, config, out); |
| } |
| |
| // Details start |
| |
| //if ( display_ctors || display_members ) |
| // out << "[br]" << std::endl; |
| |
| if (display_ctors && counts[function_constructor_destructor] > 0) |
| quickbook_output_functions_details(cos.functions, function_constructor_destructor, config, out); |
| |
| if (display_members && counts[function_member] > 0) |
| quickbook_output_functions_details(cos.functions, function_member, config, out); |
| |
| // Details end |
| |
| out << "[endsect]" << std::endl |
| << std::endl; |
| } |
| |
| #endif // QUICKBOOK_OUTPUT_HPP |