blob: 515b10ba5098277c70ba8fcdecc7692c4956a4e8 [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright (c) 2010-2011 Barend Gehrels, Amsterdam, the Netherlands.
// 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;
}
void quickbook_template_parameter_list(std::vector<parameter> const& parameters, std::ostream& out, bool name = false)
{
if (!parameters.empty())
{
out << "template<" ;
bool first = true;
BOOST_FOREACH(parameter const& p, parameters)
{
out << (first ? "" : ", ") << p.fulltype;
first = false;
}
out << ">" << std::endl;
}
}
void quickbook_synopsis(function const& f, std::ostream& out)
{
out << "``";
quickbook_template_parameter_list(f.template_parameters, out);
switch(f.type)
{
case function_constructor :
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
{
bool first = true;
BOOST_FOREACH(parameter const& p, f.parameters)
{
if (! p.skip)
{
out
<< (first ? "(" : ", ")
<< p.fulltype << (p.fulltype.empty() ? "" : " ")
<< p.name
<< (p.default_value.empty() ? "" : " = ")
<< p.default_value;
first = false;
}
}
if (! first)
{
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;
BOOST_FOREACH(enumeration_value const& value, e.enumeration_values)
{
out << (first ? " {" : ", ") << value.name;
if (! value.initializer.empty())
{
out << " = " << boost::trim_copy(value.initializer);
}
first = false;
}
if (! first)
{
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;
}
void quickbook_header(std::string const& location,
configuration const& config,
std::ostream& out)
{
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 <" << config.start_include << header << ">`" << 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_short_output(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;
if (! f.return_description.empty())
{
out << "][" << std::endl;
out << f.return_description << std::endl;
out << 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_member(std::vector<function> const& functions,
function_type type,
std::string const& title,
configuration const& config, std::ostream& out)
{
std::string returns = type == function_constructor ? "" : " [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_short_output(f, out);
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, 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
<< " // ..." << std::endl
<< "};" << 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] > 0)
{
quickbook_output_member(cos.functions, function_constructor, "Constructor", config, out);
}
if (counts[function_member] > 0)
{
quickbook_output_member(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;
}
#endif // QUICKBOOK_OUTPUT_HPP