mirror of
https://github.com/boostorg/quickbook.git
synced 2026-01-19 04:22:16 +00:00
Reformat
This commit is contained in:
1058
src/actions.cpp
1058
src/actions.cpp
File diff suppressed because it is too large
Load Diff
175
src/actions.hpp
175
src/actions.hpp
@@ -12,51 +12,59 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/spirit/include/classic_parser.hpp>
|
||||
#include "fwd.hpp"
|
||||
#include "iterator.hpp"
|
||||
#include "scoped.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "values.hpp"
|
||||
#include "scoped.hpp"
|
||||
#include "iterator.hpp"
|
||||
#include <boost/spirit/include/classic_parser.hpp>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
namespace cl = boost::spirit::classic;
|
||||
|
||||
// Match if quickbook version is within range
|
||||
struct quickbook_range : cl::parser<quickbook_range> {
|
||||
struct quickbook_range : cl::parser<quickbook_range>
|
||||
{
|
||||
explicit quickbook_range(unsigned lower_, unsigned upper_)
|
||||
: lower(lower_), upper(upper_) {}
|
||||
: lower(lower_), upper(upper_)
|
||||
{
|
||||
}
|
||||
|
||||
bool in_range() const;
|
||||
|
||||
|
||||
template <typename ScannerT>
|
||||
typename cl::parser_result<quickbook_range, ScannerT>::type
|
||||
parse(ScannerT const& scan) const
|
||||
typename cl::parser_result<quickbook_range, ScannerT>::type parse(
|
||||
ScannerT const& scan) const
|
||||
{
|
||||
return in_range() ? scan.empty_match() : scan.no_match();
|
||||
}
|
||||
|
||||
unsigned lower, upper;
|
||||
};
|
||||
|
||||
inline quickbook_range qbk_ver(unsigned lower, unsigned upper = 999u) {
|
||||
|
||||
inline quickbook_range qbk_ver(unsigned lower, unsigned upper = 999u)
|
||||
{
|
||||
return quickbook_range(lower, upper);
|
||||
}
|
||||
|
||||
// Match if in strict mode.
|
||||
struct quickbook_strict : cl::parser<quickbook_strict> {
|
||||
explicit quickbook_strict(quickbook::state& state_, bool positive_ = true)
|
||||
: state(state_), positive(positive_) {}
|
||||
struct quickbook_strict : cl::parser<quickbook_strict>
|
||||
{
|
||||
explicit quickbook_strict(
|
||||
quickbook::state& state_, bool positive_ = true)
|
||||
: state(state_), positive(positive_)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_strict_checking() const;
|
||||
|
||||
template <typename ScannerT>
|
||||
typename cl::parser_result<quickbook_range, ScannerT>::type
|
||||
parse(ScannerT const& scan) const
|
||||
typename cl::parser_result<quickbook_range, ScannerT>::type parse(
|
||||
ScannerT const& scan) const
|
||||
{
|
||||
return is_strict_checking() == positive ?
|
||||
scan.empty_match() : scan.no_match();
|
||||
return is_strict_checking() == positive ? scan.empty_match()
|
||||
: scan.no_match();
|
||||
}
|
||||
|
||||
quickbook_strict operator~() const
|
||||
@@ -68,22 +76,28 @@ namespace quickbook
|
||||
bool positive;
|
||||
};
|
||||
|
||||
inline quickbook_strict qbk_strict(quickbook::state& state, unsigned lower = 999u) {
|
||||
inline quickbook_strict qbk_strict(
|
||||
quickbook::state& state, unsigned lower = 999u)
|
||||
{
|
||||
return quickbook_strict(state, lower);
|
||||
}
|
||||
|
||||
// Throws load_error
|
||||
int load_snippets(fs::path const& file, std::vector<template_symbol>& storage,
|
||||
std::string const& extension, value::tag_type load_type);
|
||||
int load_snippets(
|
||||
fs::path const& file,
|
||||
std::vector<template_symbol>& storage,
|
||||
std::string const& extension,
|
||||
value::tag_type load_type);
|
||||
|
||||
struct error_message_action
|
||||
{
|
||||
// Prints an error message to std::cerr
|
||||
|
||||
explicit error_message_action(quickbook::state& state_, std::string const& message_)
|
||||
: state(state_)
|
||||
, message(message_)
|
||||
{}
|
||||
explicit error_message_action(
|
||||
quickbook::state& state_, std::string const& message_)
|
||||
: state(state_), message(message_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(parse_iterator, parse_iterator) const;
|
||||
|
||||
@@ -95,8 +109,7 @@ namespace quickbook
|
||||
{
|
||||
// Prints an error message to std::cerr
|
||||
|
||||
explicit error_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
explicit error_action(quickbook::state& state_) : state(state_) {}
|
||||
|
||||
void operator()(parse_iterator first, parse_iterator last) const;
|
||||
|
||||
@@ -110,8 +123,7 @@ namespace quickbook
|
||||
|
||||
struct element_action
|
||||
{
|
||||
explicit element_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
explicit element_action(quickbook::state& state_) : state(state_) {}
|
||||
|
||||
void operator()(parse_iterator, parse_iterator) const;
|
||||
|
||||
@@ -123,8 +135,7 @@ namespace quickbook
|
||||
// implicit paragraphs
|
||||
// doesn't output the paragraph if it's only whitespace.
|
||||
|
||||
explicit paragraph_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
explicit paragraph_action(quickbook::state& state_) : state(state_) {}
|
||||
|
||||
void operator()() const;
|
||||
void operator()(parse_iterator, parse_iterator) const { (*this)(); }
|
||||
@@ -137,8 +148,9 @@ namespace quickbook
|
||||
// implicit paragraphs
|
||||
// doesn't output the paragraph if it's only whitespace.
|
||||
|
||||
explicit explicit_list_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
explicit explicit_list_action(quickbook::state& state_) : state(state_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()() const;
|
||||
void operator()(parse_iterator, parse_iterator) const { (*this)(); }
|
||||
@@ -148,8 +160,7 @@ namespace quickbook
|
||||
|
||||
struct phrase_end_action
|
||||
{
|
||||
explicit phrase_end_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
explicit phrase_end_action(quickbook::state& state_) : state(state_) {}
|
||||
|
||||
void operator()() const;
|
||||
void operator()(parse_iterator, parse_iterator) const { (*this)(); }
|
||||
@@ -161,8 +172,9 @@ namespace quickbook
|
||||
{
|
||||
// Handles simple text formats
|
||||
|
||||
explicit simple_phrase_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
explicit simple_phrase_action(quickbook::state& state_) : state(state_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(char) const;
|
||||
|
||||
@@ -171,8 +183,7 @@ namespace quickbook
|
||||
|
||||
struct cond_phrase_push : scoped_action_base
|
||||
{
|
||||
cond_phrase_push(quickbook::state& x)
|
||||
: state(x) {}
|
||||
cond_phrase_push(quickbook::state& x) : state(x) {}
|
||||
|
||||
bool start();
|
||||
void cleanup();
|
||||
@@ -216,10 +227,12 @@ namespace quickbook
|
||||
|
||||
quickbook::state& state;
|
||||
};
|
||||
|
||||
|
||||
struct escape_unicode_action
|
||||
{
|
||||
explicit escape_unicode_action(quickbook::state& state_) : state(state_) {}
|
||||
explicit escape_unicode_action(quickbook::state& state_) : state(state_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(parse_iterator first, parse_iterator last) const;
|
||||
|
||||
@@ -235,24 +248,29 @@ namespace quickbook
|
||||
quickbook::state& state;
|
||||
};
|
||||
|
||||
struct element_id_warning_action
|
||||
{
|
||||
struct element_id_warning_action
|
||||
{
|
||||
explicit element_id_warning_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
: state(state_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(parse_iterator first, parse_iterator last) const;
|
||||
|
||||
quickbook::state& state;
|
||||
};
|
||||
};
|
||||
|
||||
// Returns the doc_type, or an empty string if there isn't one.
|
||||
std::string pre(quickbook::state& state, parse_iterator pos, value include_doc_id, bool nested_file);
|
||||
std::string pre(
|
||||
quickbook::state& state,
|
||||
parse_iterator pos,
|
||||
value include_doc_id,
|
||||
bool nested_file);
|
||||
void post(quickbook::state& state, std::string const& doc_type);
|
||||
|
||||
struct to_value_scoped_action : scoped_action_base
|
||||
{
|
||||
to_value_scoped_action(quickbook::state& state_)
|
||||
: state(state_) {}
|
||||
to_value_scoped_action(quickbook::state& state_) : state(state_) {}
|
||||
|
||||
bool start(value::tag_type = value::default_tag);
|
||||
void success(parse_iterator, parse_iterator);
|
||||
@@ -267,29 +285,30 @@ namespace quickbook
|
||||
//
|
||||
// Action for calling a member function taking two parse iterators.
|
||||
|
||||
template <typename T>
|
||||
struct member_action
|
||||
template <typename T> struct member_action
|
||||
{
|
||||
typedef void(T::*member_function)(parse_iterator, parse_iterator);
|
||||
typedef void (T::*member_function)(parse_iterator, parse_iterator);
|
||||
|
||||
T& l;
|
||||
member_function mf;
|
||||
|
||||
explicit member_action(T& l_, member_function mf_) : l(l_), mf(mf_) {}
|
||||
|
||||
void operator()(parse_iterator first, parse_iterator last) const {
|
||||
void operator()(parse_iterator first, parse_iterator last) const
|
||||
{
|
||||
(l.*mf)(first, last);
|
||||
}
|
||||
};
|
||||
|
||||
// member_action1
|
||||
//
|
||||
// Action for calling a member function taking two parse iterators and a value.
|
||||
// Action for calling a member function taking two parse iterators and a
|
||||
// value.
|
||||
|
||||
template <typename T, typename Arg1>
|
||||
struct member_action1
|
||||
template <typename T, typename Arg1> struct member_action1
|
||||
{
|
||||
typedef void(T::*member_function)(parse_iterator, parse_iterator, Arg1);
|
||||
typedef void (T::*member_function)(
|
||||
parse_iterator, parse_iterator, Arg1);
|
||||
|
||||
T& l;
|
||||
member_function mf;
|
||||
@@ -301,61 +320,59 @@ namespace quickbook
|
||||
member_action1 a;
|
||||
Arg1 value;
|
||||
|
||||
explicit impl(member_action1& a_, Arg1 value_) :
|
||||
a(a_), value(value_)
|
||||
{}
|
||||
explicit impl(member_action1& a_, Arg1 value_)
|
||||
: a(a_), value(value_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(parse_iterator first, parse_iterator last) const {
|
||||
void operator()(parse_iterator first, parse_iterator last) const
|
||||
{
|
||||
(a.l.*a.mf)(first, last, value);
|
||||
}
|
||||
};
|
||||
|
||||
impl operator()(Arg1 a1) {
|
||||
return impl(*this, a1);
|
||||
}
|
||||
impl operator()(Arg1 a1) { return impl(*this, a1); }
|
||||
};
|
||||
|
||||
// member_action_value
|
||||
//
|
||||
// Action for calling a unary member function.
|
||||
|
||||
template <typename T, typename Value>
|
||||
struct member_action_value
|
||||
template <typename T, typename Value> struct member_action_value
|
||||
{
|
||||
typedef void(T::*member_function)(Value);
|
||||
typedef void (T::*member_function)(Value);
|
||||
|
||||
T& l;
|
||||
member_function mf;
|
||||
|
||||
explicit member_action_value(T& l_, member_function mf_) : l(l_), mf(mf_) {}
|
||||
|
||||
void operator()(Value v) const {
|
||||
(l.*mf)(v);
|
||||
explicit member_action_value(T& l_, member_function mf_)
|
||||
: l(l_), mf(mf_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(Value v) const { (l.*mf)(v); }
|
||||
};
|
||||
|
||||
// member_action_value
|
||||
//
|
||||
// Action for calling a unary member function with a fixed value.
|
||||
|
||||
template <typename T, typename Value>
|
||||
struct member_action_fixed_value
|
||||
template <typename T, typename Value> struct member_action_fixed_value
|
||||
{
|
||||
typedef void(T::*member_function)(Value);
|
||||
typedef void (T::*member_function)(Value);
|
||||
|
||||
T& l;
|
||||
member_function mf;
|
||||
Value v;
|
||||
|
||||
explicit member_action_fixed_value(T& l_, member_function mf_, Value v_) : l(l_), mf(mf_), v(v_) {}
|
||||
|
||||
void operator()() const {
|
||||
(l.*mf)(v);
|
||||
explicit member_action_fixed_value(T& l_, member_function mf_, Value v_)
|
||||
: l(l_), mf(mf_), v(v_)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(parse_iterator, parse_iterator) const {
|
||||
(l.*mf)(v);
|
||||
}
|
||||
void operator()() const { (l.*mf)(v); }
|
||||
|
||||
void operator()(parse_iterator, parse_iterator) const { (l.*mf)(v); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "utils.hpp"
|
||||
#include "state.hpp"
|
||||
#include "actions.hpp"
|
||||
#include "grammar_impl.hpp"
|
||||
#include "block_tags.hpp"
|
||||
#include "template_tags.hpp"
|
||||
#include <boost/spirit/include/classic_assign_actor.hpp>
|
||||
#include <boost/spirit/include/classic_if.hpp>
|
||||
#include <boost/spirit/include/classic_clear_actor.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include <boost/spirit/include/classic_if.hpp>
|
||||
#include <boost/spirit/include/phoenix1_casts.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include "actions.hpp"
|
||||
#include "block_tags.hpp"
|
||||
#include "grammar_impl.hpp"
|
||||
#include "state.hpp"
|
||||
#include "template_tags.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -27,22 +27,18 @@ namespace quickbook
|
||||
|
||||
struct block_element_grammar_local
|
||||
{
|
||||
cl::rule<scanner>
|
||||
heading, inner_block, inner_phrase, def_macro,
|
||||
table, table_title, table_row, variablelist,
|
||||
varlistentry, varlistterm, list, cell,
|
||||
preformatted, begin_section, end_section,
|
||||
xinclude, include, include_filename,
|
||||
template_, template_id, template_formal_arg,
|
||||
template_body, identifier, import,
|
||||
element_id,
|
||||
same_line;
|
||||
cl::rule<scanner> heading, inner_block, inner_phrase, def_macro, table,
|
||||
table_title, table_row, variablelist, varlistentry, varlistterm,
|
||||
list, cell, preformatted, begin_section, end_section, xinclude,
|
||||
include, include_filename, template_, template_id,
|
||||
template_formal_arg, template_body, identifier, import, element_id,
|
||||
same_line;
|
||||
};
|
||||
|
||||
void quickbook_grammar::impl::init_block_elements()
|
||||
{
|
||||
block_element_grammar_local& local = cleanup_.add(
|
||||
new block_element_grammar_local);
|
||||
block_element_grammar_local& local =
|
||||
cleanup_.add(new block_element_grammar_local);
|
||||
|
||||
// Actions
|
||||
error_action error(state);
|
||||
|
||||
@@ -30,14 +30,17 @@ namespace quickbook
|
||||
// should be okay for an object to depend on something that was previously
|
||||
// added.
|
||||
|
||||
namespace detail { struct cleanup_node; }
|
||||
namespace detail
|
||||
{
|
||||
struct cleanup_node;
|
||||
}
|
||||
struct cleanup
|
||||
{
|
||||
cleanup() : first_(0) {}
|
||||
~cleanup();
|
||||
template <typename T> T& add(T*);
|
||||
|
||||
private:
|
||||
private:
|
||||
detail::cleanup_node* first_;
|
||||
|
||||
cleanup& operator=(cleanup const&);
|
||||
@@ -46,38 +49,42 @@ namespace quickbook
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
void delete_impl(void* ptr) {
|
||||
template <typename T> void delete_impl(void* ptr)
|
||||
{
|
||||
delete static_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
|
||||
struct cleanup_node
|
||||
{
|
||||
void* ptr_;
|
||||
void (*del_)(void*);
|
||||
cleanup_node* next_;
|
||||
|
||||
|
||||
cleanup_node() : ptr_(0), del_(0), next_(0) {}
|
||||
cleanup_node(void* ptr, void (*del)(void* x))
|
||||
: ptr_(ptr), del_(del), next_(0) {}
|
||||
~cleanup_node() {
|
||||
if(ptr_) del_(ptr_);
|
||||
: ptr_(ptr), del_(del), next_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void move_assign(cleanup_node& n) {
|
||||
~cleanup_node()
|
||||
{
|
||||
if (ptr_) del_(ptr_);
|
||||
}
|
||||
|
||||
void move_assign(cleanup_node& n)
|
||||
{
|
||||
ptr_ = n.ptr_;
|
||||
del_ = n.del_;
|
||||
n.ptr_ = 0;
|
||||
n.del_ = 0;
|
||||
}
|
||||
private:
|
||||
|
||||
private:
|
||||
cleanup_node(cleanup_node const&);
|
||||
cleanup_node& operator=(cleanup_node const&);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& cleanup::add(T* ptr)
|
||||
|
||||
template <typename T> T& cleanup::add(T* ptr)
|
||||
{
|
||||
detail::cleanup_node n(ptr, &detail::delete_impl<T>);
|
||||
detail::cleanup_node* n2 = new detail::cleanup_node();
|
||||
@@ -87,8 +94,9 @@ namespace quickbook
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline cleanup::~cleanup() {
|
||||
while(first_) {
|
||||
inline cleanup::~cleanup()
|
||||
{
|
||||
while (first_) {
|
||||
detail::cleanup_node* to_delete = first_;
|
||||
first_ = first_->next_;
|
||||
delete to_delete;
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/spirit/include/classic_actor.hpp>
|
||||
#include <boost/spirit/include/classic_confix.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include "block_tags.hpp"
|
||||
#include "template_stack.hpp"
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include "actions.hpp"
|
||||
#include "state.hpp"
|
||||
#include "values.hpp"
|
||||
#include "block_tags.hpp"
|
||||
#include "files.hpp"
|
||||
#include "state.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "template_stack.hpp"
|
||||
#include "values.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -26,9 +26,10 @@ namespace quickbook
|
||||
|
||||
struct code_snippet_actions
|
||||
{
|
||||
code_snippet_actions(std::vector<template_symbol>& storage_,
|
||||
file_ptr source_file_,
|
||||
char const* source_type_)
|
||||
code_snippet_actions(
|
||||
std::vector<template_symbol>& storage_,
|
||||
file_ptr source_file_,
|
||||
char const* source_type_)
|
||||
: last_code_pos(source_file_->source().begin())
|
||||
, in_code(false)
|
||||
, snippet_stack()
|
||||
@@ -49,26 +50,22 @@ namespace quickbook
|
||||
void end_snippet(string_iterator first, string_iterator last);
|
||||
void end_snippet_impl(string_iterator);
|
||||
void end_file(string_iterator, string_iterator);
|
||||
|
||||
|
||||
void append_code(string_iterator first, string_iterator last);
|
||||
void close_code();
|
||||
|
||||
struct snippet_data
|
||||
{
|
||||
snippet_data(std::string const& id_)
|
||||
: id(id_)
|
||||
, start_code(false)
|
||||
{}
|
||||
|
||||
snippet_data(std::string const& id_) : id(id_), start_code(false) {}
|
||||
|
||||
std::string id;
|
||||
bool start_code;
|
||||
string_iterator source_pos;
|
||||
mapped_file_builder::pos_type start_pos;
|
||||
boost::shared_ptr<snippet_data> next;
|
||||
};
|
||||
|
||||
void push_snippet_data(std::string const& id,
|
||||
string_iterator pos)
|
||||
|
||||
void push_snippet_data(std::string const& id, string_iterator pos)
|
||||
{
|
||||
boost::shared_ptr<snippet_data> new_snippet(new snippet_data(id));
|
||||
new_snippet->next = snippet_stack;
|
||||
@@ -101,16 +98,15 @@ namespace quickbook
|
||||
: cl::grammar<python_code_snippet_grammar>
|
||||
{
|
||||
typedef code_snippet_actions actions_type;
|
||||
|
||||
python_code_snippet_grammar(actions_type & actions_)
|
||||
: actions(actions_)
|
||||
{}
|
||||
|
||||
template <typename Scanner>
|
||||
struct definition
|
||||
python_code_snippet_grammar(actions_type& actions_) : actions(actions_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Scanner> struct definition
|
||||
{
|
||||
typedef code_snippet_actions actions_type;
|
||||
|
||||
|
||||
definition(python_code_snippet_grammar const& self)
|
||||
{
|
||||
// clang-format off
|
||||
@@ -195,28 +191,22 @@ namespace quickbook
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
cl::rule<Scanner>
|
||||
start_, identifier, code_elements, start_snippet, end_snippet,
|
||||
escaped_comment, pass_thru_comment, ignore;
|
||||
cl::rule<Scanner> start_, identifier, code_elements, start_snippet,
|
||||
end_snippet, escaped_comment, pass_thru_comment, ignore;
|
||||
|
||||
cl::rule<Scanner> const&
|
||||
start() const { return start_; }
|
||||
cl::rule<Scanner> const& start() const { return start_; }
|
||||
};
|
||||
|
||||
actions_type& actions;
|
||||
};
|
||||
};
|
||||
|
||||
struct cpp_code_snippet_grammar
|
||||
: cl::grammar<cpp_code_snippet_grammar>
|
||||
struct cpp_code_snippet_grammar : cl::grammar<cpp_code_snippet_grammar>
|
||||
{
|
||||
typedef code_snippet_actions actions_type;
|
||||
|
||||
cpp_code_snippet_grammar(actions_type & actions_)
|
||||
: actions(actions_)
|
||||
{}
|
||||
|
||||
template <typename Scanner>
|
||||
struct definition
|
||||
cpp_code_snippet_grammar(actions_type& actions_) : actions(actions_) {}
|
||||
|
||||
template <typename Scanner> struct definition
|
||||
{
|
||||
definition(cpp_code_snippet_grammar const& self)
|
||||
{
|
||||
@@ -330,54 +320,58 @@ namespace quickbook
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
cl::rule<Scanner>
|
||||
start_, identifier, code_elements, start_snippet, end_snippet,
|
||||
escaped_comment, pass_thru_comment, ignore;
|
||||
cl::rule<Scanner> start_, identifier, code_elements, start_snippet,
|
||||
end_snippet, escaped_comment, pass_thru_comment, ignore;
|
||||
|
||||
cl::rule<Scanner> const&
|
||||
start() const { return start_; }
|
||||
cl::rule<Scanner> const& start() const { return start_; }
|
||||
};
|
||||
|
||||
actions_type& actions;
|
||||
};
|
||||
|
||||
int load_snippets(
|
||||
fs::path const& filename
|
||||
, std::vector<template_symbol>& storage // snippets are stored in a
|
||||
// vector of template_symbols
|
||||
, std::string const& extension
|
||||
, value::tag_type load_type)
|
||||
fs::path const& filename,
|
||||
std::vector<template_symbol>& storage // snippets are stored in a
|
||||
// vector of template_symbols
|
||||
,
|
||||
std::string const& extension,
|
||||
value::tag_type load_type)
|
||||
{
|
||||
assert(load_type == block_tags::include ||
|
||||
assert(
|
||||
load_type == block_tags::include ||
|
||||
load_type == block_tags::import);
|
||||
|
||||
bool is_python = extension == ".py" || extension == ".jam";
|
||||
code_snippet_actions a(storage, load(filename, qbk_version_n), is_python ? "[python]" : "[c++]");
|
||||
code_snippet_actions a(
|
||||
storage, load(filename, qbk_version_n),
|
||||
is_python ? "[python]" : "[c++]");
|
||||
|
||||
string_iterator first(a.source_file->source().begin());
|
||||
string_iterator last(a.source_file->source().end());
|
||||
|
||||
cl::parse_info<string_iterator> info;
|
||||
|
||||
if(is_python) {
|
||||
info = boost::spirit::classic::parse(first, last, python_code_snippet_grammar(a));
|
||||
if (is_python) {
|
||||
info = boost::spirit::classic::parse(
|
||||
first, last, python_code_snippet_grammar(a));
|
||||
}
|
||||
else {
|
||||
info = boost::spirit::classic::parse(first, last, cpp_code_snippet_grammar(a));
|
||||
info = boost::spirit::classic::parse(
|
||||
first, last, cpp_code_snippet_grammar(a));
|
||||
}
|
||||
|
||||
assert(info.full);
|
||||
return a.error_count;
|
||||
}
|
||||
|
||||
void code_snippet_actions::append_code(string_iterator first, string_iterator last)
|
||||
void code_snippet_actions::append_code(
|
||||
string_iterator first, string_iterator last)
|
||||
{
|
||||
assert(last_code_pos <= first);
|
||||
|
||||
if(snippet_stack) {
|
||||
if (snippet_stack) {
|
||||
if (last_code_pos != first) {
|
||||
if (!in_code)
|
||||
{
|
||||
if (!in_code) {
|
||||
content.add_at_pos("\n\n", last_code_pos);
|
||||
content.add_at_pos(source_type, last_code_pos);
|
||||
content.add_at_pos("```\n", last_code_pos);
|
||||
@@ -385,19 +379,19 @@ namespace quickbook
|
||||
in_code = true;
|
||||
}
|
||||
|
||||
content.add(quickbook::string_view(last_code_pos, first - last_code_pos));
|
||||
content.add(quickbook::string_view(
|
||||
last_code_pos, first - last_code_pos));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
last_code_pos = last;
|
||||
}
|
||||
|
||||
|
||||
void code_snippet_actions::close_code()
|
||||
{
|
||||
if (!snippet_stack) return;
|
||||
|
||||
if (in_code)
|
||||
{
|
||||
|
||||
if (in_code) {
|
||||
content.add_at_pos("\n```\n\n", last_code_pos);
|
||||
in_code = false;
|
||||
}
|
||||
@@ -409,13 +403,13 @@ namespace quickbook
|
||||
mark_end = last;
|
||||
}
|
||||
|
||||
void code_snippet_actions::pass_thru(string_iterator first, string_iterator last)
|
||||
void code_snippet_actions::pass_thru(
|
||||
string_iterator first, string_iterator last)
|
||||
{
|
||||
if(!snippet_stack) return;
|
||||
if (!snippet_stack) return;
|
||||
append_code(first, last);
|
||||
|
||||
if (!in_code)
|
||||
{
|
||||
if (!in_code) {
|
||||
content.add_at_pos("\n\n", first);
|
||||
content.add_at_pos(source_type, first);
|
||||
content.add_at_pos("```\n", first);
|
||||
@@ -425,58 +419,57 @@ namespace quickbook
|
||||
content.add(quickbook::string_view(mark_begin, mark_end - mark_begin));
|
||||
}
|
||||
|
||||
void code_snippet_actions::escaped_comment(string_iterator first, string_iterator last)
|
||||
void code_snippet_actions::escaped_comment(
|
||||
string_iterator first, string_iterator last)
|
||||
{
|
||||
append_code(first, last);
|
||||
close_code();
|
||||
|
||||
if (mark_begin != mark_end)
|
||||
{
|
||||
if (!snippet_stack)
|
||||
{
|
||||
if (mark_begin != mark_end) {
|
||||
if (!snippet_stack) {
|
||||
start_snippet_impl("!", first);
|
||||
}
|
||||
|
||||
|
||||
snippet_data& snippet = *snippet_stack;
|
||||
|
||||
content.add_at_pos("\n", mark_begin);
|
||||
content.unindent_and_add(quickbook::string_view(mark_begin, mark_end - mark_begin));
|
||||
content.unindent_and_add(
|
||||
quickbook::string_view(mark_begin, mark_end - mark_begin));
|
||||
|
||||
if (snippet.id == "!")
|
||||
{
|
||||
if (snippet.id == "!") {
|
||||
end_snippet_impl(last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void code_snippet_actions::start_snippet(string_iterator first, string_iterator last)
|
||||
void code_snippet_actions::start_snippet(
|
||||
string_iterator first, string_iterator last)
|
||||
{
|
||||
append_code(first, last);
|
||||
start_snippet_impl(std::string(mark_begin, mark_end), first);
|
||||
}
|
||||
|
||||
void code_snippet_actions::end_snippet(string_iterator first, string_iterator last)
|
||||
void code_snippet_actions::end_snippet(
|
||||
string_iterator first, string_iterator last)
|
||||
{
|
||||
append_code(first, last);
|
||||
|
||||
if(!snippet_stack) {
|
||||
if (!snippet_stack) {
|
||||
if (qbk_version_n >= 106u) {
|
||||
detail::outerr(source_file, first)
|
||||
<< "Mismatched end snippet."
|
||||
<< std::endl;
|
||||
<< "Mismatched end snippet." << std::endl;
|
||||
++error_count;
|
||||
}
|
||||
else {
|
||||
detail::outwarn(source_file, first)
|
||||
<< "Mismatched end snippet."
|
||||
<< std::endl;
|
||||
<< "Mismatched end snippet." << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
end_snippet_impl(first);
|
||||
}
|
||||
|
||||
|
||||
void code_snippet_actions::end_file(string_iterator, string_iterator pos)
|
||||
{
|
||||
append_code(pos, pos);
|
||||
@@ -485,26 +478,22 @@ namespace quickbook
|
||||
while (snippet_stack) {
|
||||
if (qbk_version_n >= 106u) {
|
||||
detail::outerr(source_file->path)
|
||||
<< "Unclosed snippet '"
|
||||
<< snippet_stack->id
|
||||
<< "'"
|
||||
<< "Unclosed snippet '" << snippet_stack->id << "'"
|
||||
<< std::endl;
|
||||
++error_count;
|
||||
}
|
||||
else {
|
||||
detail::outwarn(source_file->path)
|
||||
<< "Unclosed snippet '"
|
||||
<< snippet_stack->id
|
||||
<< "'"
|
||||
<< "Unclosed snippet '" << snippet_stack->id << "'"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
end_snippet_impl(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void code_snippet_actions::start_snippet_impl(std::string const& id,
|
||||
string_iterator position)
|
||||
void code_snippet_actions::start_snippet_impl(
|
||||
std::string const& id, string_iterator position)
|
||||
{
|
||||
push_snippet_data(id, position);
|
||||
}
|
||||
@@ -531,8 +520,10 @@ namespace quickbook
|
||||
|
||||
file_ptr body = f.release();
|
||||
|
||||
storage.push_back(template_symbol(snippet->id, params,
|
||||
qbk_value(body, body->source().begin(), body->source().end(),
|
||||
storage.push_back(template_symbol(
|
||||
snippet->id, params,
|
||||
qbk_value(
|
||||
body, body->source().begin(), body->source().end(),
|
||||
template_tags::snippet)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,48 +13,40 @@ namespace quickbook
|
||||
{
|
||||
string_stream::string_stream()
|
||||
: buffer_ptr(new std::string())
|
||||
, stream_ptr(new ostream(boost::iostreams::back_inserter(*buffer_ptr.get())))
|
||||
{}
|
||||
, stream_ptr(
|
||||
new ostream(boost::iostreams::back_inserter(*buffer_ptr.get())))
|
||||
{
|
||||
}
|
||||
|
||||
string_stream::string_stream(string_stream const& other)
|
||||
: buffer_ptr(other.buffer_ptr)
|
||||
, stream_ptr(other.stream_ptr)
|
||||
{}
|
||||
|
||||
string_stream&
|
||||
string_stream::operator=(string_stream const& other)
|
||||
: buffer_ptr(other.buffer_ptr), stream_ptr(other.stream_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
string_stream& string_stream::operator=(string_stream const& other)
|
||||
{
|
||||
buffer_ptr = other.buffer_ptr;
|
||||
stream_ptr = other.stream_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
collector::collector()
|
||||
: main(default_)
|
||||
, top(default_)
|
||||
{
|
||||
}
|
||||
|
||||
collector::collector(string_stream& out)
|
||||
: main(out)
|
||||
, top(out)
|
||||
{
|
||||
}
|
||||
|
||||
collector::collector() : main(default_), top(default_) {}
|
||||
|
||||
collector::collector(string_stream& out) : main(out), top(out) {}
|
||||
|
||||
collector::~collector()
|
||||
{
|
||||
BOOST_ASSERT(streams.empty()); // assert there are no more pushes than pops!!!
|
||||
BOOST_ASSERT(
|
||||
streams.empty()); // assert there are no more pushes than pops!!!
|
||||
}
|
||||
|
||||
void
|
||||
collector::push()
|
||||
|
||||
void collector::push()
|
||||
{
|
||||
streams.push(string_stream());
|
||||
top = boost::ref(streams.top());
|
||||
}
|
||||
|
||||
void
|
||||
collector::pop()
|
||||
|
||||
void collector::pop()
|
||||
{
|
||||
BOOST_ASSERT(!streams.empty());
|
||||
streams.pop();
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_COLLECTOR_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_COLLECTOR_HPP
|
||||
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
#include <boost/iostreams/device/back_inserter.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -32,16 +32,10 @@ namespace quickbook
|
||||
stream_ptr->flush();
|
||||
return *buffer_ptr.get();
|
||||
}
|
||||
|
||||
std::ostream& get() const
|
||||
{
|
||||
return *stream_ptr.get();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
buffer_ptr->clear();
|
||||
}
|
||||
|
||||
std::ostream& get() const { return *stream_ptr.get(); }
|
||||
|
||||
void clear() { buffer_ptr->clear(); }
|
||||
|
||||
void swap(std::string& other)
|
||||
{
|
||||
@@ -55,8 +49,7 @@ namespace quickbook
|
||||
*buffer_ptr.get() += other;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
boost::shared_ptr<std::string> buffer_ptr;
|
||||
boost::shared_ptr<ostream> stream_ptr;
|
||||
};
|
||||
@@ -66,53 +59,35 @@ namespace quickbook
|
||||
collector();
|
||||
collector(string_stream& out);
|
||||
~collector();
|
||||
|
||||
|
||||
void push();
|
||||
void pop();
|
||||
|
||||
std::ostream& get() const
|
||||
{
|
||||
return top.get().get();
|
||||
}
|
||||
|
||||
std::string const& str() const
|
||||
{
|
||||
return top.get().str();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
top.get().clear();
|
||||
}
|
||||
|
||||
void swap(std::string& other)
|
||||
{
|
||||
top.get().swap(other);
|
||||
}
|
||||
std::ostream& get() const { return top.get().get(); }
|
||||
|
||||
void append(std::string const& other)
|
||||
{
|
||||
top.get().append(other);
|
||||
}
|
||||
std::string const& str() const { return top.get().str(); }
|
||||
|
||||
private:
|
||||
void clear() { top.get().clear(); }
|
||||
|
||||
void swap(std::string& other) { top.get().swap(other); }
|
||||
|
||||
void append(std::string const& other) { top.get().append(other); }
|
||||
|
||||
private:
|
||||
std::stack<string_stream> streams;
|
||||
boost::reference_wrapper<string_stream> main;
|
||||
boost::reference_wrapper<string_stream> top;
|
||||
string_stream default_;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline collector&
|
||||
operator<<(collector& out, T const& val)
|
||||
inline collector& operator<<(collector& out, T const& val)
|
||||
{
|
||||
out.get() << val;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline collector&
|
||||
operator<<(collector& out, std::string const& val)
|
||||
inline collector& operator<<(collector& out, std::string const& val)
|
||||
{
|
||||
out.append(val);
|
||||
return out;
|
||||
@@ -120,4 +95,3 @@ namespace quickbook
|
||||
}
|
||||
|
||||
#endif // BOOST_SPIRIT_QUICKBOOK_COLLECTOR_HPP
|
||||
|
||||
|
||||
@@ -7,29 +7,25 @@
|
||||
=============================================================================*/
|
||||
|
||||
#include "dependency_tracker.hpp"
|
||||
#include "path.hpp"
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include "path.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
static char const* control_escapes[16] = {
|
||||
"\\000", "\\001", "\\002", "\\003",
|
||||
"\\004", "\\005", "\\006", "\\a",
|
||||
"\\b", "\\t", "\\n", "\\v",
|
||||
"\\f", "\\r", "\\016", "\\017"
|
||||
};
|
||||
"\\000", "\\001", "\\002", "\\003", "\\004", "\\005", "\\006", "\\a",
|
||||
"\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "\\016", "\\017"};
|
||||
|
||||
static std::string escaped_path(std::string const& generic)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(generic.size());
|
||||
|
||||
BOOST_FOREACH(char c, generic)
|
||||
{
|
||||
BOOST_FOREACH (char c, generic) {
|
||||
if (c >= 0 && c < 16) {
|
||||
result += control_escapes[(unsigned int) c];
|
||||
result += control_escapes[(unsigned int)c];
|
||||
}
|
||||
else if (c == '\\') {
|
||||
result += "\\\\";
|
||||
@@ -45,8 +41,8 @@ namespace quickbook
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string get_path(fs::path const& path,
|
||||
dependency_tracker::flags f)
|
||||
static std::string get_path(
|
||||
fs::path const& path, dependency_tracker::flags f)
|
||||
{
|
||||
std::string generic = quickbook::detail::path_to_generic(path);
|
||||
|
||||
@@ -57,29 +53,35 @@ namespace quickbook
|
||||
return generic;
|
||||
}
|
||||
|
||||
dependency_tracker::dependency_tracker() :
|
||||
dependencies(), glob_dependencies(),
|
||||
last_glob(glob_dependencies.end()) {}
|
||||
dependency_tracker::dependency_tracker()
|
||||
: dependencies()
|
||||
, glob_dependencies()
|
||||
, last_glob(glob_dependencies.end())
|
||||
{
|
||||
}
|
||||
|
||||
bool dependency_tracker::add_dependency(fs::path const& f) {
|
||||
bool dependency_tracker::add_dependency(fs::path const& f)
|
||||
{
|
||||
bool found = fs::exists(fs::status(f));
|
||||
dependencies[f] |= found;
|
||||
return found;
|
||||
}
|
||||
|
||||
void dependency_tracker::add_glob(fs::path const& f) {
|
||||
void dependency_tracker::add_glob(fs::path const& f)
|
||||
{
|
||||
std::pair<glob_list::iterator, bool> r = glob_dependencies.insert(
|
||||
std::make_pair(f, glob_list::mapped_type()));
|
||||
std::make_pair(f, glob_list::mapped_type()));
|
||||
last_glob = r.first;
|
||||
}
|
||||
|
||||
void dependency_tracker::add_glob_match(fs::path const& f) {
|
||||
void dependency_tracker::add_glob_match(fs::path const& f)
|
||||
{
|
||||
assert(last_glob != glob_dependencies.end());
|
||||
last_glob->second.insert(f);
|
||||
}
|
||||
|
||||
void dependency_tracker::write_dependencies(fs::path const& file_out,
|
||||
flags f)
|
||||
void dependency_tracker::write_dependencies(
|
||||
fs::path const& file_out, flags f)
|
||||
{
|
||||
fs::ofstream out(file_out);
|
||||
|
||||
@@ -93,23 +95,18 @@ namespace quickbook
|
||||
write_dependencies(out, f);
|
||||
}
|
||||
|
||||
void dependency_tracker::write_dependencies(std::ostream& out,
|
||||
flags f)
|
||||
void dependency_tracker::write_dependencies(std::ostream& out, flags f)
|
||||
{
|
||||
if (f & checked) {
|
||||
BOOST_FOREACH(dependency_list::value_type const& d, dependencies)
|
||||
{
|
||||
out << (d.second ? "+ " : "- ")
|
||||
<< get_path(d.first, f) << std::endl;
|
||||
BOOST_FOREACH (dependency_list::value_type const& d, dependencies) {
|
||||
out << (d.second ? "+ " : "- ") << get_path(d.first, f)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(glob_list::value_type const& g, glob_dependencies)
|
||||
{
|
||||
out << "g "
|
||||
<< get_path(g.first, f) << std::endl;
|
||||
BOOST_FOREACH (glob_list::value_type const& g, glob_dependencies) {
|
||||
out << "g " << get_path(g.first, f) << std::endl;
|
||||
|
||||
BOOST_FOREACH(fs::path const& p, g.second)
|
||||
{
|
||||
BOOST_FOREACH (fs::path const& p, g.second) {
|
||||
out << "+ " << get_path(p, f) << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -117,23 +114,19 @@ namespace quickbook
|
||||
else {
|
||||
std::set<std::string> paths;
|
||||
|
||||
BOOST_FOREACH(dependency_list::value_type const& d, dependencies)
|
||||
{
|
||||
BOOST_FOREACH (dependency_list::value_type const& d, dependencies) {
|
||||
if (d.second) {
|
||||
paths.insert(get_path(d.first, f));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(glob_list::value_type const& g, glob_dependencies)
|
||||
{
|
||||
BOOST_FOREACH(fs::path const& p, g.second)
|
||||
{
|
||||
BOOST_FOREACH (glob_list::value_type const& g, glob_dependencies) {
|
||||
BOOST_FOREACH (fs::path const& p, g.second) {
|
||||
paths.insert(get_path(p, f));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(std::string const& p, paths)
|
||||
{
|
||||
BOOST_FOREACH (std::string const& p, paths) {
|
||||
out << p << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
#if !defined(QUICKBOOK_DEPENDENCY_TRACKER_HPP)
|
||||
#define QUICKBOOK_DEPENDENCY_TRACKER_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <iosfwd>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
struct dependency_tracker {
|
||||
private:
|
||||
|
||||
struct dependency_tracker
|
||||
{
|
||||
private:
|
||||
typedef std::map<fs::path, bool> dependency_list;
|
||||
typedef std::map<fs::path, std::set<fs::path> > glob_list;
|
||||
|
||||
@@ -28,9 +28,9 @@ namespace quickbook
|
||||
glob_list glob_dependencies;
|
||||
glob_list::iterator last_glob;
|
||||
|
||||
public:
|
||||
|
||||
enum flags {
|
||||
public:
|
||||
enum flags
|
||||
{
|
||||
default_ = 0,
|
||||
checked = 1,
|
||||
escaped = 2
|
||||
|
||||
@@ -9,23 +9,24 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#include <sstream>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include "quickbook.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "files.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "state.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include "doc_info_tags.hpp"
|
||||
#include "document_state.hpp"
|
||||
#include "files.hpp"
|
||||
#include "path.hpp"
|
||||
#include "quickbook.hpp"
|
||||
#include "state.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
static void write_document_title(collector& out, value const& title, value const& version);
|
||||
|
||||
static void write_document_title(
|
||||
collector& out, value const& title, value const& version);
|
||||
|
||||
static std::string doc_info_output(value const& p, unsigned version)
|
||||
{
|
||||
if (qbk_version_n < version) {
|
||||
@@ -40,8 +41,8 @@ namespace quickbook
|
||||
|
||||
char const* doc_info_attribute_name(value::tag_type tag)
|
||||
{
|
||||
return doc_attributes::is_tag(tag) ? doc_attributes::name(tag) :
|
||||
doc_info_attributes::name(tag);
|
||||
return doc_attributes::is_tag(tag) ? doc_attributes::name(tag)
|
||||
: doc_info_attributes::name(tag);
|
||||
}
|
||||
|
||||
// Each docinfo attribute is stored in a value list, these are then stored
|
||||
@@ -49,29 +50,33 @@ namespace quickbook
|
||||
// values for an attribute tag.
|
||||
|
||||
// Expecting at most one attribute, with several values in the list.
|
||||
value consume_list(value_consumer& c, value::tag_type tag,
|
||||
std::vector<std::string>* duplicates)
|
||||
value consume_list(
|
||||
value_consumer& c,
|
||||
value::tag_type tag,
|
||||
std::vector<std::string>* duplicates)
|
||||
{
|
||||
value p;
|
||||
|
||||
int count = 0;
|
||||
while(c.check(tag)) {
|
||||
while (c.check(tag)) {
|
||||
p = c.consume();
|
||||
++count;
|
||||
}
|
||||
|
||||
if(count > 1) duplicates->push_back(doc_info_attribute_name(tag));
|
||||
if (count > 1) duplicates->push_back(doc_info_attribute_name(tag));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// Expecting at most one attribute, with a single value, so extract that
|
||||
// immediately.
|
||||
value consume_value_in_list(value_consumer& c, value::tag_type tag,
|
||||
std::vector<std::string>* duplicates)
|
||||
value consume_value_in_list(
|
||||
value_consumer& c,
|
||||
value::tag_type tag,
|
||||
std::vector<std::string>* duplicates)
|
||||
{
|
||||
value l = consume_list(c, tag, duplicates);
|
||||
if(l.empty()) return l;
|
||||
if (l.empty()) return l;
|
||||
|
||||
assert(l.is_list());
|
||||
value_consumer c2 = l;
|
||||
@@ -82,60 +87,67 @@ namespace quickbook
|
||||
}
|
||||
|
||||
// Any number of attributes, so stuff them into a vector.
|
||||
std::vector<value> consume_multiple_values(value_consumer& c, value::tag_type tag)
|
||||
std::vector<value> consume_multiple_values(
|
||||
value_consumer& c, value::tag_type tag)
|
||||
{
|
||||
std::vector<value> values;
|
||||
|
||||
while(c.check(tag)) {
|
||||
|
||||
while (c.check(tag)) {
|
||||
values.push_back(c.consume());
|
||||
}
|
||||
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
enum version_state { version_unknown, version_stable, version_dev };
|
||||
version_state classify_version(unsigned v) {
|
||||
return v < 100u ? version_unknown :
|
||||
v <= 107u ? version_stable :
|
||||
//v <= 107u ? version_dev :
|
||||
version_unknown;
|
||||
enum version_state
|
||||
{
|
||||
version_unknown,
|
||||
version_stable,
|
||||
version_dev
|
||||
};
|
||||
version_state classify_version(unsigned v)
|
||||
{
|
||||
return v < 100u ? version_unknown
|
||||
: v <= 107u ? version_stable :
|
||||
// v <= 107u ? version_dev :
|
||||
version_unknown;
|
||||
}
|
||||
|
||||
unsigned get_version(quickbook::state& state, bool using_docinfo,
|
||||
value version)
|
||||
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();
|
||||
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 (classify_version(result) == version_unknown)
|
||||
{
|
||||
result =
|
||||
((unsigned)major_verison * 100) + (unsigned)minor_verison;
|
||||
|
||||
if (classify_version(result) == version_unknown) {
|
||||
detail::outerr(state.current_file->path)
|
||||
<< "Unknown version: "
|
||||
<< major_verison
|
||||
<< "."
|
||||
<< minor_verison
|
||||
<< std::endl;
|
||||
<< "Unknown version: " << major_verison << "."
|
||||
<< minor_verison << std::endl;
|
||||
++state.error_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string pre(quickbook::state& state, parse_iterator pos,
|
||||
value include_doc_id, bool nested_file)
|
||||
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.
|
||||
@@ -147,32 +159,30 @@ namespace quickbook
|
||||
|
||||
// Skip over invalid attributes
|
||||
|
||||
while (values.check(value::default_tag)) values.consume();
|
||||
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 = values.consume(doc_info_tags::type).get_quickbook().to_s();
|
||||
if (values.check(doc_info_tags::type)) {
|
||||
doc_type =
|
||||
values.consume(doc_info_tags::type).get_quickbook().to_s();
|
||||
doc_title = values.consume(doc_info_tags::title);
|
||||
use_doc_info = !nested_file || qbk_version_n >= 106u;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!nested_file)
|
||||
{
|
||||
else {
|
||||
if (!nested_file) {
|
||||
detail::outerr(state.current_file, pos.base())
|
||||
<< "No doc_info block."
|
||||
<< std::endl;
|
||||
<< "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_title = qbk_value(
|
||||
state.current_file, pos.base(), pos.base(),
|
||||
doc_info_tags::type);
|
||||
use_doc_info = true;
|
||||
}
|
||||
@@ -180,56 +190,67 @@ namespace quickbook
|
||||
|
||||
std::vector<std::string> duplicates;
|
||||
|
||||
std::vector<value> escaped_attributes = consume_multiple_values(values, doc_info_tags::escaped_attribute);
|
||||
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);
|
||||
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);
|
||||
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())
|
||||
{
|
||||
if (!duplicates.empty()) {
|
||||
detail::outwarn(state.current_file->path)
|
||||
<< (duplicates.size() > 1 ?
|
||||
"Duplicate attributes" : "Duplicate attribute")
|
||||
<< ":" << boost::algorithm::join(duplicates, ", ")
|
||||
<< "\n"
|
||||
;
|
||||
<< (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_ = include_doc_id.get_quickbook().to_s();
|
||||
if (!id.empty())
|
||||
id_ = id.get_quickbook().to_s();
|
||||
if (!id.empty()) id_ = id.get_quickbook().to_s();
|
||||
|
||||
// Quickbook version
|
||||
|
||||
unsigned new_version = get_version(state, use_doc_info, qbk_version);
|
||||
|
||||
if (new_version != qbk_version_n)
|
||||
{
|
||||
if (classify_version(new_version) == version_dev)
|
||||
{
|
||||
if (new_version != qbk_version_n) {
|
||||
if (classify_version(new_version) == version_dev) {
|
||||
detail::outwarn(state.current_file->path)
|
||||
<< "Quickbook " << (new_version / 100) << "." << (new_version % 100)
|
||||
<< "Quickbook " << (new_version / 100) << "."
|
||||
<< (new_version % 100)
|
||||
<< " is still under development and is "
|
||||
"likely to change in the future." << std::endl;
|
||||
"likely to change in the future."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +262,8 @@ namespace quickbook
|
||||
qbk_version_n = 101;
|
||||
detail::outwarn(state.current_file, pos.base())
|
||||
<< "Quickbook version undefined. "
|
||||
"Version 1.1 is assumed" << std::endl;
|
||||
"Version 1.1 is assumed"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
state.current_file->version(qbk_version_n);
|
||||
@@ -252,22 +274,21 @@ namespace quickbook
|
||||
get_version(state, use_doc_info, compatibility_mode);
|
||||
|
||||
if (!compatibility_version) {
|
||||
compatibility_version = use_doc_info ?
|
||||
qbk_version_n : state.document.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);
|
||||
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);
|
||||
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.
|
||||
|
||||
@@ -277,26 +298,20 @@ namespace quickbook
|
||||
|
||||
std::string xmlbase_value;
|
||||
|
||||
if (!xmlbase.empty())
|
||||
{
|
||||
if (!xmlbase.empty()) {
|
||||
path_parameter x = check_xinclude_path(xmlbase, state);
|
||||
|
||||
if (x.type == path_parameter::path)
|
||||
{
|
||||
if (x.type == path_parameter::path) {
|
||||
quickbook_path path = resolve_xinclude_path(x.value, state);
|
||||
|
||||
if (!fs::is_directory(path.file_path))
|
||||
{
|
||||
if (!fs::is_directory(path.file_path)) {
|
||||
detail::outerr(xmlbase.get_file(), xmlbase.get_position())
|
||||
<< "xmlbase \""
|
||||
<< xmlbase.get_quickbook()
|
||||
<< "\" isn't a directory."
|
||||
<< std::endl;
|
||||
<< "xmlbase \"" << xmlbase.get_quickbook()
|
||||
<< "\" isn't a directory." << std::endl;
|
||||
|
||||
++state.error_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
xmlbase_value = dir_path_to_url(path.abstract_file_path);
|
||||
state.xinclude_base = path.file_path;
|
||||
}
|
||||
@@ -305,64 +320,50 @@ namespace quickbook
|
||||
|
||||
// Warn about invalid fields
|
||||
|
||||
if (doc_type != "library")
|
||||
{
|
||||
if (doc_type != "library") {
|
||||
std::vector<std::string> invalid_attributes;
|
||||
|
||||
if (!purpose.empty())
|
||||
invalid_attributes.push_back("purpose");
|
||||
if (!purpose.empty()) invalid_attributes.push_back("purpose");
|
||||
|
||||
if (!categories.empty())
|
||||
invalid_attributes.push_back("category");
|
||||
if (!categories.empty()) invalid_attributes.push_back("category");
|
||||
|
||||
if (!dirname.empty())
|
||||
invalid_attributes.push_back("dirname");
|
||||
if (!dirname.empty()) invalid_attributes.push_back("dirname");
|
||||
|
||||
if(!invalid_attributes.empty())
|
||||
{
|
||||
if (!invalid_attributes.empty()) {
|
||||
detail::outwarn(state.current_file->path)
|
||||
<< (invalid_attributes.size() > 1 ?
|
||||
"Invalid attributes" : "Invalid attribute")
|
||||
<< (invalid_attributes.size() > 1 ? "Invalid attributes"
|
||||
: "Invalid attribute")
|
||||
<< " for '" << doc_type << " document info': "
|
||||
<< boost::algorithm::join(invalid_attributes, ", ")
|
||||
<< "\n"
|
||||
;
|
||||
<< boost::algorithm::join(invalid_attributes, ", ") << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Write out header
|
||||
|
||||
if (!nested_file)
|
||||
{
|
||||
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"
|
||||
;
|
||||
<< "<!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";
|
||||
<< " id=\"" << id_placeholder << "\"\n";
|
||||
|
||||
if(!lang.empty())
|
||||
{
|
||||
state.out << " lang=\""
|
||||
<< doc_info_output(lang, 106)
|
||||
<< "\"\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";
|
||||
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")
|
||||
{
|
||||
if (!dirname.empty() || doc_type == "library") {
|
||||
state.out << " dirname=\"";
|
||||
if (!dirname.empty()) {
|
||||
state.out << doc_info_output(dirname, 106);
|
||||
@@ -384,54 +385,46 @@ namespace quickbook
|
||||
}
|
||||
|
||||
state.out << " last-revision=\"";
|
||||
if (!last_revision.empty())
|
||||
{
|
||||
if (!last_revision.empty()) {
|
||||
state.out << doc_info_output(last_revision, 106);
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
);
|
||||
(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";
|
||||
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())
|
||||
{
|
||||
if (!authors.empty()) {
|
||||
tmp << " <authorgroup>\n";
|
||||
BOOST_FOREACH(value_consumer author_values, authors)
|
||||
{
|
||||
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);
|
||||
|
||||
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>" << doc_info_output(first, 106)
|
||||
<< "</firstname>\n"
|
||||
<< " <surname>"
|
||||
<< doc_info_output(surname, 106)
|
||||
<< " <surname>" << doc_info_output(surname, 106)
|
||||
<< "</surname>\n"
|
||||
<< " </author>\n";
|
||||
}
|
||||
@@ -439,48 +432,44 @@ namespace quickbook
|
||||
tmp << " </authorgroup>\n";
|
||||
}
|
||||
|
||||
BOOST_FOREACH(value_consumer copyright, copyrights)
|
||||
{
|
||||
while(copyright.check())
|
||||
{
|
||||
tmp << "\n" << " <copyright>\n";
|
||||
|
||||
while(copyright.check(doc_info_tags::copyright_year))
|
||||
{
|
||||
BOOST_FOREACH (value_consumer copyright, copyrights) {
|
||||
while (copyright.check()) {
|
||||
tmp << "\n"
|
||||
<< " <copyright>\n";
|
||||
|
||||
while (copyright.check(doc_info_tags::copyright_year)) {
|
||||
value year_start_value = copyright.consume();
|
||||
int year_start = year_start_value.get_int();
|
||||
int year_end =
|
||||
copyright.check(doc_info_tags::copyright_year_end) ?
|
||||
copyright.consume().get_int() :
|
||||
year_start;
|
||||
|
||||
copyright.check(doc_info_tags::copyright_year_end)
|
||||
? copyright.consume().get_int()
|
||||
: year_start;
|
||||
|
||||
if (year_end < year_start) {
|
||||
++state.error_count;
|
||||
|
||||
detail::outerr(state.current_file, copyright.begin()->get_position())
|
||||
<< "Invalid year range: "
|
||||
<< year_start
|
||||
<< "-"
|
||||
<< year_end
|
||||
<< "."
|
||||
<< std::endl;
|
||||
|
||||
detail::outerr(
|
||||
state.current_file,
|
||||
copyright.begin()->get_position())
|
||||
<< "Invalid year range: " << year_start << "-"
|
||||
<< year_end << "." << std::endl;
|
||||
}
|
||||
|
||||
for(; year_start <= year_end; ++year_start)
|
||||
|
||||
for (; year_start <= year_end; ++year_start)
|
||||
tmp << " <year>" << year_start << "</year>\n";
|
||||
}
|
||||
|
||||
|
||||
tmp << " <holder>"
|
||||
<< doc_info_output(copyright.consume(doc_info_tags::copyright_name), 106)
|
||||
<< doc_info_output(
|
||||
copyright.consume(doc_info_tags::copyright_name),
|
||||
106)
|
||||
<< "</holder>\n"
|
||||
<< " </copyright>\n"
|
||||
<< "\n"
|
||||
;
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!license.empty())
|
||||
{
|
||||
if (!license.empty()) {
|
||||
tmp << " <legalnotice id=\""
|
||||
<< state.document.add_id("legal", id_category::generated)
|
||||
<< "\">\n"
|
||||
@@ -488,69 +477,54 @@ namespace quickbook
|
||||
<< " " << doc_info_output(license, 103) << "\n"
|
||||
<< " </para>\n"
|
||||
<< " </legalnotice>\n"
|
||||
<< "\n"
|
||||
;
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if (!purpose.empty())
|
||||
{
|
||||
if (!purpose.empty()) {
|
||||
tmp << " <" << doc_type << "purpose>\n"
|
||||
<< " " << doc_info_output(purpose, 103)
|
||||
<< " </" << doc_type << "purpose>\n"
|
||||
<< "\n"
|
||||
;
|
||||
<< " " << doc_info_output(purpose, 103) << " </"
|
||||
<< doc_type << "purpose>\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
BOOST_FOREACH(value_consumer category_values, categories) {
|
||||
BOOST_FOREACH (value_consumer category_values, categories) {
|
||||
value category = category_values.optional_consume();
|
||||
if(!category.empty()) {
|
||||
if (!category.empty()) {
|
||||
tmp << " <" << doc_type << "category name=\"category:"
|
||||
<< doc_info_output(category, 106)
|
||||
<< "\"></" << doc_type << "category>\n"
|
||||
<< "\n"
|
||||
;
|
||||
<< doc_info_output(category, 106) << "\"></" << doc_type
|
||||
<< "category>\n"
|
||||
<< "\n";
|
||||
}
|
||||
category_values.finish();
|
||||
}
|
||||
|
||||
BOOST_FOREACH(value_consumer biblioid, biblioids)
|
||||
{
|
||||
BOOST_FOREACH (value_consumer biblioid, biblioids) {
|
||||
value class_ = biblioid.consume(doc_info_tags::biblioid_class);
|
||||
value value_ = biblioid.consume(doc_info_tags::biblioid_value);
|
||||
|
||||
tmp << " <biblioid class=\""
|
||||
<< class_.get_quickbook()
|
||||
<< "\">"
|
||||
<< doc_info_output(value_, 106)
|
||||
<< "</biblioid>"
|
||||
<< "\n"
|
||||
;
|
||||
|
||||
tmp << " <biblioid class=\"" << class_.get_quickbook() << "\">"
|
||||
<< doc_info_output(value_, 106) << "</biblioid>"
|
||||
<< "\n";
|
||||
biblioid.finish();
|
||||
}
|
||||
|
||||
BOOST_FOREACH(value escaped, escaped_attributes)
|
||||
{
|
||||
tmp << "<!--quickbook-escape-prefix-->"
|
||||
<< escaped.get_quickbook()
|
||||
<< "<!--quickbook-escape-postfix-->"
|
||||
;
|
||||
BOOST_FOREACH (value escaped, escaped_attributes) {
|
||||
tmp << "<!--quickbook-escape-prefix-->" << escaped.get_quickbook()
|
||||
<< "<!--quickbook-escape-postfix-->";
|
||||
}
|
||||
|
||||
if(doc_type != "library") {
|
||||
if (doc_type != "library") {
|
||||
write_document_title(state.out, doc_title, version);
|
||||
}
|
||||
|
||||
std::string docinfo = tmp.str();
|
||||
if(!docinfo.empty())
|
||||
{
|
||||
if (!docinfo.empty()) {
|
||||
state.out << " <" << doc_type << "info>\n"
|
||||
<< docinfo
|
||||
<< " </" << doc_type << "info>\n"
|
||||
<< "\n"
|
||||
;
|
||||
<< docinfo << " </" << doc_type << "info>\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if(doc_type == "library") {
|
||||
if (doc_type == "library") {
|
||||
write_document_title(state.out, doc_title, version);
|
||||
}
|
||||
|
||||
@@ -566,16 +540,18 @@ namespace quickbook
|
||||
if (!doc_type.empty() && state.document.section_level() > 1) {
|
||||
if (state.strict_mode) {
|
||||
detail::outerr(state.current_file->path)
|
||||
<< "Missing [endsect] detected at end of file (strict mode)."
|
||||
<< "Missing [endsect] detected at end of file (strict "
|
||||
"mode)."
|
||||
<< std::endl;
|
||||
++state.error_count;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
detail::outwarn(state.current_file->path)
|
||||
<< "Missing [endsect] detected at end of file."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
while(state.document.section_level() > 1) {
|
||||
while (state.document.section_level() > 1) {
|
||||
state.out << "</section>";
|
||||
state.document.end_section();
|
||||
}
|
||||
@@ -585,16 +561,15 @@ namespace quickbook
|
||||
if (!doc_type.empty()) state.out << "\n</" << doc_type << ">\n\n";
|
||||
}
|
||||
|
||||
static void write_document_title(collector& out, value const& title, value const& version)
|
||||
static void write_document_title(
|
||||
collector& out, value const& title, value const& version)
|
||||
{
|
||||
if (!title.empty())
|
||||
{
|
||||
out << " <title>"
|
||||
<< doc_info_output(title, 106);
|
||||
if (!title.empty()) {
|
||||
out << " <title>" << doc_info_output(title, 106);
|
||||
if (!version.empty()) {
|
||||
out << ' ' << doc_info_output(version, 106);
|
||||
}
|
||||
out<< "</title>\n\n\n";
|
||||
out << "</title>\n\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,18 +10,18 @@
|
||||
|
||||
#include <map>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/spirit/include/classic_chset.hpp>
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_loops.hpp>
|
||||
#include <boost/spirit/include/classic_symbols.hpp>
|
||||
#include <boost/spirit/include/classic_chset.hpp>
|
||||
#include <boost/spirit/include/classic_numerics.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include <boost/spirit/include/classic_symbols.hpp>
|
||||
#include <boost/spirit/include/phoenix1_operators.hpp>
|
||||
#include "grammar_impl.hpp"
|
||||
#include "state.hpp"
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include "actions.hpp"
|
||||
#include "doc_info_tags.hpp"
|
||||
#include "grammar_impl.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -31,7 +31,8 @@ namespace quickbook
|
||||
{
|
||||
attribute_info(value::tag_type t, cl::rule<scanner>* r)
|
||||
: tag(t), rule(r)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
value::tag_type tag;
|
||||
cl::rule<scanner>* rule;
|
||||
@@ -41,77 +42,69 @@ namespace quickbook
|
||||
{
|
||||
struct assign_attribute_type
|
||||
{
|
||||
assign_attribute_type(doc_info_grammar_local& l_)
|
||||
: l(l_)
|
||||
{}
|
||||
assign_attribute_type(doc_info_grammar_local& l_) : l(l_) {}
|
||||
|
||||
void operator()(value::tag_type& t) const {
|
||||
void operator()(value::tag_type& t) const
|
||||
{
|
||||
l.attribute_rule = *l.attribute_rules[t];
|
||||
l.attribute_tag = t;
|
||||
}
|
||||
|
||||
|
||||
doc_info_grammar_local& l;
|
||||
};
|
||||
|
||||
|
||||
struct fallback_attribute_type
|
||||
{
|
||||
fallback_attribute_type(doc_info_grammar_local& l_)
|
||||
: l(l_)
|
||||
{}
|
||||
fallback_attribute_type(doc_info_grammar_local& l_) : l(l_) {}
|
||||
|
||||
void operator()(parse_iterator, parse_iterator) const {
|
||||
void operator()(parse_iterator, parse_iterator) const
|
||||
{
|
||||
l.attribute_rule = l.doc_fallback;
|
||||
l.attribute_tag = value::default_tag;
|
||||
}
|
||||
|
||||
|
||||
doc_info_grammar_local& l;
|
||||
};
|
||||
|
||||
cl::rule<scanner>
|
||||
doc_info_block, doc_attribute, doc_info_attribute,
|
||||
doc_info_escaped_attributes,
|
||||
doc_title, doc_simple, doc_phrase, doc_fallback,
|
||||
doc_authors, doc_author,
|
||||
doc_copyright, doc_copyright_holder,
|
||||
doc_source_mode, doc_biblioid, doc_compatibility_mode,
|
||||
quickbook_version, macro, char_;
|
||||
cl::rule<scanner> doc_info_block, doc_attribute, doc_info_attribute,
|
||||
doc_info_escaped_attributes, doc_title, doc_simple, doc_phrase,
|
||||
doc_fallback, doc_authors, doc_author, doc_copyright,
|
||||
doc_copyright_holder, doc_source_mode, doc_biblioid,
|
||||
doc_compatibility_mode, quickbook_version, macro, char_;
|
||||
cl::uint_parser<int, 10, 4, 4> doc_copyright_year;
|
||||
cl::symbols<> doc_types;
|
||||
cl::symbols<value::tag_type> doc_info_attributes;
|
||||
cl::symbols<value::tag_type> doc_attributes;
|
||||
std::map<value::tag_type, cl::rule<scanner>* > attribute_rules;
|
||||
std::map<value::tag_type, cl::rule<scanner>*> attribute_rules;
|
||||
value::tag_type attribute_tag;
|
||||
cl::rule<scanner> attribute_rule;
|
||||
assign_attribute_type assign_attribute;
|
||||
fallback_attribute_type fallback_attribute;
|
||||
|
||||
doc_info_grammar_local()
|
||||
: assign_attribute(*this)
|
||||
, fallback_attribute(*this)
|
||||
{}
|
||||
: assign_attribute(*this), fallback_attribute(*this)
|
||||
{
|
||||
}
|
||||
|
||||
bool source_mode_unset;
|
||||
};
|
||||
|
||||
void quickbook_grammar::impl::init_doc_info()
|
||||
{
|
||||
doc_info_grammar_local& local = cleanup_.add(
|
||||
new doc_info_grammar_local);
|
||||
doc_info_grammar_local& local =
|
||||
cleanup_.add(new doc_info_grammar_local);
|
||||
|
||||
typedef cl::uint_parser<int, 10, 1, 2> uint2_t;
|
||||
typedef cl::uint_parser<int, 10, 1, 2> uint2_t;
|
||||
|
||||
local.doc_types =
|
||||
"book", "article", "library", "chapter", "part"
|
||||
, "appendix", "preface", "qandadiv", "qandaset"
|
||||
, "reference", "set"
|
||||
;
|
||||
local.doc_types = "book", "article", "library", "chapter", "part",
|
||||
"appendix", "preface", "qandadiv", "qandaset", "reference", "set";
|
||||
|
||||
BOOST_FOREACH(value::tag_type t, doc_attributes::tags()) {
|
||||
BOOST_FOREACH (value::tag_type t, doc_attributes::tags()) {
|
||||
local.doc_attributes.add(doc_attributes::name(t), t);
|
||||
local.doc_info_attributes.add(doc_attributes::name(t), t);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(value::tag_type t, doc_info_attributes::tags()) {
|
||||
BOOST_FOREACH (value::tag_type t, doc_info_attributes::tags()) {
|
||||
local.doc_info_attributes.add(doc_info_attributes::name(t), t);
|
||||
}
|
||||
|
||||
@@ -120,10 +113,11 @@ namespace quickbook
|
||||
plain_char_action plain_char(state);
|
||||
do_macro_action do_macro(state);
|
||||
scoped_parser<to_value_scoped_action> to_value(state);
|
||||
member_action_value<quickbook::state, source_mode_type> change_source_mode(
|
||||
state, &state::change_source_mode);
|
||||
member_action_fixed_value<quickbook::state, source_mode_type> default_source_mode(
|
||||
state, &state::change_source_mode, source_mode_tags::cpp);
|
||||
member_action_value<quickbook::state, source_mode_type>
|
||||
change_source_mode(state, &state::change_source_mode);
|
||||
member_action_fixed_value<quickbook::state, source_mode_type>
|
||||
default_source_mode(
|
||||
state, &state::change_source_mode, source_mode_tags::cpp);
|
||||
|
||||
// clang-format off
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include <cctype>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include "document_state_impl.hpp"
|
||||
#include "utils.hpp"
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <cctype>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -31,28 +31,36 @@ namespace quickbook
|
||||
std::string const doc_id_1_1;
|
||||
|
||||
// Constructor for files that aren't the root of a document.
|
||||
explicit file_info(boost::shared_ptr<file_info> const& parent_,
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view doc_id_1_1_,
|
||||
id_placeholder const* override_id_) :
|
||||
parent(parent_), document(parent->document),
|
||||
compatibility_version(compatibility_version_),
|
||||
depth(parent->depth + 1),
|
||||
override_depth(override_id_ ? depth : parent->override_depth),
|
||||
override_id(override_id_ ? override_id_ : parent->override_id),
|
||||
doc_id_1_1(doc_id_1_1_.to_s())
|
||||
{}
|
||||
explicit file_info(
|
||||
boost::shared_ptr<file_info> const& parent_,
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view doc_id_1_1_,
|
||||
id_placeholder const* override_id_)
|
||||
: parent(parent_)
|
||||
, document(parent->document)
|
||||
, compatibility_version(compatibility_version_)
|
||||
, depth(parent->depth + 1)
|
||||
, override_depth(override_id_ ? depth : parent->override_depth)
|
||||
, override_id(override_id_ ? override_id_ : parent->override_id)
|
||||
, doc_id_1_1(doc_id_1_1_.to_s())
|
||||
{
|
||||
}
|
||||
|
||||
// Constructor for files that are the root of a document.
|
||||
explicit file_info(boost::shared_ptr<file_info> const& parent_,
|
||||
boost::shared_ptr<doc_info> const& document_,
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view doc_id_1_1_) :
|
||||
parent(parent_), document(document_),
|
||||
compatibility_version(compatibility_version_),
|
||||
depth(0), override_depth(0), override_id(0),
|
||||
doc_id_1_1(doc_id_1_1_.to_s())
|
||||
{}
|
||||
explicit file_info(
|
||||
boost::shared_ptr<file_info> const& parent_,
|
||||
boost::shared_ptr<doc_info> const& document_,
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view doc_id_1_1_)
|
||||
: parent(parent_)
|
||||
, document(document_)
|
||||
, compatibility_version(compatibility_version_)
|
||||
, depth(0)
|
||||
, override_depth(0)
|
||||
, override_id(0)
|
||||
, doc_id_1_1(doc_id_1_1_.to_s())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct doc_info
|
||||
@@ -78,69 +86,68 @@ namespace quickbook
|
||||
id_placeholder const* const placeholder_1_6;
|
||||
source_mode_info const source_mode;
|
||||
|
||||
explicit section_info(boost::shared_ptr<section_info> const& parent_,
|
||||
file_info const* current_file_,
|
||||
value const& explicit_id_,
|
||||
quickbook::string_view id_1_1_,
|
||||
id_placeholder const* placeholder_1_6_,
|
||||
source_mode_info const& source_mode_) :
|
||||
parent(parent_),
|
||||
compatibility_version(current_file_->compatibility_version),
|
||||
file_depth(current_file_->depth),
|
||||
level(parent ? parent->level + 1 : 1),
|
||||
explicit_id(explicit_id_),
|
||||
id_1_1(id_1_1_.to_s()),
|
||||
placeholder_1_6(placeholder_1_6_),
|
||||
source_mode(source_mode_) {}
|
||||
explicit section_info(
|
||||
boost::shared_ptr<section_info> const& parent_,
|
||||
file_info const* current_file_,
|
||||
value const& explicit_id_,
|
||||
quickbook::string_view id_1_1_,
|
||||
id_placeholder const* placeholder_1_6_,
|
||||
source_mode_info const& source_mode_)
|
||||
: parent(parent_)
|
||||
, compatibility_version(current_file_->compatibility_version)
|
||||
, file_depth(current_file_->depth)
|
||||
, level(parent ? parent->level + 1 : 1)
|
||||
, explicit_id(explicit_id_)
|
||||
, id_1_1(id_1_1_.to_s())
|
||||
, placeholder_1_6(placeholder_1_6_)
|
||||
, source_mode(source_mode_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// document_state
|
||||
//
|
||||
|
||||
document_state::document_state()
|
||||
: state(new document_state_impl)
|
||||
{
|
||||
}
|
||||
document_state::document_state() : state(new document_state_impl) {}
|
||||
|
||||
document_state::~document_state() {}
|
||||
|
||||
void document_state::start_file(
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title_)
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title_)
|
||||
{
|
||||
state->start_file(compatibility_version_, false, include_doc_id, id, title_);
|
||||
state->start_file(
|
||||
compatibility_version_, false, include_doc_id, id, title_);
|
||||
}
|
||||
|
||||
std::string document_state::start_file_with_docinfo(
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title_)
|
||||
unsigned compatibility_version_,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title_)
|
||||
{
|
||||
return state->start_file(compatibility_version_, true, include_doc_id,
|
||||
id, title_)->to_string();
|
||||
return state
|
||||
->start_file(
|
||||
compatibility_version_, true, include_doc_id, id, title_)
|
||||
->to_string();
|
||||
}
|
||||
|
||||
void document_state::end_file()
|
||||
{
|
||||
state->end_file();
|
||||
}
|
||||
void document_state::end_file() { state->end_file(); }
|
||||
|
||||
std::string document_state::begin_section(
|
||||
value const& explicit_id_, quickbook::string_view id,
|
||||
id_category category, source_mode_info const& source_mode)
|
||||
value const& explicit_id_,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const& source_mode)
|
||||
{
|
||||
return state->begin_section(explicit_id_, id, category, source_mode)
|
||||
->to_string();
|
||||
}
|
||||
|
||||
void document_state::end_section()
|
||||
{
|
||||
return state->end_section();
|
||||
}
|
||||
void document_state::end_section() { return state->end_section(); }
|
||||
|
||||
int document_state::section_level() const
|
||||
{
|
||||
@@ -154,33 +161,37 @@ namespace quickbook
|
||||
|
||||
source_mode_info document_state::section_source_mode() const
|
||||
{
|
||||
return state->current_file ?
|
||||
state->current_file->document->current_section->source_mode :
|
||||
source_mode_info();
|
||||
return state->current_file
|
||||
? state->current_file->document->current_section->source_mode
|
||||
: source_mode_info();
|
||||
}
|
||||
|
||||
std::string document_state::old_style_id(quickbook::string_view id, id_category category)
|
||||
std::string document_state::old_style_id(
|
||||
quickbook::string_view id, id_category category)
|
||||
{
|
||||
return state->old_style_id(id, category)->to_string();
|
||||
}
|
||||
|
||||
std::string document_state::add_id(quickbook::string_view id, id_category category)
|
||||
std::string document_state::add_id(
|
||||
quickbook::string_view id, id_category category)
|
||||
{
|
||||
return state->add_id(id, category)->to_string();
|
||||
}
|
||||
|
||||
std::string document_state::add_anchor(quickbook::string_view id, id_category category)
|
||||
std::string document_state::add_anchor(
|
||||
quickbook::string_view id, id_category category)
|
||||
{
|
||||
return state->add_placeholder(id, category)->to_string();
|
||||
}
|
||||
|
||||
std::string document_state::replace_placeholders_with_unresolved_ids(
|
||||
quickbook::string_view xml) const
|
||||
quickbook::string_view xml) const
|
||||
{
|
||||
return replace_ids(*state, xml);
|
||||
}
|
||||
|
||||
std::string document_state::replace_placeholders(quickbook::string_view xml) const
|
||||
std::string document_state::replace_placeholders(
|
||||
quickbook::string_view xml) const
|
||||
{
|
||||
assert(!state->current_file);
|
||||
std::vector<std::string> ids = generate_ids(*state, xml);
|
||||
@@ -197,17 +208,18 @@ namespace quickbook
|
||||
//
|
||||
|
||||
id_placeholder::id_placeholder(
|
||||
std::size_t index_,
|
||||
quickbook::string_view id_,
|
||||
id_category category_,
|
||||
id_placeholder const* parent_)
|
||||
: index(index_),
|
||||
id(id_.begin(), id_.end()),
|
||||
unresolved_id(parent_ ? parent_->unresolved_id + '.' + id : id),
|
||||
parent(parent_),
|
||||
category(category_),
|
||||
num_dots(boost::range::count(id, '.') +
|
||||
(parent_ ? parent_->num_dots + 1 : 0))
|
||||
std::size_t index_,
|
||||
quickbook::string_view id_,
|
||||
id_category category_,
|
||||
id_placeholder const* parent_)
|
||||
: index(index_)
|
||||
, id(id_.begin(), id_.end())
|
||||
, unresolved_id(parent_ ? parent_->unresolved_id + '.' + id : id)
|
||||
, parent(parent_)
|
||||
, category(category_)
|
||||
, num_dots(
|
||||
boost::range::count(id, '.') +
|
||||
(parent_ ? parent_->num_dots + 1 : 0))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -221,40 +233,42 @@ namespace quickbook
|
||||
//
|
||||
|
||||
id_placeholder const* document_state_impl::add_placeholder(
|
||||
quickbook::string_view id, id_category category,
|
||||
id_placeholder const* parent)
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
id_placeholder const* parent)
|
||||
{
|
||||
placeholders.push_back(id_placeholder(
|
||||
placeholders.size(), id, category, parent));
|
||||
placeholders.push_back(
|
||||
id_placeholder(placeholders.size(), id, category, parent));
|
||||
return &placeholders.back();
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::get_placeholder(quickbook::string_view value) const
|
||||
id_placeholder const* document_state_impl::get_placeholder(
|
||||
quickbook::string_view value) const
|
||||
{
|
||||
// If this isn't a placeholder id.
|
||||
if (value.size() <= 1 || *value.begin() != '$')
|
||||
return 0;
|
||||
if (value.size() <= 1 || *value.begin() != '$') return 0;
|
||||
|
||||
unsigned index = boost::lexical_cast<unsigned>(std::string(
|
||||
value.begin() + 1, value.end()));
|
||||
unsigned index = boost::lexical_cast<unsigned>(
|
||||
std::string(value.begin() + 1, value.end()));
|
||||
|
||||
return &placeholders.at(index);
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::get_id_placeholder(
|
||||
boost::shared_ptr<section_info> const& section) const
|
||||
boost::shared_ptr<section_info> const& section) const
|
||||
{
|
||||
return !section ? 0 :
|
||||
section->file_depth < current_file->override_depth ?
|
||||
current_file->override_id : section->placeholder_1_6;
|
||||
return !section ? 0
|
||||
: section->file_depth < current_file->override_depth
|
||||
? current_file->override_id
|
||||
: section->placeholder_1_6;
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::start_file(
|
||||
unsigned compatibility_version,
|
||||
bool document_root,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title)
|
||||
unsigned compatibility_version,
|
||||
bool document_root,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title)
|
||||
{
|
||||
boost::shared_ptr<file_info> parent = current_file;
|
||||
assert(parent || document_root);
|
||||
@@ -268,10 +282,8 @@ namespace quickbook
|
||||
|
||||
quickbook::string_view initial_doc_id;
|
||||
|
||||
if (document_root ||
|
||||
compatibility_version >= 106u ||
|
||||
parent->compatibility_version >= 106u)
|
||||
{
|
||||
if (document_root || compatibility_version >= 106u ||
|
||||
parent->compatibility_version >= 106u) {
|
||||
initial_doc_id = !include_doc_id.empty() ? include_doc_id : id;
|
||||
}
|
||||
else {
|
||||
@@ -288,8 +300,10 @@ namespace quickbook
|
||||
if (title.check())
|
||||
document->last_title_1_1 = title.get_quickbook().to_s();
|
||||
|
||||
doc_id_1_1 = !initial_doc_id.empty() ? initial_doc_id.to_s() :
|
||||
detail::make_identifier(document->last_title_1_1);
|
||||
doc_id_1_1 =
|
||||
!initial_doc_id.empty()
|
||||
? initial_doc_id.to_s()
|
||||
: detail::make_identifier(document->last_title_1_1);
|
||||
}
|
||||
else if (parent) {
|
||||
doc_id_1_1 = parent->doc_id_1_1;
|
||||
@@ -298,29 +312,33 @@ namespace quickbook
|
||||
if (document_root) {
|
||||
// Create new file
|
||||
|
||||
current_file = boost::make_shared<file_info>(parent,
|
||||
document, compatibility_version, doc_id_1_1);
|
||||
current_file = boost::make_shared<file_info>(
|
||||
parent, document, compatibility_version, doc_id_1_1);
|
||||
|
||||
// Create a section for the new document.
|
||||
|
||||
source_mode_info default_source_mode;
|
||||
|
||||
if (!initial_doc_id.empty()) {
|
||||
return create_new_section(empty_value(), id,
|
||||
id_category::explicit_section_id, default_source_mode);
|
||||
return create_new_section(
|
||||
empty_value(), id, id_category::explicit_section_id,
|
||||
default_source_mode);
|
||||
}
|
||||
else if (!title.empty()) {
|
||||
return create_new_section(empty_value(),
|
||||
return create_new_section(
|
||||
empty_value(),
|
||||
detail::make_identifier(title.get_quickbook()),
|
||||
id_category::generated_doc, default_source_mode);
|
||||
}
|
||||
else if (compatibility_version >= 106u) {
|
||||
return create_new_section(empty_value(), "doc",
|
||||
id_category::numbered, default_source_mode);
|
||||
return create_new_section(
|
||||
empty_value(), "doc", id_category::numbered,
|
||||
default_source_mode);
|
||||
}
|
||||
else {
|
||||
return create_new_section(empty_value(), "",
|
||||
id_category::generated_doc, default_source_mode);
|
||||
return create_new_section(
|
||||
empty_value(), "", id_category::generated_doc,
|
||||
default_source_mode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -335,19 +353,18 @@ namespace quickbook
|
||||
|
||||
id_placeholder const* override_id = 0;
|
||||
|
||||
if (!initial_doc_id.empty() && compatibility_version >= 106u)
|
||||
{
|
||||
if (!initial_doc_id.empty() && compatibility_version >= 106u) {
|
||||
boost::shared_ptr<section_info> null_section;
|
||||
|
||||
override_id = add_id_to_section(initial_doc_id,
|
||||
id_category::explicit_section_id, null_section);
|
||||
override_id = add_id_to_section(
|
||||
initial_doc_id, id_category::explicit_section_id,
|
||||
null_section);
|
||||
}
|
||||
|
||||
// Create new file
|
||||
|
||||
current_file =
|
||||
boost::make_shared<file_info>(parent, compatibility_version,
|
||||
doc_id_1_1, override_id);
|
||||
current_file = boost::make_shared<file_info>(
|
||||
parent, compatibility_version, doc_id_1_1, override_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -359,17 +376,16 @@ namespace quickbook
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::add_id(
|
||||
quickbook::string_view id,
|
||||
id_category category)
|
||||
quickbook::string_view id, id_category category)
|
||||
{
|
||||
return add_id_to_section(id, category,
|
||||
current_file->document->current_section);
|
||||
return add_id_to_section(
|
||||
id, category, current_file->document->current_section);
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::add_id_to_section(
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
boost::shared_ptr<section_info> const& section)
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
boost::shared_ptr<section_info> const& section)
|
||||
{
|
||||
std::string id_part(id.begin(), id.end());
|
||||
|
||||
@@ -377,21 +393,20 @@ namespace quickbook
|
||||
// adding to section according to section compatibility version.
|
||||
|
||||
if (current_file->compatibility_version >= 106u &&
|
||||
category.c < id_category::explicit_id) {
|
||||
category.c < id_category::explicit_id) {
|
||||
id_part = normalize_id(id);
|
||||
}
|
||||
|
||||
id_placeholder const* placeholder_1_6 = get_id_placeholder(section);
|
||||
|
||||
if(!section || section->compatibility_version >= 106u) {
|
||||
if (!section || section->compatibility_version >= 106u) {
|
||||
return add_placeholder(id_part, category, placeholder_1_6);
|
||||
}
|
||||
else {
|
||||
std::string const& qualified_id = section->id_1_1;
|
||||
|
||||
std::string new_id;
|
||||
if (!placeholder_1_6)
|
||||
new_id = current_file->doc_id_1_1;
|
||||
if (!placeholder_1_6) new_id = current_file->doc_id_1_1;
|
||||
if (!new_id.empty() && !qualified_id.empty()) new_id += '.';
|
||||
new_id += qualified_id;
|
||||
if (!new_id.empty() && !id_part.empty()) new_id += '.';
|
||||
@@ -402,30 +417,31 @@ namespace quickbook
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::old_style_id(
|
||||
quickbook::string_view id,
|
||||
id_category category)
|
||||
quickbook::string_view id, id_category category)
|
||||
{
|
||||
return current_file->compatibility_version < 103u ?
|
||||
add_placeholder(
|
||||
current_file->document->section_id_1_1 + "." + id.to_s(), category) :
|
||||
add_id(id, category);
|
||||
return current_file->compatibility_version < 103u
|
||||
? add_placeholder(
|
||||
current_file->document->section_id_1_1 + "." +
|
||||
id.to_s(),
|
||||
category)
|
||||
: add_id(id, category);
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::begin_section(
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const& source_mode)
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const& source_mode)
|
||||
{
|
||||
current_file->document->section_id_1_1 = id.to_s();
|
||||
return create_new_section(explicit_id, id, category, source_mode);
|
||||
}
|
||||
|
||||
id_placeholder const* document_state_impl::create_new_section(
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const& source_mode)
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const& source_mode)
|
||||
{
|
||||
boost::shared_ptr<section_info> parent =
|
||||
current_file->document->current_section;
|
||||
@@ -437,8 +453,7 @@ namespace quickbook
|
||||
|
||||
if (parent && current_file->compatibility_version < 106u) {
|
||||
id_1_1 = parent->id_1_1;
|
||||
if (!id_1_1.empty() && !id.empty())
|
||||
id_1_1 += ".";
|
||||
if (!id_1_1.empty() && !id.empty()) id_1_1 += ".";
|
||||
id_1_1.append(id.begin(), id.end());
|
||||
}
|
||||
|
||||
@@ -470,9 +485,9 @@ namespace quickbook
|
||||
}
|
||||
|
||||
current_file->document->current_section =
|
||||
boost::make_shared<section_info>(parent,
|
||||
current_file.get(), explicit_id, id_1_1, placeholder_1_6,
|
||||
source_mode);
|
||||
boost::make_shared<section_info>(
|
||||
parent, current_file.get(), explicit_id, id_1_1,
|
||||
placeholder_1_6, source_mode);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
#if !defined(BOOST_QUICKBOOK_DOCUMENT_STATE_HPP)
|
||||
#define BOOST_QUICKBOOK_DOCUMENT_STATE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include "string_view.hpp"
|
||||
#include <string>
|
||||
#include "values.hpp"
|
||||
#include "syntax_highlight.hpp"
|
||||
#include "values.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -26,12 +26,12 @@ namespace quickbook
|
||||
enum categories
|
||||
{
|
||||
default_category = 0,
|
||||
numbered, // Just used to avoid random docbook ids
|
||||
generated, // Generated ids for other elements.
|
||||
generated_heading, // Generated ids for headings.
|
||||
generated_section, // Generated ids for sections.
|
||||
generated_doc, // Generated ids for document.
|
||||
explicit_id, // Explicitly given by user
|
||||
numbered, // Just used to avoid random docbook ids
|
||||
generated, // Generated ids for other elements.
|
||||
generated_heading, // Generated ids for headings.
|
||||
generated_section, // Generated ids for sections.
|
||||
generated_doc, // Generated ids for document.
|
||||
explicit_id, // Explicitly given by user
|
||||
explicit_section_id,
|
||||
explicit_anchor_id
|
||||
};
|
||||
@@ -53,21 +53,24 @@ namespace quickbook
|
||||
~document_state();
|
||||
|
||||
std::string start_file_with_docinfo(
|
||||
unsigned compatibility_version,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title);
|
||||
unsigned compatibility_version,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title);
|
||||
|
||||
void start_file(
|
||||
unsigned compatibility_version,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title);
|
||||
unsigned compatibility_version,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title);
|
||||
|
||||
void end_file();
|
||||
|
||||
std::string begin_section(value const&,
|
||||
quickbook::string_view, id_category, source_mode_info const&);
|
||||
std::string begin_section(
|
||||
value const&,
|
||||
quickbook::string_view,
|
||||
id_category,
|
||||
source_mode_info const&);
|
||||
void end_section();
|
||||
int section_level() const;
|
||||
value const& explicit_id() const;
|
||||
@@ -78,11 +81,12 @@ namespace quickbook
|
||||
std::string add_anchor(quickbook::string_view, id_category);
|
||||
|
||||
std::string replace_placeholders_with_unresolved_ids(
|
||||
quickbook::string_view) const;
|
||||
quickbook::string_view) const;
|
||||
std::string replace_placeholders(quickbook::string_view) const;
|
||||
|
||||
unsigned compatibility_version() const;
|
||||
private:
|
||||
|
||||
private:
|
||||
boost::scoped_ptr<document_state_impl> state;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
#if !defined(BOOST_QUICKBOOK_DOCUMENT_STATE_IMPL_HPP)
|
||||
#define BOOST_QUICKBOOK_DOCUMENT_STATE_IMPL_HPP
|
||||
|
||||
#include "document_state.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "string_view.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "document_state.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "string_view.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -30,24 +30,27 @@ namespace quickbook
|
||||
|
||||
struct id_placeholder
|
||||
{
|
||||
std::size_t index; // The index in document_state_impl::placeholders.
|
||||
// Use for the dollar identifiers in
|
||||
// intermediate xml.
|
||||
std::string id; // The node id.
|
||||
std::size_t index; // The index in document_state_impl::placeholders.
|
||||
// Use for the dollar identifiers in
|
||||
// intermediate xml.
|
||||
std::string id; // The node id.
|
||||
std::string unresolved_id;
|
||||
// The id that would be generated
|
||||
// without any duplicate handling.
|
||||
// Used for generating old style header anchors.
|
||||
// The id that would be generated
|
||||
// without any duplicate handling.
|
||||
// Used for generating old style header anchors.
|
||||
id_placeholder const* parent;
|
||||
// Placeholder of the parent id.
|
||||
// Placeholder of the parent id.
|
||||
id_category category;
|
||||
std::ptrdiff_t num_dots; // Number of dots in the id.
|
||||
// Normally equal to the section level
|
||||
// but not when an explicit id contains
|
||||
// dots.
|
||||
// Normally equal to the section level
|
||||
// but not when an explicit id contains
|
||||
// dots.
|
||||
|
||||
id_placeholder(std::size_t index, quickbook::string_view id,
|
||||
id_category category, id_placeholder const* parent_);
|
||||
id_placeholder(
|
||||
std::size_t index,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
id_placeholder const* parent_);
|
||||
|
||||
std::string to_string() const;
|
||||
};
|
||||
@@ -69,53 +72,56 @@ namespace quickbook
|
||||
|
||||
// Placeholder methods
|
||||
|
||||
id_placeholder const* add_placeholder(quickbook::string_view, id_category,
|
||||
id_placeholder const* add_placeholder(
|
||||
quickbook::string_view,
|
||||
id_category,
|
||||
id_placeholder const* parent = 0);
|
||||
|
||||
id_placeholder const* get_placeholder(quickbook::string_view) const;
|
||||
|
||||
id_placeholder const* get_id_placeholder(
|
||||
boost::shared_ptr<section_info> const& section) const;
|
||||
boost::shared_ptr<section_info> const& section) const;
|
||||
|
||||
// Events
|
||||
|
||||
id_placeholder const* start_file(
|
||||
unsigned compatibility_version,
|
||||
bool document_root,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title);
|
||||
unsigned compatibility_version,
|
||||
bool document_root,
|
||||
quickbook::string_view include_doc_id,
|
||||
quickbook::string_view id,
|
||||
value const& title);
|
||||
|
||||
void end_file();
|
||||
|
||||
id_placeholder const* add_id(
|
||||
quickbook::string_view id,
|
||||
id_category category);
|
||||
quickbook::string_view id, id_category category);
|
||||
id_placeholder const* old_style_id(
|
||||
quickbook::string_view id,
|
||||
id_category category);
|
||||
quickbook::string_view id, id_category category);
|
||||
id_placeholder const* begin_section(
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const&);
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const&);
|
||||
void end_section();
|
||||
|
||||
private:
|
||||
private:
|
||||
id_placeholder const* add_id_to_section(
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
boost::shared_ptr<section_info> const& section);
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
boost::shared_ptr<section_info> const& section);
|
||||
id_placeholder const* create_new_section(
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const&);
|
||||
value const& explicit_id,
|
||||
quickbook::string_view id,
|
||||
id_category category,
|
||||
source_mode_info const&);
|
||||
};
|
||||
|
||||
std::string replace_ids(document_state_impl const& state, quickbook::string_view xml,
|
||||
std::vector<std::string> const* = 0);
|
||||
std::vector<std::string> generate_ids(document_state_impl const&, quickbook::string_view);
|
||||
std::string replace_ids(
|
||||
document_state_impl const& state,
|
||||
quickbook::string_view xml,
|
||||
std::vector<std::string> const* = 0);
|
||||
std::vector<std::string> generate_ids(
|
||||
document_state_impl const&, quickbook::string_view);
|
||||
|
||||
std::string normalize_id(quickbook::string_view src_id);
|
||||
std::string normalize_id(quickbook::string_view src_id, std::size_t);
|
||||
@@ -135,7 +141,8 @@ namespace quickbook
|
||||
|
||||
std::vector<std::string> id_attributes;
|
||||
|
||||
struct callback {
|
||||
struct callback
|
||||
{
|
||||
virtual void start(quickbook::string_view) {}
|
||||
virtual void id_value(quickbook::string_view) {}
|
||||
virtual void finish(quickbook::string_view) {}
|
||||
|
||||
366
src/files.cpp
366
src/files.cpp
@@ -8,14 +8,14 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#include "files.hpp"
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/range/algorithm/upper_bound.hpp>
|
||||
#include <boost/range/algorithm/transform.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/range/algorithm/transform.hpp>
|
||||
#include <boost/range/algorithm/upper_bound.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -30,43 +30,49 @@ namespace quickbook
|
||||
// probably broken.
|
||||
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
bool check_bom(InputIterator& begin, InputIterator end,
|
||||
OutputIterator out, char const* chars, int length)
|
||||
bool check_bom(
|
||||
InputIterator& begin,
|
||||
InputIterator end,
|
||||
OutputIterator out,
|
||||
char const* chars,
|
||||
int length)
|
||||
{
|
||||
char const* ptr = chars;
|
||||
|
||||
while(begin != end && *begin == *ptr) {
|
||||
while (begin != end && *begin == *ptr) {
|
||||
++begin;
|
||||
++ptr;
|
||||
--length;
|
||||
if(length == 0) return true;
|
||||
if (length == 0) return true;
|
||||
}
|
||||
|
||||
// Failed to match, so write the skipped characters to storage:
|
||||
while(chars != ptr) *out++ = *chars++;
|
||||
while (chars != ptr)
|
||||
*out++ = *chars++;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
std::string read_bom(InputIterator& begin, InputIterator end,
|
||||
OutputIterator out)
|
||||
std::string read_bom(
|
||||
InputIterator& begin, InputIterator end, OutputIterator out)
|
||||
{
|
||||
if(begin == end) return "";
|
||||
if (begin == end) return "";
|
||||
|
||||
const char* utf8 = "\xef\xbb\xbf" ;
|
||||
const char* utf8 = "\xef\xbb\xbf";
|
||||
const char* utf32be = "\0\0\xfe\xff";
|
||||
const char* utf32le = "\xff\xfe\0\0";
|
||||
|
||||
unsigned char c = *begin;
|
||||
switch(c)
|
||||
{
|
||||
switch (c) {
|
||||
case 0xEF: { // UTF-8
|
||||
return check_bom(begin, end, out, utf8, 3) ? "UTF-8" : "";
|
||||
}
|
||||
case 0xFF: // UTF-16/UTF-32 little endian
|
||||
return !check_bom(begin, end, out, utf32le, 2) ? "" :
|
||||
check_bom(begin, end, out, utf32le + 2, 2) ? "UTF-32" : "UTF-16";
|
||||
return !check_bom(begin, end, out, utf32le, 2)
|
||||
? ""
|
||||
: check_bom(begin, end, out, utf32le + 2, 2) ? "UTF-32"
|
||||
: "UTF-16";
|
||||
case 0: // UTF-32 big endian
|
||||
return check_bom(begin, end, out, utf32be, 4) ? "UTF-32" : "";
|
||||
case 0xFE: // UTF-16 big endian
|
||||
@@ -80,20 +86,18 @@ namespace quickbook
|
||||
// newlines.
|
||||
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
void normalize(InputIterator begin, InputIterator end,
|
||||
OutputIterator out)
|
||||
void normalize(InputIterator begin, InputIterator end, OutputIterator out)
|
||||
{
|
||||
std::string encoding = read_bom(begin, end, out);
|
||||
|
||||
if(encoding != "UTF-8" && encoding != "")
|
||||
throw load_error(encoding +
|
||||
" is not supported. Please use UTF-8.");
|
||||
if (encoding != "UTF-8" && encoding != "")
|
||||
throw load_error(encoding + " is not supported. Please use UTF-8.");
|
||||
|
||||
while(begin != end) {
|
||||
if(*begin == '\r') {
|
||||
while (begin != end) {
|
||||
if (*begin == '\r') {
|
||||
*out++ = '\n';
|
||||
++begin;
|
||||
if(begin != end && *begin == '\n') ++begin;
|
||||
if (begin != end && *begin == '\n') ++begin;
|
||||
}
|
||||
else {
|
||||
*out++ = *begin++;
|
||||
@@ -103,27 +107,23 @@ namespace quickbook
|
||||
|
||||
file_ptr load(fs::path const& filename, unsigned qbk_version)
|
||||
{
|
||||
boost::unordered_map<fs::path, file_ptr>::iterator pos
|
||||
= files.find(filename);
|
||||
boost::unordered_map<fs::path, file_ptr>::iterator pos =
|
||||
files.find(filename);
|
||||
|
||||
if (pos == files.end())
|
||||
{
|
||||
if (pos == files.end()) {
|
||||
fs::ifstream in(filename, std::ios_base::in);
|
||||
|
||||
if (!in)
|
||||
throw load_error("Could not open input file.");
|
||||
if (!in) throw load_error("Could not open input file.");
|
||||
|
||||
// Turn off white space skipping on the stream
|
||||
in.unsetf(std::ios::skipws);
|
||||
|
||||
std::string source;
|
||||
normalize(
|
||||
std::istream_iterator<char>(in),
|
||||
std::istream_iterator<char>(),
|
||||
std::istream_iterator<char>(in), std::istream_iterator<char>(),
|
||||
std::back_inserter(source));
|
||||
|
||||
if (in.bad())
|
||||
throw load_error("Error reading input file.");
|
||||
if (in.bad()) throw load_error("Error reading input file.");
|
||||
|
||||
bool inserted;
|
||||
|
||||
@@ -142,34 +142,28 @@ namespace quickbook
|
||||
}
|
||||
|
||||
file_position relative_position(
|
||||
string_iterator begin,
|
||||
string_iterator iterator)
|
||||
string_iterator begin, string_iterator iterator)
|
||||
{
|
||||
file_position pos;
|
||||
string_iterator line_begin = begin;
|
||||
|
||||
while (begin != iterator)
|
||||
{
|
||||
if (*begin == '\r')
|
||||
{
|
||||
while (begin != iterator) {
|
||||
if (*begin == '\r') {
|
||||
++begin;
|
||||
++pos.line;
|
||||
line_begin = begin;
|
||||
}
|
||||
else if (*begin == '\n')
|
||||
{
|
||||
else if (*begin == '\n') {
|
||||
++begin;
|
||||
++pos.line;
|
||||
line_begin = begin;
|
||||
if (begin == iterator) break;
|
||||
if (*begin == '\r')
|
||||
{
|
||||
if (*begin == '\r') {
|
||||
++begin;
|
||||
line_begin = begin;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
@@ -187,40 +181,44 @@ namespace quickbook
|
||||
|
||||
struct mapped_file_section
|
||||
{
|
||||
enum section_types {
|
||||
enum section_types
|
||||
{
|
||||
normal,
|
||||
empty,
|
||||
indented
|
||||
};
|
||||
|
||||
|
||||
std::string::size_type original_pos;
|
||||
std::string::size_type our_pos;
|
||||
section_types section_type;
|
||||
|
||||
explicit mapped_file_section(
|
||||
std::string::size_type original_pos_,
|
||||
std::string::size_type our_pos_,
|
||||
section_types section_type_ = normal) :
|
||||
original_pos(original_pos_), our_pos(our_pos_),
|
||||
section_type(section_type_) {}
|
||||
std::string::size_type original_pos_,
|
||||
std::string::size_type our_pos_,
|
||||
section_types section_type_ = normal)
|
||||
: original_pos(original_pos_)
|
||||
, our_pos(our_pos_)
|
||||
, section_type(section_type_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct mapped_section_original_cmp
|
||||
{
|
||||
bool operator()(mapped_file_section const& x,
|
||||
mapped_file_section const& y)
|
||||
bool operator()(
|
||||
mapped_file_section const& x, mapped_file_section const& y)
|
||||
{
|
||||
return x.original_pos < y.original_pos;
|
||||
}
|
||||
|
||||
bool operator()(mapped_file_section const& x,
|
||||
std::string::size_type const& y)
|
||||
bool operator()(
|
||||
mapped_file_section const& x, std::string::size_type const& y)
|
||||
{
|
||||
return x.original_pos < y;
|
||||
}
|
||||
|
||||
bool operator()(std::string::size_type const& x,
|
||||
mapped_file_section const& y)
|
||||
bool operator()(
|
||||
std::string::size_type const& x, mapped_file_section const& y)
|
||||
{
|
||||
return x < y.original_pos;
|
||||
}
|
||||
@@ -228,51 +226,53 @@ namespace quickbook
|
||||
|
||||
struct mapped_section_pos_cmp
|
||||
{
|
||||
bool operator()(mapped_file_section const& x,
|
||||
mapped_file_section const& y)
|
||||
bool operator()(
|
||||
mapped_file_section const& x, mapped_file_section const& y)
|
||||
{
|
||||
return x.our_pos < y.our_pos;
|
||||
}
|
||||
|
||||
bool operator()(mapped_file_section const& x,
|
||||
std::string::size_type const& y)
|
||||
bool operator()(
|
||||
mapped_file_section const& x, std::string::size_type const& y)
|
||||
{
|
||||
return x.our_pos < y;
|
||||
}
|
||||
|
||||
bool operator()(std::string::size_type const& x,
|
||||
mapped_file_section const& y)
|
||||
bool operator()(
|
||||
std::string::size_type const& x, mapped_file_section const& y)
|
||||
{
|
||||
return x < y.our_pos;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct mapped_file : file
|
||||
{
|
||||
explicit mapped_file(file_ptr original_) :
|
||||
file(*original_, std::string()),
|
||||
original(original_), mapped_sections()
|
||||
{}
|
||||
explicit mapped_file(file_ptr original_)
|
||||
: file(*original_, std::string())
|
||||
, original(original_)
|
||||
, mapped_sections()
|
||||
{
|
||||
}
|
||||
|
||||
file_ptr original;
|
||||
std::vector<mapped_file_section> mapped_sections;
|
||||
|
||||
void add_empty_mapped_file_section(string_iterator pos) {
|
||||
|
||||
void add_empty_mapped_file_section(string_iterator pos)
|
||||
{
|
||||
std::string::size_type original_pos =
|
||||
pos - original->source().begin();
|
||||
|
||||
|
||||
if (mapped_sections.empty() ||
|
||||
mapped_sections.back().section_type !=
|
||||
mapped_file_section::empty ||
|
||||
mapped_sections.back().original_pos != original_pos)
|
||||
{
|
||||
mapped_sections.back().section_type !=
|
||||
mapped_file_section::empty ||
|
||||
mapped_sections.back().original_pos != original_pos) {
|
||||
mapped_sections.push_back(mapped_file_section(
|
||||
original_pos, source().size(),
|
||||
mapped_file_section::empty));
|
||||
original_pos, source().size(), mapped_file_section::empty));
|
||||
}
|
||||
}
|
||||
|
||||
void add_mapped_file_section(string_iterator pos) {
|
||||
void add_mapped_file_section(string_iterator pos)
|
||||
{
|
||||
mapped_sections.push_back(mapped_file_section(
|
||||
pos - original->source().begin(), source().size()));
|
||||
}
|
||||
@@ -289,68 +289,67 @@ namespace quickbook
|
||||
std::string::size_type pos) const
|
||||
{
|
||||
switch (section->section_type) {
|
||||
case mapped_file_section::normal:
|
||||
return pos - section->our_pos + section->original_pos;
|
||||
case mapped_file_section::normal:
|
||||
return pos - section->our_pos + section->original_pos;
|
||||
|
||||
case mapped_file_section::empty:
|
||||
return section->original_pos;
|
||||
case mapped_file_section::empty:
|
||||
return section->original_pos;
|
||||
|
||||
case mapped_file_section::indented: {
|
||||
// Will contain the start of the current line.
|
||||
quickbook::string_view::size_type our_line = section->our_pos;
|
||||
case mapped_file_section::indented: {
|
||||
// Will contain the start of the current line.
|
||||
quickbook::string_view::size_type our_line = section->our_pos;
|
||||
|
||||
// Will contain the number of lines in the block before
|
||||
// the current line.
|
||||
unsigned newline_count = 0;
|
||||
// Will contain the number of lines in the block before
|
||||
// the current line.
|
||||
unsigned newline_count = 0;
|
||||
|
||||
for(quickbook::string_view::size_type i = section->our_pos;
|
||||
i != pos; ++i)
|
||||
{
|
||||
if (source()[i] == '\n') {
|
||||
our_line = i + 1;
|
||||
++newline_count;
|
||||
}
|
||||
for (quickbook::string_view::size_type i = section->our_pos;
|
||||
i != pos; ++i) {
|
||||
if (source()[i] == '\n') {
|
||||
our_line = i + 1;
|
||||
++newline_count;
|
||||
}
|
||||
|
||||
// The start of the line in the original source.
|
||||
quickbook::string_view::size_type original_line =
|
||||
section->original_pos;
|
||||
|
||||
while(newline_count > 0) {
|
||||
if (original->source()[original_line] == '\n')
|
||||
--newline_count;
|
||||
++original_line;
|
||||
}
|
||||
|
||||
// The start of line content (i.e. after indentation).
|
||||
our_line = skip_indentation(source(), our_line);
|
||||
|
||||
// The position is in the middle of indentation, so
|
||||
// just return the start of the whitespace, which should
|
||||
// be good enough.
|
||||
if (our_line > pos) return original_line;
|
||||
|
||||
original_line =
|
||||
skip_indentation(original->source(), original_line);
|
||||
|
||||
// Confirm that we are actually in the same position.
|
||||
assert(original->source()[original_line] ==
|
||||
source()[our_line]);
|
||||
|
||||
// Calculate the position
|
||||
return original_line + (pos - our_line);
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
return section->original_pos;
|
||||
|
||||
// The start of the line in the original source.
|
||||
quickbook::string_view::size_type original_line =
|
||||
section->original_pos;
|
||||
|
||||
while (newline_count > 0) {
|
||||
if (original->source()[original_line] == '\n')
|
||||
--newline_count;
|
||||
++original_line;
|
||||
}
|
||||
|
||||
// The start of line content (i.e. after indentation).
|
||||
our_line = skip_indentation(source(), our_line);
|
||||
|
||||
// The position is in the middle of indentation, so
|
||||
// just return the start of the whitespace, which should
|
||||
// be good enough.
|
||||
if (our_line > pos) return original_line;
|
||||
|
||||
original_line =
|
||||
skip_indentation(original->source(), original_line);
|
||||
|
||||
// Confirm that we are actually in the same position.
|
||||
assert(original->source()[original_line] == source()[our_line]);
|
||||
|
||||
// Calculate the position
|
||||
return original_line + (pos - our_line);
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
return section->original_pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<mapped_file_section>::const_iterator find_section(
|
||||
string_iterator pos) const
|
||||
{
|
||||
std::vector<mapped_file_section>::const_iterator section =
|
||||
boost::upper_bound(mapped_sections,
|
||||
boost::upper_bound(
|
||||
mapped_sections,
|
||||
std::string::size_type(pos - source().begin()),
|
||||
mapped_section_pos_cmp());
|
||||
assert(section != mapped_sections.begin());
|
||||
@@ -361,18 +360,18 @@ namespace quickbook
|
||||
|
||||
virtual file_position position_of(string_iterator) const;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
static std::string::size_type skip_indentation(
|
||||
quickbook::string_view src, std::string::size_type i)
|
||||
quickbook::string_view src, std::string::size_type i)
|
||||
{
|
||||
while (i != src.size() && (src[i] == ' ' || src[i] == '\t')) ++i;
|
||||
while (i != src.size() && (src[i] == ' ' || src[i] == '\t'))
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
std::list<mapped_file> mapped_files;
|
||||
}
|
||||
|
||||
@@ -380,7 +379,7 @@ namespace quickbook
|
||||
{
|
||||
mapped_file_builder_data() { reset(); }
|
||||
void reset() { new_file.reset(); }
|
||||
|
||||
|
||||
boost::intrusive_ptr<mapped_file> new_file;
|
||||
};
|
||||
|
||||
@@ -404,11 +403,8 @@ namespace quickbook
|
||||
return r;
|
||||
}
|
||||
|
||||
void mapped_file_builder::clear()
|
||||
{
|
||||
data->reset();
|
||||
}
|
||||
|
||||
void mapped_file_builder::clear() { data->reset(); }
|
||||
|
||||
bool mapped_file_builder::empty() const
|
||||
{
|
||||
return data->new_file->source().empty();
|
||||
@@ -418,7 +414,7 @@ namespace quickbook
|
||||
{
|
||||
return data->new_file->source().size();
|
||||
}
|
||||
|
||||
|
||||
void mapped_file_builder::add_at_pos(quickbook::string_view x, iterator pos)
|
||||
{
|
||||
data->new_file->add_empty_mapped_file_section(pos);
|
||||
@@ -436,48 +432,46 @@ namespace quickbook
|
||||
add(x, 0, x.data->new_file->source_.size());
|
||||
}
|
||||
|
||||
void mapped_file_builder::add(mapped_file_builder const& x,
|
||||
pos_type begin, pos_type end)
|
||||
void mapped_file_builder::add(
|
||||
mapped_file_builder const& x, pos_type begin, pos_type end)
|
||||
{
|
||||
assert(data->new_file->original == x.data->new_file->original);
|
||||
assert(begin <= x.data->new_file->source_.size());
|
||||
assert(end <= x.data->new_file->source_.size());
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
if (begin != end) {
|
||||
std::vector<mapped_file_section>::const_iterator i =
|
||||
x.data->new_file->find_section(
|
||||
x.data->new_file->source().begin() + begin);
|
||||
|
||||
|
||||
std::string::size_type size = data->new_file->source_.size();
|
||||
|
||||
|
||||
data->new_file->mapped_sections.push_back(mapped_file_section(
|
||||
x.data->new_file->to_original_pos(i, begin),
|
||||
size, i->section_type));
|
||||
|
||||
x.data->new_file->to_original_pos(i, begin), size,
|
||||
i->section_type));
|
||||
|
||||
for (++i; i != x.data->new_file->mapped_sections.end() &&
|
||||
i->our_pos < end; ++i)
|
||||
{
|
||||
i->our_pos < end;
|
||||
++i) {
|
||||
data->new_file->mapped_sections.push_back(mapped_file_section(
|
||||
i->original_pos, i->our_pos - begin + size,
|
||||
i->section_type));
|
||||
}
|
||||
|
||||
|
||||
data->new_file->source_.append(
|
||||
x.data->new_file->source_.begin() + begin,
|
||||
x.data->new_file->source_.begin() + end);
|
||||
x.data->new_file->source_.begin() + end);
|
||||
}
|
||||
}
|
||||
|
||||
quickbook::string_view::size_type indentation_count(quickbook::string_view x)
|
||||
quickbook::string_view::size_type indentation_count(
|
||||
quickbook::string_view x)
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
for(string_iterator begin = x.begin(), end = x.end();
|
||||
begin != end; ++begin)
|
||||
{
|
||||
switch(*begin)
|
||||
{
|
||||
for (string_iterator begin = x.begin(), end = x.end(); begin != end;
|
||||
++begin) {
|
||||
switch (*begin) {
|
||||
case ' ':
|
||||
++count;
|
||||
break;
|
||||
@@ -500,7 +494,8 @@ namespace quickbook
|
||||
std::string const program(x.begin(), x.end());
|
||||
|
||||
// Erase leading blank lines and newlines:
|
||||
std::string::size_type text_start = program.find_first_not_of(" \t\r\n");
|
||||
std::string::size_type text_start =
|
||||
program.find_first_not_of(" \t\r\n");
|
||||
if (text_start == std::string::npos) return;
|
||||
|
||||
text_start = program.find_last_of("\r\n", text_start);
|
||||
@@ -509,7 +504,8 @@ namespace quickbook
|
||||
assert(text_start < program.size());
|
||||
|
||||
// Get the first line indentation
|
||||
std::string::size_type indent = program.find_first_not_of(" \t", text_start) - text_start;
|
||||
std::string::size_type indent =
|
||||
program.find_first_not_of(" \t", text_start) - text_start;
|
||||
quickbook::string_view::size_type full_indent = indentation_count(
|
||||
quickbook::string_view(&program[text_start], indent));
|
||||
|
||||
@@ -517,8 +513,8 @@ namespace quickbook
|
||||
|
||||
// Calculate the minimum indent from the rest of the lines
|
||||
// Detecting a mix of spaces and tabs.
|
||||
while (std::string::npos != (pos = program.find_first_of("\r\n", pos)))
|
||||
{
|
||||
while (std::string::npos !=
|
||||
(pos = program.find_first_of("\r\n", pos))) {
|
||||
pos = program.find_first_not_of("\r\n", pos);
|
||||
if (std::string::npos == pos) break;
|
||||
|
||||
@@ -528,9 +524,10 @@ namespace quickbook
|
||||
char ch = program[n];
|
||||
if (ch == '\r' || ch == '\n') continue; // ignore empty lines
|
||||
|
||||
indent = (std::min)(indent, n-pos);
|
||||
full_indent = (std::min)(full_indent, indentation_count(
|
||||
quickbook::string_view(&program[pos], n-pos)));
|
||||
indent = (std::min)(indent, n - pos);
|
||||
full_indent = (std::min)(
|
||||
full_indent, indentation_count(quickbook::string_view(
|
||||
&program[pos], n - pos)));
|
||||
}
|
||||
|
||||
// Detect if indentation is mixed.
|
||||
@@ -538,13 +535,13 @@ namespace quickbook
|
||||
quickbook::string_view first_indent(&program[text_start], indent);
|
||||
pos = text_start;
|
||||
|
||||
while (std::string::npos != (pos = program.find_first_of("\r\n", pos)))
|
||||
{
|
||||
while (std::string::npos !=
|
||||
(pos = program.find_first_of("\r\n", pos))) {
|
||||
pos = program.find_first_not_of("\r\n", pos);
|
||||
if (std::string::npos == pos) break;
|
||||
|
||||
std::string::size_type n = program.find_first_not_of(" \t", pos);
|
||||
if (n == std::string::npos || n-pos < indent) continue;
|
||||
if (n == std::string::npos || n - pos < indent) continue;
|
||||
|
||||
if (quickbook::string_view(&program[pos], indent) != first_indent) {
|
||||
mixed_indentation = true;
|
||||
@@ -558,20 +555,21 @@ namespace quickbook
|
||||
pos = text_start;
|
||||
|
||||
do {
|
||||
if (std::string::npos == (pos = program.find_first_not_of("\r\n", pos)))
|
||||
if (std::string::npos ==
|
||||
(pos = program.find_first_not_of("\r\n", pos)))
|
||||
break;
|
||||
|
||||
unindented_program.append(program.begin() + copy_start, program.begin() + pos);
|
||||
unindented_program.append(
|
||||
program.begin() + copy_start, program.begin() + pos);
|
||||
copy_start = pos;
|
||||
|
||||
// Find the end of the indentation.
|
||||
std::string::size_type next = program.find_first_not_of(" \t", pos);
|
||||
if (next == std::string::npos) next = program.size();
|
||||
|
||||
if (mixed_indentation)
|
||||
{
|
||||
string_view::size_type length = indentation_count(quickbook::string_view(
|
||||
&program[pos], next - pos));
|
||||
if (mixed_indentation) {
|
||||
string_view::size_type length = indentation_count(
|
||||
quickbook::string_view(&program[pos], next - pos));
|
||||
|
||||
if (length > full_indent) {
|
||||
std::string new_indentation(length - full_indent, ' ');
|
||||
@@ -580,14 +578,13 @@ namespace quickbook
|
||||
|
||||
copy_start = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
copy_start = (std::min)(pos + indent, next);
|
||||
}
|
||||
|
||||
pos = next;
|
||||
} while (std::string::npos !=
|
||||
(pos = program.find_first_of("\r\n", pos)));
|
||||
(pos = program.find_first_of("\r\n", pos)));
|
||||
|
||||
unindented_program.append(program.begin() + copy_start, program.end());
|
||||
|
||||
@@ -597,7 +594,8 @@ namespace quickbook
|
||||
|
||||
file_position mapped_file::position_of(string_iterator pos) const
|
||||
{
|
||||
return original->position_of(original->source().begin() +
|
||||
return original->position_of(
|
||||
original->source().begin() +
|
||||
to_original_pos(find_section(pos), pos - source().begin()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,15 +11,16 @@
|
||||
#if !defined(BOOST_QUICKBOOK_FILES_HPP)
|
||||
#define BOOST_QUICKBOOK_FILES_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <iosfwd>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include "string_view.hpp"
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace quickbook {
|
||||
namespace quickbook
|
||||
{
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
@@ -29,60 +30,71 @@ namespace quickbook {
|
||||
struct file_position
|
||||
{
|
||||
file_position() : line(1), column(1) {}
|
||||
file_position(std::ptrdiff_t l, std::ptrdiff_t c) : line(l), column(c) {}
|
||||
file_position(std::ptrdiff_t l, std::ptrdiff_t c) : line(l), column(c)
|
||||
{
|
||||
}
|
||||
|
||||
std::ptrdiff_t line;
|
||||
std::ptrdiff_t column;
|
||||
|
||||
|
||||
bool operator==(file_position const& other) const
|
||||
{
|
||||
return line == other.line && column == other.column;
|
||||
}
|
||||
|
||||
|
||||
friend std::ostream& operator<<(std::ostream&, file_position const&);
|
||||
};
|
||||
|
||||
struct file
|
||||
{
|
||||
private:
|
||||
private:
|
||||
// Non copyable
|
||||
file& operator=(file const&);
|
||||
file(file const&);
|
||||
public:
|
||||
|
||||
public:
|
||||
fs::path const path;
|
||||
std::string source_;
|
||||
bool is_code_snippets;
|
||||
private:
|
||||
|
||||
private:
|
||||
unsigned qbk_version;
|
||||
unsigned ref_count;
|
||||
public:
|
||||
|
||||
public:
|
||||
quickbook::string_view source() const { return source_; }
|
||||
|
||||
file(fs::path const& path_, quickbook::string_view source_view,
|
||||
unsigned qbk_version_) :
|
||||
path(path_),
|
||||
source_(source_view.begin(), source_view.end()),
|
||||
is_code_snippets(false),
|
||||
qbk_version(qbk_version_),
|
||||
ref_count(0)
|
||||
{}
|
||||
|
||||
explicit file(file const& f, quickbook::string_view s) :
|
||||
path(f.path), source_(s.begin(), s.end()),
|
||||
is_code_snippets(f.is_code_snippets),
|
||||
qbk_version(f.qbk_version), ref_count(0)
|
||||
{}
|
||||
|
||||
virtual ~file() {
|
||||
assert(!ref_count);
|
||||
file(
|
||||
fs::path const& path_,
|
||||
quickbook::string_view source_view,
|
||||
unsigned qbk_version_)
|
||||
: path(path_)
|
||||
, source_(source_view.begin(), source_view.end())
|
||||
, is_code_snippets(false)
|
||||
, qbk_version(qbk_version_)
|
||||
, ref_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned version() const {
|
||||
explicit file(file const& f, quickbook::string_view s)
|
||||
: path(f.path)
|
||||
, source_(s.begin(), s.end())
|
||||
, is_code_snippets(f.is_code_snippets)
|
||||
, qbk_version(f.qbk_version)
|
||||
, ref_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~file() { assert(!ref_count); }
|
||||
|
||||
unsigned version() const
|
||||
{
|
||||
assert(qbk_version);
|
||||
return qbk_version;
|
||||
}
|
||||
|
||||
void version(unsigned v) {
|
||||
void version(unsigned v)
|
||||
{
|
||||
// Check that either version hasn't been set, or it was
|
||||
// previously set to the same version (because the same
|
||||
// file has been loaded twice).
|
||||
@@ -95,17 +107,17 @@ namespace quickbook {
|
||||
friend void intrusive_ptr_add_ref(file* ptr) { ++ptr->ref_count; }
|
||||
|
||||
friend void intrusive_ptr_release(file* ptr)
|
||||
{ if(--ptr->ref_count == 0) delete ptr; }
|
||||
{
|
||||
if (--ptr->ref_count == 0) delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// If version isn't supplied then it must be set later.
|
||||
file_ptr load(fs::path const& filename,
|
||||
unsigned qbk_version = 0);
|
||||
file_ptr load(fs::path const& filename, unsigned qbk_version = 0);
|
||||
|
||||
struct load_error : std::runtime_error
|
||||
{
|
||||
explicit load_error(std::string const& arg)
|
||||
: std::runtime_error(arg) {}
|
||||
explicit load_error(std::string const& arg) : std::runtime_error(arg) {}
|
||||
};
|
||||
|
||||
// Interface for creating fake files which are mapped to
|
||||
@@ -133,7 +145,8 @@ namespace quickbook {
|
||||
void add(mapped_file_builder const&);
|
||||
void add(mapped_file_builder const&, pos_type, pos_type);
|
||||
void unindent_and_add(quickbook::string_view);
|
||||
private:
|
||||
|
||||
private:
|
||||
mapped_file_builder_data* data;
|
||||
|
||||
mapped_file_builder(mapped_file_builder const&);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace quickbook
|
||||
typedef boost::intrusive_ptr<file> file_ptr;
|
||||
typedef unsigned source_mode_type;
|
||||
|
||||
inline void ignore_variable(void const*) {}
|
||||
inline void ignore_variable(void const*) {}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
191
src/glob.cpp
191
src/glob.cpp
@@ -16,10 +16,13 @@ namespace quickbook
|
||||
void check_glob_range(glob_iterator&, glob_iterator);
|
||||
void check_glob_escape(glob_iterator&, glob_iterator);
|
||||
|
||||
bool match_section(glob_iterator& pattern_begin, glob_iterator pattern_end,
|
||||
glob_iterator& filename_begin, glob_iterator& filename_end);
|
||||
bool match_range(glob_iterator& pattern_begin, glob_iterator pattern_end,
|
||||
char x);
|
||||
bool match_section(
|
||||
glob_iterator& pattern_begin,
|
||||
glob_iterator pattern_end,
|
||||
glob_iterator& filename_begin,
|
||||
glob_iterator& filename_end);
|
||||
bool match_range(
|
||||
glob_iterator& pattern_begin, glob_iterator pattern_end, char x);
|
||||
|
||||
// Is pattern a glob or a plain file name?
|
||||
// Throws glob_error if pattern is an invalid glob.
|
||||
@@ -32,38 +35,37 @@ namespace quickbook
|
||||
glob_iterator end = pattern.end();
|
||||
|
||||
while (begin != end) {
|
||||
if (*begin < 32 || (*begin & 0x80))
|
||||
is_ascii = false;
|
||||
if (*begin < 32 || (*begin & 0x80)) is_ascii = false;
|
||||
|
||||
switch(*begin) {
|
||||
case '\\':
|
||||
check_glob_escape(begin, end);
|
||||
break;
|
||||
switch (*begin) {
|
||||
case '\\':
|
||||
check_glob_escape(begin, end);
|
||||
break;
|
||||
|
||||
case '[':
|
||||
check_glob_range(begin, end);
|
||||
is_glob = true;
|
||||
break;
|
||||
case '[':
|
||||
check_glob_range(begin, end);
|
||||
is_glob = true;
|
||||
break;
|
||||
|
||||
case ']':
|
||||
throw glob_error("uneven square brackets");
|
||||
case ']':
|
||||
throw glob_error("uneven square brackets");
|
||||
|
||||
case '?':
|
||||
is_glob = true;
|
||||
++begin;
|
||||
break;
|
||||
case '?':
|
||||
is_glob = true;
|
||||
++begin;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
is_glob = true;
|
||||
++begin;
|
||||
case '*':
|
||||
is_glob = true;
|
||||
++begin;
|
||||
|
||||
if (begin != end && *begin == '*') {
|
||||
throw glob_error("'**' not supported");
|
||||
}
|
||||
break;
|
||||
if (begin != end && *begin == '*') {
|
||||
throw glob_error("'**' not supported");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
++begin;
|
||||
default:
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,32 +80,31 @@ namespace quickbook
|
||||
assert(begin != end && *begin == '[');
|
||||
++begin;
|
||||
|
||||
if (*begin == ']')
|
||||
throw glob_error("empty range");
|
||||
if (*begin == ']') throw glob_error("empty range");
|
||||
|
||||
while (begin != end) {
|
||||
switch (*begin) {
|
||||
case '\\':
|
||||
++begin;
|
||||
case '\\':
|
||||
++begin;
|
||||
|
||||
if (begin == end) {
|
||||
throw glob_error("trailing escape");
|
||||
}
|
||||
else if (*begin == '\\' || *begin == '/') {
|
||||
throw glob_error("contains escaped slash");
|
||||
}
|
||||
if (begin == end) {
|
||||
throw glob_error("trailing escape");
|
||||
}
|
||||
else if (*begin == '\\' || *begin == '/') {
|
||||
throw glob_error("contains escaped slash");
|
||||
}
|
||||
|
||||
++begin;
|
||||
break;
|
||||
case '[':
|
||||
throw glob_error("nested square brackets");
|
||||
case ']':
|
||||
++begin;
|
||||
return;
|
||||
case '/':
|
||||
throw glob_error("slash in square brackets");
|
||||
default:
|
||||
++begin;
|
||||
++begin;
|
||||
break;
|
||||
case '[':
|
||||
throw glob_error("nested square brackets");
|
||||
case ']':
|
||||
++begin;
|
||||
return;
|
||||
case '/':
|
||||
throw glob_error("slash in square brackets");
|
||||
default:
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,8 +130,9 @@ namespace quickbook
|
||||
// Does filename match pattern?
|
||||
// Might throw glob_error if pattern is an invalid glob,
|
||||
// but should call check_glob first to validate the glob.
|
||||
bool glob(quickbook::string_view const& pattern,
|
||||
quickbook::string_view const& filename)
|
||||
bool glob(
|
||||
quickbook::string_view const& pattern,
|
||||
quickbook::string_view const& filename)
|
||||
{
|
||||
// If there wasn't this special case then '*' would match an
|
||||
// empty string.
|
||||
@@ -151,11 +153,14 @@ namespace quickbook
|
||||
|
||||
if (pattern_it == pattern_end) return true;
|
||||
|
||||
if (*pattern_it == '*') { throw glob_error("'**' not supported"); }
|
||||
if (*pattern_it == '*') {
|
||||
throw glob_error("'**' not supported");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (filename_it == filename_end) return false;
|
||||
if (match_section(pattern_it, pattern_end, filename_it, filename_end))
|
||||
if (match_section(
|
||||
pattern_it, pattern_end, filename_it, filename_end))
|
||||
break;
|
||||
++filename_it;
|
||||
}
|
||||
@@ -164,8 +169,11 @@ namespace quickbook
|
||||
return filename_it == filename_end;
|
||||
}
|
||||
|
||||
bool match_section(glob_iterator& pattern_begin, glob_iterator pattern_end,
|
||||
glob_iterator& filename_begin, glob_iterator& filename_end)
|
||||
bool match_section(
|
||||
glob_iterator& pattern_begin,
|
||||
glob_iterator pattern_end,
|
||||
glob_iterator& filename_begin,
|
||||
glob_iterator& filename_end)
|
||||
{
|
||||
glob_iterator pattern_it = pattern_begin;
|
||||
glob_iterator filename_it = filename_begin;
|
||||
@@ -173,33 +181,34 @@ namespace quickbook
|
||||
while (pattern_it != pattern_end && *pattern_it != '*') {
|
||||
if (filename_it == filename_end) return false;
|
||||
|
||||
switch(*pattern_it) {
|
||||
case '*':
|
||||
assert(false);
|
||||
throw new glob_error("Internal error");
|
||||
case '[':
|
||||
if (!match_range(pattern_it, pattern_end, *filename_it))
|
||||
return false;
|
||||
++filename_it;
|
||||
break;
|
||||
case ']':
|
||||
throw glob_error("uneven square brackets");
|
||||
case '?':
|
||||
++pattern_it;
|
||||
++filename_it;
|
||||
break;
|
||||
case '\\':
|
||||
++pattern_it;
|
||||
if (pattern_it == pattern_end) {
|
||||
throw glob_error("trailing escape");
|
||||
} else if (*pattern_it == '\\' || *pattern_it == '/') {
|
||||
throw glob_error("contains escaped slash");
|
||||
}
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
if (*pattern_it != *filename_it) return false;
|
||||
++pattern_it;
|
||||
++filename_it;
|
||||
switch (*pattern_it) {
|
||||
case '*':
|
||||
assert(false);
|
||||
throw new glob_error("Internal error");
|
||||
case '[':
|
||||
if (!match_range(pattern_it, pattern_end, *filename_it))
|
||||
return false;
|
||||
++filename_it;
|
||||
break;
|
||||
case ']':
|
||||
throw glob_error("uneven square brackets");
|
||||
case '?':
|
||||
++pattern_it;
|
||||
++filename_it;
|
||||
break;
|
||||
case '\\':
|
||||
++pattern_it;
|
||||
if (pattern_it == pattern_end) {
|
||||
throw glob_error("trailing escape");
|
||||
}
|
||||
else if (*pattern_it == '\\' || *pattern_it == '/') {
|
||||
throw glob_error("contains escaped slash");
|
||||
}
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
if (*pattern_it != *filename_it) return false;
|
||||
++pattern_it;
|
||||
++filename_it;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,8 +220,8 @@ namespace quickbook
|
||||
return true;
|
||||
}
|
||||
|
||||
bool match_range(glob_iterator& pattern_begin, glob_iterator pattern_end,
|
||||
char x)
|
||||
bool match_range(
|
||||
glob_iterator& pattern_begin, glob_iterator pattern_end, char x)
|
||||
{
|
||||
assert(pattern_begin != pattern_end && *pattern_begin == '[');
|
||||
++pattern_begin;
|
||||
@@ -229,7 +238,8 @@ namespace quickbook
|
||||
if (pattern_begin == pattern_end) {
|
||||
throw glob_error("uneven square brackets");
|
||||
}
|
||||
} else if (*pattern_begin == ']') {
|
||||
}
|
||||
else if (*pattern_begin == ']') {
|
||||
throw glob_error("empty range");
|
||||
}
|
||||
|
||||
@@ -254,7 +264,8 @@ namespace quickbook
|
||||
if (pattern_begin == pattern_end) {
|
||||
throw glob_error("uneven square brackets");
|
||||
}
|
||||
} else if (first == '/') {
|
||||
}
|
||||
else if (first == '/') {
|
||||
throw glob_error("slash in square brackets");
|
||||
}
|
||||
|
||||
@@ -286,7 +297,8 @@ namespace quickbook
|
||||
if (pattern_begin == pattern_end) {
|
||||
throw glob_error("uneven square brackets");
|
||||
}
|
||||
} else if (second == '/') {
|
||||
}
|
||||
else if (second == '/') {
|
||||
throw glob_error("slash in square brackets");
|
||||
}
|
||||
|
||||
@@ -297,8 +309,7 @@ namespace quickbook
|
||||
return invert_match != matched;
|
||||
}
|
||||
|
||||
std::size_t find_glob_char(quickbook::string_view pattern,
|
||||
std::size_t pos)
|
||||
std::size_t find_glob_char(quickbook::string_view pattern, std::size_t pos)
|
||||
{
|
||||
// Weird style is because quickbook::string_view's find_first_of
|
||||
// doesn't take a position argument.
|
||||
|
||||
13
src/glob.hpp
13
src/glob.hpp
@@ -6,25 +6,24 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "string_view.hpp"
|
||||
#include <stdexcept>
|
||||
#include "string_view.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
struct glob_error : std::runtime_error
|
||||
{
|
||||
explicit glob_error(char const* error) :
|
||||
std::runtime_error(error) {}
|
||||
explicit glob_error(char const* error) : std::runtime_error(error) {}
|
||||
};
|
||||
|
||||
// Is this path a glob? Throws glob_error if glob is invalid.
|
||||
bool check_glob(quickbook::string_view);
|
||||
|
||||
// pre: glob is valid (call check_glob first on user data).
|
||||
bool glob(quickbook::string_view const& pattern,
|
||||
quickbook::string_view const& filename);
|
||||
bool glob(
|
||||
quickbook::string_view const& pattern,
|
||||
quickbook::string_view const& filename);
|
||||
|
||||
std::size_t find_glob_char(quickbook::string_view,
|
||||
std::size_t start = 0);
|
||||
std::size_t find_glob_char(quickbook::string_view, std::size_t start = 0);
|
||||
std::string glob_unescape(quickbook::string_view);
|
||||
}
|
||||
|
||||
@@ -13,25 +13,21 @@
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
quickbook_grammar::quickbook_grammar(quickbook::state& s)
|
||||
quickbook_grammar::quickbook_grammar(quickbook::state& s)
|
||||
: impl_(new impl(s))
|
||||
, command_line_macro(impl_->command_line, "command_line_macro")
|
||||
, inline_phrase(impl_->inline_phrase, "inline_phrase")
|
||||
, phrase_start(impl_->phrase_start, "phrase")
|
||||
, block_start(impl_->block_start, "block")
|
||||
, attribute_template_body(impl_->attribute_template_body,
|
||||
"attribute_template_body")
|
||||
, attribute_template_body(
|
||||
impl_->attribute_template_body, "attribute_template_body")
|
||||
, doc_info(impl_->doc_info_details, "doc_info")
|
||||
{
|
||||
}
|
||||
|
||||
quickbook_grammar::~quickbook_grammar()
|
||||
{
|
||||
}
|
||||
|
||||
quickbook_grammar::impl::impl(quickbook::state& s)
|
||||
: state(s)
|
||||
, cleanup_()
|
||||
quickbook_grammar::~quickbook_grammar() {}
|
||||
|
||||
quickbook_grammar::impl::impl(quickbook::state& s) : state(s), cleanup_()
|
||||
{
|
||||
init_main();
|
||||
init_block_elements();
|
||||
|
||||
@@ -22,23 +22,30 @@ namespace quickbook
|
||||
// spirit implementation detail, but since classic is no longer under
|
||||
// development, it won't change. And spirit 2 won't require such a hack.
|
||||
|
||||
typedef cl::scanner<parse_iterator, cl::scanner_policies <
|
||||
cl::iteration_policy, cl::match_policy, cl::action_policy> > scanner;
|
||||
typedef cl::scanner<
|
||||
parse_iterator,
|
||||
cl::scanner_policies<
|
||||
cl::iteration_policy,
|
||||
cl::match_policy,
|
||||
cl::action_policy> >
|
||||
scanner;
|
||||
|
||||
template <typename Scanner>
|
||||
struct Scanner_must_be_the_quickbook_scanner_typedef;
|
||||
template <>
|
||||
struct Scanner_must_be_the_quickbook_scanner_typedef<scanner> {};
|
||||
template <> struct Scanner_must_be_the_quickbook_scanner_typedef<scanner>
|
||||
{
|
||||
};
|
||||
|
||||
struct grammar
|
||||
: public cl::grammar<grammar>
|
||||
struct grammar : public cl::grammar<grammar>
|
||||
{
|
||||
grammar(cl::rule<scanner> const& start_rule_, char const* /* name */)
|
||||
: start_rule(start_rule_) {}
|
||||
: start_rule(start_rule_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Scanner>
|
||||
struct definition :
|
||||
Scanner_must_be_the_quickbook_scanner_typedef<Scanner>
|
||||
struct definition
|
||||
: Scanner_must_be_the_quickbook_scanner_typedef<Scanner>
|
||||
{
|
||||
definition(grammar const& self) : start_rule(self.start_rule) {}
|
||||
cl::rule<scanner> const& start() const { return start_rule; }
|
||||
@@ -50,13 +57,13 @@ namespace quickbook
|
||||
|
||||
struct quickbook_grammar
|
||||
{
|
||||
public:
|
||||
public:
|
||||
struct impl;
|
||||
|
||||
private:
|
||||
private:
|
||||
boost::scoped_ptr<impl> impl_;
|
||||
|
||||
public:
|
||||
public:
|
||||
grammar command_line_macro;
|
||||
grammar inline_phrase;
|
||||
grammar phrase_start;
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_GRAMMARS_IMPL_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_GRAMMARS_IMPL_HPP
|
||||
|
||||
#include "grammar.hpp"
|
||||
#include "cleanup.hpp"
|
||||
#include "values.hpp"
|
||||
#include <boost/spirit/include/classic_symbols.hpp>
|
||||
#include "cleanup.hpp"
|
||||
#include "grammar.hpp"
|
||||
#include "values.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -32,7 +32,8 @@ namespace quickbook
|
||||
// - whether they end a paragraph
|
||||
// - how following newlines are interpreted by the grammar.
|
||||
// - and possibly other things.....
|
||||
enum type_enum {
|
||||
enum type_enum
|
||||
{
|
||||
// Used when there's no element.
|
||||
nothing = 0,
|
||||
|
||||
@@ -43,9 +44,9 @@ namespace quickbook
|
||||
// but not nested.
|
||||
conditional_or_block = 2,
|
||||
|
||||
// Block elements that can be nested in other elements.
|
||||
// Block elements that can be nested in other elements.
|
||||
nested_block = 4,
|
||||
|
||||
|
||||
// Phrase elements.
|
||||
phrase = 8,
|
||||
|
||||
@@ -65,17 +66,18 @@ namespace quickbook
|
||||
|
||||
// Masks to determine which context elements can be used in (in_*), and
|
||||
// whether they are consided to be a block element (is_*).
|
||||
enum context {
|
||||
enum context
|
||||
{
|
||||
// At the top level we allow everything.
|
||||
in_top_level = phrase | maybe_block | nested_block |
|
||||
conditional_or_block | section_block,
|
||||
conditional_or_block | section_block,
|
||||
|
||||
// In conditional phrases and list blocks we everything but section
|
||||
// elements.
|
||||
in_conditional = phrase | maybe_block | nested_block |
|
||||
conditional_or_block,
|
||||
in_list_block = phrase | maybe_block | nested_block |
|
||||
conditional_or_block,
|
||||
in_conditional =
|
||||
phrase | maybe_block | nested_block | conditional_or_block,
|
||||
in_list_block =
|
||||
phrase | maybe_block | nested_block | conditional_or_block,
|
||||
|
||||
// In nested blocks we allow a more limited range of elements.
|
||||
in_nested_block = phrase | maybe_block | nested_block,
|
||||
@@ -86,21 +88,22 @@ namespace quickbook
|
||||
|
||||
// At the start of a block these are all block elements.
|
||||
is_contextual_block = maybe_block | nested_block |
|
||||
conditional_or_block | section_block,
|
||||
conditional_or_block | section_block,
|
||||
|
||||
// These are all block elements in all other contexts.
|
||||
is_block = nested_block | conditional_or_block | section_block
|
||||
};
|
||||
|
||||
element_info()
|
||||
: type(nothing), rule(), tag(0) {}
|
||||
element_info() : type(nothing), rule(), tag(0) {}
|
||||
|
||||
element_info(
|
||||
type_enum t,
|
||||
cl::rule<scanner>* r,
|
||||
value::tag_type tag_ = value::default_tag,
|
||||
unsigned int v = 0)
|
||||
: type(t), rule(r), tag(tag_), qbk_version(v) {}
|
||||
type_enum t,
|
||||
cl::rule<scanner>* r,
|
||||
value::tag_type tag_ = value::default_tag,
|
||||
unsigned int v = 0)
|
||||
: type(t), rule(r), tag(tag_), qbk_version(v)
|
||||
{
|
||||
}
|
||||
|
||||
type_enum type;
|
||||
cl::rule<scanner>* rule;
|
||||
@@ -137,25 +140,24 @@ namespace quickbook
|
||||
// the end of an itendifier.
|
||||
cl::rule<scanner> space; // Space/tab/newline/comment (possibly empty)
|
||||
cl::rule<scanner> blank; // Space/tab/comment (possibly empty)
|
||||
cl::rule<scanner> eol; // blank >> eol
|
||||
cl::rule<scanner> eol; // blank >> eol
|
||||
cl::rule<scanner> phrase_end; // End of phrase text, context sensitive
|
||||
cl::rule<scanner> comment;
|
||||
cl::rule<scanner> line_comment;
|
||||
cl::rule<scanner> macro_identifier;
|
||||
|
||||
// Element Symbols
|
||||
// Element Symbols
|
||||
cl::symbols<element_info> elements;
|
||||
|
||||
// Source mode
|
||||
cl::symbols<source_mode_type> source_modes;
|
||||
|
||||
|
||||
// Doc Info
|
||||
cl::rule<scanner> doc_info_details;
|
||||
|
||||
|
||||
impl(quickbook::state&);
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
void init_main();
|
||||
void init_block_elements();
|
||||
void init_phrase_elements();
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
=============================================================================*/
|
||||
|
||||
#include <cctype>
|
||||
#include "document_state_impl.hpp"
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "document_state_impl.hpp"
|
||||
|
||||
namespace quickbook {
|
||||
namespace quickbook
|
||||
{
|
||||
//
|
||||
// The maximum size of a generated part of an id.
|
||||
//
|
||||
@@ -24,13 +25,16 @@ namespace quickbook {
|
||||
static const std::size_t max_size = 32;
|
||||
|
||||
typedef std::vector<id_placeholder const*> placeholder_index;
|
||||
placeholder_index index_placeholders(document_state_impl const&, quickbook::string_view);
|
||||
placeholder_index index_placeholders(
|
||||
document_state_impl const&, quickbook::string_view);
|
||||
|
||||
void generate_id_block(
|
||||
placeholder_index::iterator, placeholder_index::iterator,
|
||||
std::vector<std::string>& generated_ids);
|
||||
placeholder_index::iterator,
|
||||
placeholder_index::iterator,
|
||||
std::vector<std::string>& generated_ids);
|
||||
|
||||
std::vector<std::string> generate_ids(document_state_impl const& state, quickbook::string_view xml)
|
||||
std::vector<std::string> generate_ids(
|
||||
document_state_impl const& state, quickbook::string_view xml)
|
||||
{
|
||||
std::vector<std::string> generated_ids(state.placeholders.size());
|
||||
|
||||
@@ -49,7 +53,8 @@ namespace quickbook {
|
||||
//
|
||||
// So find the group of placeholders with the same number of dots.
|
||||
iterator group_begin = it, group_end = it;
|
||||
while (group_end != end && (*group_end)->num_dots == (*it)->num_dots)
|
||||
while (group_end != end &&
|
||||
(*group_end)->num_dots == (*it)->num_dots)
|
||||
++group_end;
|
||||
|
||||
generate_id_block(group_begin, group_end, generated_ids);
|
||||
@@ -77,12 +82,15 @@ namespace quickbook {
|
||||
bool x_explicit = x->category.c >= id_category::explicit_id;
|
||||
bool y_explicit = y->category.c >= id_category::explicit_id;
|
||||
|
||||
return
|
||||
x->num_dots < y->num_dots ? true :
|
||||
x->num_dots > y->num_dots ? false :
|
||||
x_explicit > y_explicit ? true :
|
||||
x_explicit < y_explicit ? false :
|
||||
order[x->index] < order[y->index];
|
||||
return x->num_dots < y->num_dots
|
||||
? true
|
||||
: x->num_dots > y->num_dots
|
||||
? false
|
||||
: x_explicit > y_explicit
|
||||
? true
|
||||
: x_explicit < y_explicit
|
||||
? false
|
||||
: order[x->index] < order[y->index];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,12 +100,11 @@ namespace quickbook {
|
||||
std::vector<unsigned>& order;
|
||||
unsigned count;
|
||||
|
||||
get_placeholder_order_callback(document_state_impl const& state_,
|
||||
std::vector<unsigned>& order_)
|
||||
: state(state_),
|
||||
order(order_),
|
||||
count(0)
|
||||
{}
|
||||
get_placeholder_order_callback(
|
||||
document_state_impl const& state_, std::vector<unsigned>& order_)
|
||||
: state(state_), order(order_), count(0)
|
||||
{
|
||||
}
|
||||
|
||||
void id_value(quickbook::string_view value)
|
||||
{
|
||||
@@ -114,8 +121,7 @@ namespace quickbook {
|
||||
};
|
||||
|
||||
placeholder_index index_placeholders(
|
||||
document_state_impl const& state,
|
||||
quickbook::string_view xml)
|
||||
document_state_impl const& state, quickbook::string_view xml)
|
||||
{
|
||||
// The order that the placeholder appear in the xml source.
|
||||
std::vector<unsigned> order(state.placeholders.size());
|
||||
@@ -126,7 +132,7 @@ namespace quickbook {
|
||||
|
||||
placeholder_index sorted_placeholders;
|
||||
sorted_placeholders.reserve(state.placeholders.size());
|
||||
BOOST_FOREACH(id_placeholder const& p, state.placeholders)
|
||||
BOOST_FOREACH (id_placeholder const& p, state.placeholders)
|
||||
if (order[p.index]) sorted_placeholders.push_back(&p);
|
||||
boost::sort(sorted_placeholders, placeholder_compare(order));
|
||||
|
||||
@@ -143,26 +149,30 @@ namespace quickbook {
|
||||
chosen_id_map chosen_ids;
|
||||
std::vector<std::string>& generated_ids;
|
||||
|
||||
explicit generate_id_block_type(std::vector<std::string>& generated_ids_) :
|
||||
generated_ids(generated_ids_) {}
|
||||
explicit generate_id_block_type(
|
||||
std::vector<std::string>& generated_ids_)
|
||||
: generated_ids(generated_ids_)
|
||||
{
|
||||
}
|
||||
|
||||
void generate(placeholder_index::iterator begin,
|
||||
placeholder_index::iterator end);
|
||||
void generate(
|
||||
placeholder_index::iterator begin, placeholder_index::iterator end);
|
||||
|
||||
std::string resolve_id(id_placeholder const*);
|
||||
std::string generate_id(id_placeholder const*, std::string const&);
|
||||
};
|
||||
|
||||
void generate_id_block(placeholder_index::iterator begin,
|
||||
placeholder_index::iterator end,
|
||||
std::vector<std::string>& generated_ids)
|
||||
void generate_id_block(
|
||||
placeholder_index::iterator begin,
|
||||
placeholder_index::iterator end,
|
||||
std::vector<std::string>& generated_ids)
|
||||
{
|
||||
generate_id_block_type impl(generated_ids);
|
||||
impl.generate(begin, end);
|
||||
}
|
||||
|
||||
void generate_id_block_type::generate(placeholder_index::iterator begin,
|
||||
placeholder_index::iterator end)
|
||||
void generate_id_block_type::generate(
|
||||
placeholder_index::iterator begin, placeholder_index::iterator end)
|
||||
{
|
||||
std::vector<std::string> resolved_ids;
|
||||
|
||||
@@ -170,18 +180,15 @@ namespace quickbook {
|
||||
resolved_ids.push_back(resolve_id(*i));
|
||||
|
||||
unsigned index = 0;
|
||||
for (placeholder_index::iterator i = begin; i != end; ++i, ++index)
|
||||
{
|
||||
generated_ids[(**i).index] =
|
||||
generate_id(*i, resolved_ids[index]);
|
||||
for (placeholder_index::iterator i = begin; i != end; ++i, ++index) {
|
||||
generated_ids[(**i).index] = generate_id(*i, resolved_ids[index]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string generate_id_block_type::resolve_id(id_placeholder const* p)
|
||||
{
|
||||
std::string id = p->parent ?
|
||||
generated_ids[p->parent->index] + "." + p->id :
|
||||
p->id;
|
||||
std::string id =
|
||||
p->parent ? generated_ids[p->parent->index] + "." + p->id : p->id;
|
||||
|
||||
if (p->category.c > id_category::numbered) {
|
||||
// Reserve the id if it isn't already reserved.
|
||||
@@ -189,19 +196,17 @@ namespace quickbook {
|
||||
|
||||
// If it was reserved by a placeholder with a lower category,
|
||||
// then overwrite it.
|
||||
if (p->category.c > pos->second->category.c)
|
||||
pos->second = p;
|
||||
if (p->category.c > pos->second->category.c) pos->second = p;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string generate_id_block_type::generate_id(id_placeholder const* p,
|
||||
std::string const& resolved_id)
|
||||
std::string generate_id_block_type::generate_id(
|
||||
id_placeholder const* p, std::string const& resolved_id)
|
||||
{
|
||||
if (p->category.c > id_category::numbered &&
|
||||
chosen_ids.at(resolved_id) == p)
|
||||
{
|
||||
chosen_ids.at(resolved_id) == p) {
|
||||
return resolved_id;
|
||||
}
|
||||
|
||||
@@ -217,8 +222,8 @@ namespace quickbook {
|
||||
}
|
||||
else {
|
||||
parent_id = resolved_id.substr(0, child_start + 1);
|
||||
base_id = normalize_id(resolved_id.substr(child_start + 1),
|
||||
max_size - 1);
|
||||
base_id =
|
||||
normalize_id(resolved_id.substr(child_start + 1), max_size - 1);
|
||||
}
|
||||
|
||||
// Since we're adding digits, don't want an id that ends in
|
||||
@@ -232,7 +237,7 @@ namespace quickbook {
|
||||
++length;
|
||||
}
|
||||
else {
|
||||
while (length > 0 && std::isdigit(base_id[length -1]))
|
||||
while (length > 0 && std::isdigit(base_id[length - 1]))
|
||||
--length;
|
||||
base_id.erase(length);
|
||||
}
|
||||
@@ -240,10 +245,8 @@ namespace quickbook {
|
||||
|
||||
unsigned count = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
std::string postfix =
|
||||
boost::lexical_cast<std::string>(count++);
|
||||
for (;;) {
|
||||
std::string postfix = boost::lexical_cast<std::string>(count++);
|
||||
|
||||
if ((base_id.size() + postfix.size()) > max_size) {
|
||||
// The id is now too long, so reduce the length and
|
||||
@@ -256,7 +259,7 @@ namespace quickbook {
|
||||
--length;
|
||||
|
||||
// Trim any trailing digits.
|
||||
while (length > 0 && std::isdigit(base_id[length -1]))
|
||||
while (length > 0 && std::isdigit(base_id[length - 1]))
|
||||
--length;
|
||||
|
||||
base_id.erase(length);
|
||||
@@ -287,25 +290,20 @@ namespace quickbook {
|
||||
string_iterator source_pos;
|
||||
std::string result;
|
||||
|
||||
replace_ids_callback(document_state_impl const& state_,
|
||||
std::vector<std::string> const* ids_)
|
||||
: state(state_),
|
||||
ids(ids_),
|
||||
source_pos(),
|
||||
result()
|
||||
{}
|
||||
|
||||
void start(quickbook::string_view xml)
|
||||
replace_ids_callback(
|
||||
document_state_impl const& state_,
|
||||
std::vector<std::string> const* ids_)
|
||||
: state(state_), ids(ids_), source_pos(), result()
|
||||
{
|
||||
source_pos = xml.begin();
|
||||
}
|
||||
|
||||
void start(quickbook::string_view xml) { source_pos = xml.begin(); }
|
||||
|
||||
void id_value(quickbook::string_view value)
|
||||
{
|
||||
if (id_placeholder const* p = state.get_placeholder(value))
|
||||
{
|
||||
quickbook::string_view id = ids ?
|
||||
(*ids)[p->index] : p->unresolved_id;
|
||||
if (id_placeholder const* p = state.get_placeholder(value)) {
|
||||
quickbook::string_view id =
|
||||
ids ? (*ids)[p->index] : p->unresolved_id;
|
||||
|
||||
result.append(source_pos, value.begin());
|
||||
result.append(id.begin(), id.end());
|
||||
@@ -320,8 +318,10 @@ namespace quickbook {
|
||||
}
|
||||
};
|
||||
|
||||
std::string replace_ids(document_state_impl const& state, quickbook::string_view xml,
|
||||
std::vector<std::string> const* ids)
|
||||
std::string replace_ids(
|
||||
document_state_impl const& state,
|
||||
quickbook::string_view xml,
|
||||
std::vector<std::string> const* ids)
|
||||
{
|
||||
xml_processor processor;
|
||||
replace_ids_callback callback(state, ids);
|
||||
@@ -359,7 +359,7 @@ namespace quickbook {
|
||||
if (id[src] == '_') {
|
||||
do {
|
||||
++src;
|
||||
} while(src < id.length() && id[src] == '_');
|
||||
} while (src < id.length() && id[src] == '_');
|
||||
|
||||
if (src < id.length()) id[dst++] = '_';
|
||||
}
|
||||
|
||||
@@ -6,28 +6,23 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include "document_state_impl.hpp"
|
||||
#include "utils.hpp"
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
namespace
|
||||
{
|
||||
char const* id_attributes_[] =
|
||||
{
|
||||
"id",
|
||||
"linkend",
|
||||
"linkends",
|
||||
"arearefs"
|
||||
};
|
||||
char const* id_attributes_[] = {"id", "linkend", "linkends",
|
||||
"arearefs"};
|
||||
}
|
||||
|
||||
xml_processor::xml_processor()
|
||||
{
|
||||
static std::size_t const n_id_attributes = sizeof(id_attributes_)/sizeof(char const*);
|
||||
for (int i = 0; i != n_id_attributes; ++i)
|
||||
{
|
||||
static std::size_t const n_id_attributes =
|
||||
sizeof(id_attributes_) / sizeof(char const*);
|
||||
for (int i = 0; i != n_id_attributes; ++i) {
|
||||
id_attributes.push_back(id_attributes_[i]);
|
||||
}
|
||||
|
||||
@@ -37,26 +32,26 @@ namespace quickbook
|
||||
template <typename Iterator>
|
||||
bool read(Iterator& it, Iterator end, char const* text)
|
||||
{
|
||||
for(Iterator it2 = it;; ++it2, ++text) {
|
||||
for (Iterator it2 = it;; ++it2, ++text) {
|
||||
if (!*text) {
|
||||
it = it2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (it2 == end || *it2 != *text)
|
||||
return false;
|
||||
if (it2 == end || *it2 != *text) return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void read_past(Iterator& it, Iterator end, char const* text)
|
||||
{
|
||||
while (it != end && !read(it, end, text)) ++it;
|
||||
while (it != end && !read(it, end, text))
|
||||
++it;
|
||||
}
|
||||
|
||||
bool find_char(char const* text, char c)
|
||||
{
|
||||
for(;*text; ++text)
|
||||
for (; *text; ++text)
|
||||
if (c == *text) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -64,13 +59,15 @@ namespace quickbook
|
||||
template <typename Iterator>
|
||||
void read_some_of(Iterator& it, Iterator end, char const* text)
|
||||
{
|
||||
while(it != end && find_char(text, *it)) ++it;
|
||||
while (it != end && find_char(text, *it))
|
||||
++it;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void read_to_one_of(Iterator& it, Iterator end, char const* text)
|
||||
{
|
||||
while(it != end && !find_char(text, *it)) ++it;
|
||||
while (it != end && !find_char(text, *it))
|
||||
++it;
|
||||
}
|
||||
|
||||
void xml_processor::parse(quickbook::string_view source, callback& c)
|
||||
@@ -81,19 +78,16 @@ namespace quickbook
|
||||
|
||||
iterator it = source.begin(), end = source.end();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
for (;;) {
|
||||
read_past(it, end, "<");
|
||||
if (it == end) break;
|
||||
|
||||
if (read(it, end, "!--quickbook-escape-prefix-->"))
|
||||
{
|
||||
if (read(it, end, "!--quickbook-escape-prefix-->")) {
|
||||
read_past(it, end, "<!--quickbook-escape-postfix-->");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(*it)
|
||||
{
|
||||
switch (*it) {
|
||||
case '?':
|
||||
++it;
|
||||
read_past(it, end, "?>");
|
||||
@@ -107,10 +101,8 @@ namespace quickbook
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((*it >= 'a' && *it <= 'z') ||
|
||||
(*it >= 'A' && *it <= 'Z') ||
|
||||
*it == '_' || *it == ':')
|
||||
{
|
||||
if ((*it >= 'a' && *it <= 'z') || (*it >= 'A' && *it <= 'Z') ||
|
||||
*it == '_' || *it == ':') {
|
||||
read_to_one_of(it, end, " \t\n\r>");
|
||||
|
||||
for (;;) {
|
||||
@@ -118,7 +110,8 @@ namespace quickbook
|
||||
iterator name_start = it;
|
||||
read_to_one_of(it, end, "= \t\n\r>");
|
||||
if (it == end || *it == '>') break;
|
||||
quickbook::string_view name(name_start, it - name_start);
|
||||
quickbook::string_view name(
|
||||
name_start, it - name_start);
|
||||
++it;
|
||||
|
||||
read_some_of(it, end, "= \t\n\r");
|
||||
@@ -131,18 +124,17 @@ namespace quickbook
|
||||
|
||||
it = std::find(it, end, delim);
|
||||
if (it == end) break;
|
||||
quickbook::string_view value(value_start, it - value_start);
|
||||
quickbook::string_view value(
|
||||
value_start, it - value_start);
|
||||
++it;
|
||||
|
||||
if (boost::find(id_attributes, name.to_s())
|
||||
!= id_attributes.end())
|
||||
{
|
||||
if (boost::find(id_attributes, name.to_s()) !=
|
||||
id_attributes.end()) {
|
||||
c.id_value(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
read_past(it, end, ">");
|
||||
}
|
||||
}
|
||||
@@ -151,8 +143,10 @@ namespace quickbook
|
||||
c.finish(source);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
std::string linkify(quickbook::string_view source, quickbook::string_view linkend)
|
||||
namespace detail
|
||||
{
|
||||
std::string linkify(
|
||||
quickbook::string_view source, quickbook::string_view linkend)
|
||||
{
|
||||
typedef string_iterator iterator;
|
||||
|
||||
@@ -160,13 +154,11 @@ namespace quickbook
|
||||
|
||||
bool contains_link = false;
|
||||
|
||||
for(;!contains_link;)
|
||||
{
|
||||
for (; !contains_link;) {
|
||||
read_past(it, end, "<");
|
||||
if (it == end) break;
|
||||
|
||||
switch(*it)
|
||||
{
|
||||
switch (*it) {
|
||||
case '?':
|
||||
++it;
|
||||
read_past(it, end, "?>");
|
||||
@@ -175,20 +167,23 @@ namespace quickbook
|
||||
case '!':
|
||||
if (read(it, end, "!--")) {
|
||||
read_past(it, end, "-->");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
read_past(it, end, ">");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((*it >= 'a' && *it <= 'z') ||
|
||||
(*it >= 'A' && *it <= 'Z') ||
|
||||
*it == '_' || *it == ':')
|
||||
{
|
||||
(*it >= 'A' && *it <= 'Z') || *it == '_' ||
|
||||
*it == ':') {
|
||||
iterator tag_name_start = it;
|
||||
read_to_one_of(it, end, " \t\n\r>");
|
||||
quickbook::string_view tag_name(tag_name_start, it - tag_name_start);
|
||||
if (tag_name == "link") { contains_link = true; }
|
||||
quickbook::string_view tag_name(
|
||||
tag_name_start, it - tag_name_start);
|
||||
if (tag_name == "link") {
|
||||
contains_link = true;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
read_to_one_of(it, end, "\"'\n\r>");
|
||||
@@ -202,8 +197,7 @@ namespace quickbook
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
read_past(it, end, ">");
|
||||
}
|
||||
}
|
||||
@@ -217,7 +211,8 @@ namespace quickbook
|
||||
result += "\">";
|
||||
result.append(source.begin(), source.end());
|
||||
result += "</link>";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
result.append(source.begin(), source.end());
|
||||
}
|
||||
|
||||
|
||||
@@ -9,17 +9,17 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "stream.hpp"
|
||||
#include "glob.hpp"
|
||||
#include "include_paths.hpp"
|
||||
#include "path.hpp"
|
||||
#include "state.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "quickbook.hpp" // For the include_path global (yuck)
|
||||
#include <cassert>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/range/algorithm/replace.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <cassert>
|
||||
#include "glob.hpp"
|
||||
#include "path.hpp"
|
||||
#include "quickbook.hpp" // For the include_path global (yuck)
|
||||
#include "state.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -31,8 +31,7 @@ namespace quickbook
|
||||
{
|
||||
if (qbk_version_n >= 107u) {
|
||||
std::string path_text = path.get_encoded();
|
||||
if (path_text.empty())
|
||||
{
|
||||
if (path_text.empty()) {
|
||||
detail::outerr(path.get_file(), path.get_position())
|
||||
<< "Empty path argument"
|
||||
<< "std::endl";
|
||||
@@ -45,13 +44,12 @@ namespace quickbook
|
||||
return path_parameter(path_text, path_parameter::glob);
|
||||
}
|
||||
else {
|
||||
return path_parameter(glob_unescape(path_text),
|
||||
path_parameter::path);
|
||||
return path_parameter(
|
||||
glob_unescape(path_text), path_parameter::path);
|
||||
}
|
||||
} catch(glob_error& e) {
|
||||
} catch (glob_error& e) {
|
||||
detail::outerr(path.get_file(), path.get_position())
|
||||
<< "Invalid path (" << e.what() << "): "
|
||||
<< path_text
|
||||
<< "Invalid path (" << e.what() << "): " << path_text
|
||||
<< std::endl;
|
||||
++state.error_count;
|
||||
return path_parameter(path_text, path_parameter::invalid);
|
||||
@@ -64,14 +62,13 @@ namespace quickbook
|
||||
//
|
||||
// Counter-intuitively: encoded == plain text here.
|
||||
|
||||
std::string path_text = qbk_version_n >= 106u || path.is_encoded() ?
|
||||
path.get_encoded() : path.get_quickbook().to_s();
|
||||
std::string path_text = qbk_version_n >= 106u || path.is_encoded()
|
||||
? path.get_encoded()
|
||||
: path.get_quickbook().to_s();
|
||||
|
||||
if (path_text.empty())
|
||||
{
|
||||
if (path_text.empty()) {
|
||||
detail::outerr(path.get_file(), path.get_position())
|
||||
<< "Empty path argument"
|
||||
<< std::endl;
|
||||
<< "Empty path argument" << std::endl;
|
||||
++state.error_count;
|
||||
return path_parameter(path_text, path_parameter::invalid);
|
||||
}
|
||||
@@ -79,8 +76,7 @@ namespace quickbook
|
||||
// Check for windows paths, an error in quickbook 1.6
|
||||
// In quickbook 1.7 backslash is used as an escape character
|
||||
// for glob characters.
|
||||
if (path_text.find('\\') != std::string::npos)
|
||||
{
|
||||
if (path_text.find('\\') != std::string::npos) {
|
||||
quickbook::detail::ostream* err;
|
||||
|
||||
if (qbk_version_n >= 106u) {
|
||||
@@ -88,13 +84,12 @@ namespace quickbook
|
||||
++state.error_count;
|
||||
}
|
||||
else {
|
||||
err = &detail::outwarn(path.get_file(), path.get_position());
|
||||
err =
|
||||
&detail::outwarn(path.get_file(), path.get_position());
|
||||
}
|
||||
|
||||
*err << "Path isn't portable: '"
|
||||
<< path_text
|
||||
<< "'"
|
||||
<< std::endl;
|
||||
*err << "Path isn't portable: '" << path_text << "'"
|
||||
<< std::endl;
|
||||
|
||||
boost::replace(path_text, '\\', '/');
|
||||
}
|
||||
@@ -109,8 +104,7 @@ namespace quickbook
|
||||
|
||||
if (parameter.type == path_parameter::glob) {
|
||||
detail::outerr(p.get_file(), p.get_position())
|
||||
<< "Glob used for xml path."
|
||||
<< std::endl;
|
||||
<< "Glob used for xml path." << std::endl;
|
||||
++state.error_count;
|
||||
parameter.type = path_parameter::invalid;
|
||||
}
|
||||
@@ -122,18 +116,18 @@ namespace quickbook
|
||||
// Search include path
|
||||
//
|
||||
|
||||
void include_search_glob(std::set<quickbook_path> & result,
|
||||
void include_search_glob(
|
||||
std::set<quickbook_path>& result,
|
||||
quickbook_path const& location,
|
||||
std::string path, quickbook::state& state)
|
||||
std::string path,
|
||||
quickbook::state& state)
|
||||
{
|
||||
std::size_t glob_pos = find_glob_char(path);
|
||||
|
||||
if (glob_pos == std::string::npos)
|
||||
{
|
||||
if (glob_pos == std::string::npos) {
|
||||
quickbook_path complete_path = location / glob_unescape(path);
|
||||
|
||||
if (fs::exists(complete_path.file_path))
|
||||
{
|
||||
if (fs::exists(complete_path.file_path)) {
|
||||
state.dependencies.add_glob_match(complete_path.file_path);
|
||||
result.insert(complete_path);
|
||||
}
|
||||
@@ -155,17 +149,16 @@ namespace quickbook
|
||||
if (next != std::string::npos) ++next;
|
||||
|
||||
quickbook::string_view glob(
|
||||
path.data() + glob_begin,
|
||||
glob_end - glob_begin);
|
||||
path.data() + glob_begin, glob_end - glob_begin);
|
||||
|
||||
fs::path base_dir = new_location.file_path.empty() ?
|
||||
fs::path(".") : new_location.file_path;
|
||||
fs::path base_dir = new_location.file_path.empty()
|
||||
? fs::path(".")
|
||||
: new_location.file_path;
|
||||
if (!fs::is_directory(base_dir)) return;
|
||||
|
||||
// Walk through the dir for matches.
|
||||
for (fs::directory_iterator dir_i(base_dir), dir_e;
|
||||
dir_i != dir_e; ++dir_i)
|
||||
{
|
||||
for (fs::directory_iterator dir_i(base_dir), dir_e; dir_i != dir_e;
|
||||
++dir_i) {
|
||||
fs::path f = dir_i->path().filename();
|
||||
std::string generic_path = detail::path_to_generic(f);
|
||||
|
||||
@@ -173,34 +166,33 @@ namespace quickbook
|
||||
if (!quickbook::glob(glob, generic_path)) continue;
|
||||
|
||||
// If it's a file we add it to the results.
|
||||
if (next == std::string::npos)
|
||||
{
|
||||
if (fs::is_regular_file(dir_i->status()))
|
||||
{
|
||||
if (next == std::string::npos) {
|
||||
if (fs::is_regular_file(dir_i->status())) {
|
||||
quickbook_path r = new_location / generic_path;
|
||||
state.dependencies.add_glob_match(r.file_path);
|
||||
result.insert(r);
|
||||
}
|
||||
}
|
||||
// If it's a matching dir, we recurse looking for more files.
|
||||
else
|
||||
{
|
||||
if (!fs::is_regular_file(dir_i->status()))
|
||||
{
|
||||
include_search_glob(result, new_location / generic_path,
|
||||
path.substr(next), state);
|
||||
else {
|
||||
if (!fs::is_regular_file(dir_i->status())) {
|
||||
include_search_glob(
|
||||
result, new_location / generic_path, path.substr(next),
|
||||
state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::set<quickbook_path> include_search(path_parameter const& parameter,
|
||||
quickbook::state& state, string_iterator pos)
|
||||
std::set<quickbook_path> include_search(
|
||||
path_parameter const& parameter,
|
||||
quickbook::state& state,
|
||||
string_iterator pos)
|
||||
{
|
||||
std::set<quickbook_path> result;
|
||||
|
||||
switch (parameter.type) {
|
||||
case path_parameter::glob:
|
||||
case path_parameter::glob:
|
||||
// If the path has some glob match characters
|
||||
// we do a discovery of all the matches..
|
||||
{
|
||||
@@ -208,78 +200,70 @@ namespace quickbook
|
||||
|
||||
// Search for the current dir accumulating to the result.
|
||||
state.dependencies.add_glob(current / parameter.value);
|
||||
include_search_glob(result, state.current_path.parent_path(),
|
||||
parameter.value, state);
|
||||
include_search_glob(
|
||||
result, state.current_path.parent_path(), parameter.value,
|
||||
state);
|
||||
|
||||
// Search the include path dirs accumulating to the result.
|
||||
unsigned count = 0;
|
||||
BOOST_FOREACH(fs::path dir, include_path)
|
||||
{
|
||||
BOOST_FOREACH (fs::path dir, include_path) {
|
||||
++count;
|
||||
state.dependencies.add_glob(dir / parameter.value);
|
||||
include_search_glob(result,
|
||||
quickbook_path(dir, count, fs::path()),
|
||||
parameter.value, state);
|
||||
include_search_glob(
|
||||
result, quickbook_path(dir, count, fs::path()),
|
||||
parameter.value, state);
|
||||
}
|
||||
|
||||
// Done.
|
||||
return result;
|
||||
}
|
||||
|
||||
case path_parameter::path:
|
||||
{
|
||||
fs::path path = detail::generic_to_path(parameter.value);
|
||||
case path_parameter::path: {
|
||||
fs::path path = detail::generic_to_path(parameter.value);
|
||||
|
||||
// If the path is relative, try and resolve it.
|
||||
if (!path.has_root_directory() && !path.has_root_name())
|
||||
{
|
||||
quickbook_path path2 =
|
||||
state.current_path.parent_path() / parameter.value;
|
||||
// If the path is relative, try and resolve it.
|
||||
if (!path.has_root_directory() && !path.has_root_name()) {
|
||||
quickbook_path path2 =
|
||||
state.current_path.parent_path() / parameter.value;
|
||||
|
||||
// See if it can be found locally first.
|
||||
if (state.dependencies.add_dependency(path2.file_path))
|
||||
{
|
||||
result.insert(path2);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Search in each of the include path locations.
|
||||
unsigned count = 0;
|
||||
BOOST_FOREACH(fs::path full, include_path)
|
||||
{
|
||||
++count;
|
||||
full /= path;
|
||||
|
||||
if (state.dependencies.add_dependency(full))
|
||||
{
|
||||
result.insert(quickbook_path(full, count, path));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// See if it can be found locally first.
|
||||
if (state.dependencies.add_dependency(path2.file_path)) {
|
||||
result.insert(path2);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state.dependencies.add_dependency(path)) {
|
||||
result.insert(quickbook_path(path, 0, path));
|
||||
|
||||
// Search in each of the include path locations.
|
||||
unsigned count = 0;
|
||||
BOOST_FOREACH (fs::path full, include_path) {
|
||||
++count;
|
||||
full /= path;
|
||||
|
||||
if (state.dependencies.add_dependency(full)) {
|
||||
result.insert(quickbook_path(full, count, path));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
detail::outerr(state.current_file, pos)
|
||||
<< "Unable to find file: "
|
||||
<< parameter.value
|
||||
<< std::endl;
|
||||
++state.error_count;
|
||||
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
if (state.dependencies.add_dependency(path)) {
|
||||
result.insert(quickbook_path(path, 0, path));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
case path_parameter::invalid:
|
||||
return result;
|
||||
detail::outerr(state.current_file, pos)
|
||||
<< "Unable to find file: " << parameter.value << std::endl;
|
||||
++state.error_count;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
case path_parameter::invalid:
|
||||
return result;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +271,8 @@ namespace quickbook
|
||||
// quickbook_path
|
||||
//
|
||||
|
||||
void swap(quickbook_path& x, quickbook_path& y) {
|
||||
void swap(quickbook_path& x, quickbook_path& y)
|
||||
{
|
||||
boost::swap(x.file_path, y.file_path);
|
||||
boost::swap(x.include_path_offset, y.include_path_offset);
|
||||
boost::swap(x.abstract_file_path, y.abstract_file_path);
|
||||
@@ -295,12 +280,11 @@ namespace quickbook
|
||||
|
||||
bool quickbook_path::operator<(quickbook_path const& other) const
|
||||
{
|
||||
return
|
||||
abstract_file_path != other.abstract_file_path ?
|
||||
abstract_file_path < other.abstract_file_path :
|
||||
include_path_offset != other.include_path_offset ?
|
||||
include_path_offset < other.include_path_offset :
|
||||
file_path < other.file_path;
|
||||
return abstract_file_path != other.abstract_file_path
|
||||
? abstract_file_path < other.abstract_file_path
|
||||
: include_path_offset != other.include_path_offset
|
||||
? include_path_offset < other.include_path_offset
|
||||
: file_path < other.file_path;
|
||||
}
|
||||
|
||||
quickbook_path quickbook_path::operator/(quickbook::string_view x) const
|
||||
@@ -318,17 +302,19 @@ namespace quickbook
|
||||
|
||||
quickbook_path quickbook_path::parent_path() const
|
||||
{
|
||||
return quickbook_path(file_path.parent_path(), include_path_offset,
|
||||
abstract_file_path.parent_path());
|
||||
return quickbook_path(
|
||||
file_path.parent_path(), include_path_offset,
|
||||
abstract_file_path.parent_path());
|
||||
}
|
||||
|
||||
quickbook_path resolve_xinclude_path(std::string const& x, quickbook::state& state, bool is_file) {
|
||||
quickbook_path resolve_xinclude_path(
|
||||
std::string const& x, quickbook::state& state, bool is_file)
|
||||
{
|
||||
fs::path path = detail::generic_to_path(x);
|
||||
fs::path full_path = path;
|
||||
|
||||
// If the path is relative
|
||||
if (!path.has_root_directory())
|
||||
{
|
||||
if (!path.has_root_directory()) {
|
||||
// Resolve the path from the current file
|
||||
full_path = state.current_file->path.parent_path() / path;
|
||||
|
||||
|
||||
@@ -15,23 +15,31 @@
|
||||
// Classes and functions for dealing with the values from include, import and
|
||||
// xinclude elements.
|
||||
|
||||
#include "fwd.hpp"
|
||||
#include "values.hpp"
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "fwd.hpp"
|
||||
#include "values.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
struct path_parameter {
|
||||
struct path_parameter
|
||||
{
|
||||
// Will possibly add 'url' to this list later:
|
||||
enum path_type { invalid, path, glob };
|
||||
enum path_type
|
||||
{
|
||||
invalid,
|
||||
path,
|
||||
glob
|
||||
};
|
||||
|
||||
std::string value;
|
||||
path_type type;
|
||||
|
||||
path_parameter(std::string const& value_, path_type type_) :
|
||||
value(value_), type(type_) {}
|
||||
path_parameter(std::string const& value_, path_type type_)
|
||||
: value(value_), type(type_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
path_parameter check_path(value const& path, quickbook::state& state);
|
||||
@@ -40,7 +48,9 @@ namespace quickbook
|
||||
struct quickbook_path
|
||||
{
|
||||
quickbook_path(fs::path const& x, unsigned offset, fs::path const& y)
|
||||
: file_path(x), include_path_offset(offset), abstract_file_path(y) {}
|
||||
: file_path(x), include_path_offset(offset), abstract_file_path(y)
|
||||
{
|
||||
}
|
||||
|
||||
friend void swap(quickbook_path&, quickbook_path&);
|
||||
|
||||
@@ -62,10 +72,11 @@ namespace quickbook
|
||||
fs::path abstract_file_path;
|
||||
};
|
||||
|
||||
std::set<quickbook_path> include_search(path_parameter const&,
|
||||
quickbook::state& state, string_iterator pos);
|
||||
std::set<quickbook_path> include_search(
|
||||
path_parameter const&, quickbook::state& state, string_iterator pos);
|
||||
|
||||
quickbook_path resolve_xinclude_path(std::string const&, quickbook::state&, bool is_file = false);
|
||||
quickbook_path resolve_xinclude_path(
|
||||
std::string const&, quickbook::state&, bool is_file = false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_ITERATOR_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_ITERATOR_HPP
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include "string_view.hpp"
|
||||
|
||||
namespace quickbook
|
||||
@@ -20,38 +20,33 @@ namespace quickbook
|
||||
template <typename Iterator>
|
||||
struct lookback_iterator
|
||||
: boost::forward_iterator_helper<
|
||||
lookback_iterator<Iterator>,
|
||||
typename boost::iterator_value<Iterator>::type,
|
||||
typename boost::iterator_difference<Iterator>::type,
|
||||
typename boost::iterator_pointer<Iterator>::type,
|
||||
typename boost::iterator_reference<Iterator>::type
|
||||
>
|
||||
lookback_iterator<Iterator>,
|
||||
typename boost::iterator_value<Iterator>::type,
|
||||
typename boost::iterator_difference<Iterator>::type,
|
||||
typename boost::iterator_pointer<Iterator>::type,
|
||||
typename boost::iterator_reference<Iterator>::type>
|
||||
{
|
||||
lookback_iterator() {}
|
||||
explicit lookback_iterator(Iterator i)
|
||||
: original_(i), base_(i) {}
|
||||
|
||||
explicit lookback_iterator(Iterator i) : original_(i), base_(i) {}
|
||||
|
||||
friend bool operator==(
|
||||
lookback_iterator const& x,
|
||||
lookback_iterator const& y)
|
||||
lookback_iterator const& x, lookback_iterator const& y)
|
||||
{
|
||||
return x.base_ == y.base_;
|
||||
}
|
||||
|
||||
|
||||
lookback_iterator& operator++()
|
||||
{
|
||||
++base_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
typename boost::iterator_reference<Iterator>::type operator*() const
|
||||
{
|
||||
return *base_;
|
||||
}
|
||||
|
||||
Iterator base() const {
|
||||
return base_;
|
||||
}
|
||||
|
||||
Iterator base() const { return base_; }
|
||||
|
||||
typedef boost::iterator_range<std::reverse_iterator<Iterator> >
|
||||
lookback_range;
|
||||
@@ -60,8 +55,8 @@ namespace quickbook
|
||||
{
|
||||
return lookback_range(base_, original_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
Iterator original_;
|
||||
Iterator base_;
|
||||
};
|
||||
|
||||
@@ -8,38 +8,40 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "grammar_impl.hpp"
|
||||
#include "state.hpp"
|
||||
#include "actions.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "template_tags.hpp"
|
||||
#include "block_tags.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "parsers.hpp"
|
||||
#include "scoped.hpp"
|
||||
#include "stream.hpp"
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_chset.hpp>
|
||||
#include <boost/spirit/include/classic_if.hpp>
|
||||
#include <boost/spirit/include/classic_loops.hpp>
|
||||
#include <boost/spirit/include/classic_attribute.hpp>
|
||||
#include <boost/spirit/include/classic_lazy.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include <boost/range/algorithm/find_first_of.hpp>
|
||||
#include <boost/range/as_literal.hpp>
|
||||
#include <boost/spirit/include/classic_attribute.hpp>
|
||||
#include <boost/spirit/include/classic_chset.hpp>
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_if.hpp>
|
||||
#include <boost/spirit/include/classic_lazy.hpp>
|
||||
#include <boost/spirit/include/classic_loops.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include "actions.hpp"
|
||||
#include "block_tags.hpp"
|
||||
#include "grammar_impl.hpp"
|
||||
#include "parsers.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "scoped.hpp"
|
||||
#include "state.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "template_tags.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
namespace cl = boost::spirit::classic;
|
||||
|
||||
struct list_stack_item {
|
||||
struct list_stack_item
|
||||
{
|
||||
// Is this the root of the context
|
||||
// (e.g. top, template, table cell etc.)
|
||||
enum list_item_type {
|
||||
syntactic_list, // In a list marked up '*' or '#'
|
||||
top_level, // At the top level of a parse
|
||||
// (might be a template body)
|
||||
nested_block // Nested in a block element.
|
||||
enum list_item_type
|
||||
{
|
||||
syntactic_list, // In a list marked up '*' or '#'
|
||||
top_level, // At the top level of a parse
|
||||
// (might be a template body)
|
||||
nested_block // Nested in a block element.
|
||||
} type;
|
||||
|
||||
unsigned int indent; // Indent of list marker
|
||||
@@ -51,20 +53,31 @@ namespace quickbook
|
||||
//
|
||||
// |indent
|
||||
// * List item
|
||||
// |indent2
|
||||
// |indent2
|
||||
|
||||
explicit list_stack_item(list_item_type r) :
|
||||
type(r), indent(0), indent2(0), mark('\0') {}
|
||||
|
||||
explicit list_stack_item(char mark_, unsigned int indent_, unsigned int indent2_) :
|
||||
type(syntactic_list), indent(indent_), indent2(indent2_), mark(mark_)
|
||||
{}
|
||||
explicit list_stack_item(list_item_type r)
|
||||
: type(r), indent(0), indent2(0), mark('\0')
|
||||
{
|
||||
}
|
||||
|
||||
explicit list_stack_item(
|
||||
char mark_, unsigned int indent_, unsigned int indent2_)
|
||||
: type(syntactic_list)
|
||||
, indent(indent_)
|
||||
, indent2(indent2_)
|
||||
, mark(mark_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct block_types {
|
||||
enum values {
|
||||
none, code, list, paragraph
|
||||
struct block_types
|
||||
{
|
||||
enum values
|
||||
{
|
||||
none,
|
||||
code,
|
||||
list,
|
||||
paragraph
|
||||
};
|
||||
};
|
||||
|
||||
@@ -74,39 +87,34 @@ namespace quickbook
|
||||
// Local actions
|
||||
|
||||
void start_blocks_impl(parse_iterator first, parse_iterator last);
|
||||
void start_nested_blocks_impl(parse_iterator first, parse_iterator last);
|
||||
void start_nested_blocks_impl(
|
||||
parse_iterator first, parse_iterator last);
|
||||
void end_blocks_impl(parse_iterator first, parse_iterator last);
|
||||
void check_indentation_impl(parse_iterator first, parse_iterator last);
|
||||
void check_code_block_impl(parse_iterator first, parse_iterator last);
|
||||
void plain_block(string_iterator first, string_iterator last);
|
||||
void list_block(string_iterator first, string_iterator mark_pos,
|
||||
string_iterator last);
|
||||
void list_block(
|
||||
string_iterator first,
|
||||
string_iterator mark_pos,
|
||||
string_iterator last);
|
||||
void clear_stack();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Local members
|
||||
|
||||
cl::rule<scanner>
|
||||
template_phrase, top_level, indent_check,
|
||||
paragraph_separator, inside_paragraph,
|
||||
code, code_line, blank_line, hr,
|
||||
inline_code, skip_inline_code,
|
||||
template_, attribute_template, template_body,
|
||||
code_block, skip_code_block, macro,
|
||||
template_args,
|
||||
template_args_1_4, template_arg_1_4,
|
||||
template_inner_arg_1_4, brackets_1_4,
|
||||
template_args_1_5, template_arg_1_5, template_arg_1_5_content,
|
||||
template_inner_arg_1_5, brackets_1_5,
|
||||
template_args_1_6, template_arg_1_6, template_arg_1_6_content,
|
||||
break_,
|
||||
command_line_macro_identifier,
|
||||
dummy_block, line_dummy_block, square_brackets, error_brackets,
|
||||
skip_escape
|
||||
;
|
||||
cl::rule<scanner> template_phrase, top_level, indent_check,
|
||||
paragraph_separator, inside_paragraph, code, code_line, blank_line,
|
||||
hr, inline_code, skip_inline_code, template_, attribute_template,
|
||||
template_body, code_block, skip_code_block, macro, template_args,
|
||||
template_args_1_4, template_arg_1_4, template_inner_arg_1_4,
|
||||
brackets_1_4, template_args_1_5, template_arg_1_5,
|
||||
template_arg_1_5_content, template_inner_arg_1_5, brackets_1_5,
|
||||
template_args_1_6, template_arg_1_6, template_arg_1_6_content,
|
||||
break_, command_line_macro_identifier, dummy_block,
|
||||
line_dummy_block, square_brackets, error_brackets, skip_escape;
|
||||
|
||||
struct block_context_closure : cl::closure<block_context_closure,
|
||||
element_info::context>
|
||||
struct block_context_closure
|
||||
: cl::closure<block_context_closure, element_info::context>
|
||||
{
|
||||
// Mask used to determine whether or not an element is a block
|
||||
// element.
|
||||
@@ -117,7 +125,8 @@ namespace quickbook
|
||||
|
||||
cl::rule<scanner> paragraph;
|
||||
cl::rule<scanner> list;
|
||||
cl::rule<scanner, block_context_closure::context_t> syntactic_block_item;
|
||||
cl::rule<scanner, block_context_closure::context_t>
|
||||
syntactic_block_item;
|
||||
cl::rule<scanner> common;
|
||||
cl::rule<scanner> element;
|
||||
|
||||
@@ -126,7 +135,7 @@ namespace quickbook
|
||||
unsigned int list_indent;
|
||||
bool no_eols;
|
||||
element_info::context context;
|
||||
char mark; // Simple markup's deliminator
|
||||
char mark; // Simple markup's deliminator
|
||||
bool still_in_block; // Inside a syntatic block
|
||||
|
||||
// transitory state
|
||||
@@ -147,22 +156,24 @@ namespace quickbook
|
||||
, context(element_info::in_top_level)
|
||||
, mark('\0')
|
||||
, state_(state)
|
||||
{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct process_element_impl : scoped_action_base {
|
||||
process_element_impl(main_grammar_local& l_) :
|
||||
l(l_), pushed_source_mode_(false), element_context_error_(false) {}
|
||||
struct process_element_impl : scoped_action_base
|
||||
{
|
||||
process_element_impl(main_grammar_local& l_)
|
||||
: l(l_), pushed_source_mode_(false), element_context_error_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool start()
|
||||
{
|
||||
// This element doesn't exist in the current language version.
|
||||
if (qbk_version_n < l.info.qbk_version)
|
||||
return false;
|
||||
if (qbk_version_n < l.info.qbk_version) return false;
|
||||
|
||||
// The element is not allowed in this context.
|
||||
if (!(l.info.type & l.context))
|
||||
{
|
||||
if (!(l.info.type & l.context)) {
|
||||
if (qbk_version_n < 107u) {
|
||||
return false;
|
||||
}
|
||||
@@ -174,8 +185,7 @@ namespace quickbook
|
||||
info_ = l.info;
|
||||
|
||||
if (info_.type != element_info::phrase &&
|
||||
info_.type != element_info::maybe_block)
|
||||
{
|
||||
info_.type != element_info::maybe_block) {
|
||||
paragraph_action para(l.state_);
|
||||
para();
|
||||
}
|
||||
@@ -183,8 +193,7 @@ namespace quickbook
|
||||
assert(l.state_.values.builder.empty());
|
||||
|
||||
if (l.state_.source_mode_next &&
|
||||
info_.type != element_info::maybe_block)
|
||||
{
|
||||
info_.type != element_info::maybe_block) {
|
||||
l.state_.push_tagged_source_mode(l.state_.source_mode_next);
|
||||
pushed_source_mode_ = true;
|
||||
l.state_.source_mode_next = 0;
|
||||
@@ -197,16 +206,16 @@ namespace quickbook
|
||||
bool result(ResultT r, ScannerT const& scan)
|
||||
{
|
||||
if (element_context_error_) {
|
||||
error_message_action error(l.state_,
|
||||
"Element not allowed in this context.");
|
||||
error_message_action error(
|
||||
l.state_, "Element not allowed in this context.");
|
||||
error(scan.first, scan.first);
|
||||
return true;
|
||||
}
|
||||
else if (r) {
|
||||
return true;
|
||||
}
|
||||
else if (qbk_version_n < 107u &&
|
||||
info_.type & element_info::in_phrase) {
|
||||
else if (
|
||||
qbk_version_n < 107u && info_.type & element_info::in_phrase) {
|
||||
// Old versions of quickbook had a soft fail
|
||||
// for unparsed phrase elements.
|
||||
return false;
|
||||
@@ -219,12 +228,15 @@ namespace quickbook
|
||||
}
|
||||
}
|
||||
|
||||
void success(parse_iterator, parse_iterator) { l.element_type = info_.type; }
|
||||
void success(parse_iterator, parse_iterator)
|
||||
{
|
||||
l.element_type = info_.type;
|
||||
}
|
||||
void failure() { l.element_type = element_info::nothing; }
|
||||
|
||||
void cleanup() {
|
||||
if (pushed_source_mode_)
|
||||
l.state_.pop_tagged_source_mode();
|
||||
void cleanup()
|
||||
{
|
||||
if (pushed_source_mode_) l.state_.pop_tagged_source_mode();
|
||||
}
|
||||
|
||||
main_grammar_local& l;
|
||||
@@ -235,17 +247,21 @@ namespace quickbook
|
||||
|
||||
struct scoped_paragraph : scoped_action_base
|
||||
{
|
||||
scoped_paragraph(quickbook::state& state_) :
|
||||
state(state_), pushed(false) {}
|
||||
scoped_paragraph(quickbook::state& state_)
|
||||
: state(state_), pushed(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool start() {
|
||||
bool start()
|
||||
{
|
||||
state.push_tagged_source_mode(state.source_mode_next);
|
||||
pushed = true;
|
||||
state.source_mode_next = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
void cleanup()
|
||||
{
|
||||
if (pushed) state.pop_tagged_source_mode();
|
||||
}
|
||||
|
||||
@@ -253,15 +269,16 @@ namespace quickbook
|
||||
bool pushed;
|
||||
};
|
||||
|
||||
struct in_list_impl {
|
||||
struct in_list_impl
|
||||
{
|
||||
main_grammar_local& l;
|
||||
|
||||
explicit in_list_impl(main_grammar_local& l_) :
|
||||
l(l_) {}
|
||||
explicit in_list_impl(main_grammar_local& l_) : l(l_) {}
|
||||
|
||||
bool operator()() const {
|
||||
bool operator()() const
|
||||
{
|
||||
return !l.list_stack.empty() &&
|
||||
l.list_stack.top().type == list_stack_item::syntactic_list;
|
||||
l.list_stack.top().type == list_stack_item::syntactic_list;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -271,18 +288,19 @@ namespace quickbook
|
||||
typedef M T::*member_ptr;
|
||||
|
||||
explicit set_scoped_value_impl(T& l_, member_ptr ptr_)
|
||||
: l(l_), ptr(ptr_), saved_value() {}
|
||||
: l(l_), ptr(ptr_), saved_value()
|
||||
{
|
||||
}
|
||||
|
||||
bool start(M const& value) {
|
||||
bool start(M const& value)
|
||||
{
|
||||
saved_value = l.*ptr;
|
||||
l.*ptr = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
l.*ptr = saved_value;
|
||||
}
|
||||
void cleanup() { l.*ptr = saved_value; }
|
||||
|
||||
T& l;
|
||||
member_ptr ptr;
|
||||
@@ -294,8 +312,10 @@ namespace quickbook
|
||||
{
|
||||
typedef set_scoped_value_impl<T, M> impl;
|
||||
|
||||
set_scoped_value(T& l, typename impl::member_ptr ptr) :
|
||||
scoped_parser<impl>(impl(l, ptr)) {}
|
||||
set_scoped_value(T& l, typename impl::member_ptr ptr)
|
||||
: scoped_parser<impl>(impl(l, ptr))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -303,8 +323,7 @@ namespace quickbook
|
||||
|
||||
void quickbook_grammar::impl::init_main()
|
||||
{
|
||||
main_grammar_local& local = cleanup_.add(
|
||||
new main_grammar_local(state));
|
||||
main_grammar_local& local = cleanup_.add(new main_grammar_local(state));
|
||||
|
||||
// Global Actions
|
||||
quickbook::element_action element_action(state);
|
||||
@@ -333,22 +352,22 @@ namespace quickbook
|
||||
in_list_impl in_list(local);
|
||||
|
||||
set_scoped_value<main_grammar_local, bool> scoped_no_eols(
|
||||
local, &main_grammar_local::no_eols);
|
||||
set_scoped_value<main_grammar_local, element_info::context> scoped_context(
|
||||
local, &main_grammar_local::context);
|
||||
local, &main_grammar_local::no_eols);
|
||||
set_scoped_value<main_grammar_local, element_info::context>
|
||||
scoped_context(local, &main_grammar_local::context);
|
||||
set_scoped_value<main_grammar_local, bool> scoped_still_in_block(
|
||||
local, &main_grammar_local::still_in_block);
|
||||
local, &main_grammar_local::still_in_block);
|
||||
|
||||
member_action<main_grammar_local> check_indentation(local,
|
||||
&main_grammar_local::check_indentation_impl);
|
||||
member_action<main_grammar_local> check_code_block(local,
|
||||
&main_grammar_local::check_code_block_impl);
|
||||
member_action<main_grammar_local> start_blocks(local,
|
||||
&main_grammar_local::start_blocks_impl);
|
||||
member_action<main_grammar_local> start_nested_blocks(local,
|
||||
&main_grammar_local::start_nested_blocks_impl);
|
||||
member_action<main_grammar_local> end_blocks(local,
|
||||
&main_grammar_local::end_blocks_impl);
|
||||
member_action<main_grammar_local> check_indentation(
|
||||
local, &main_grammar_local::check_indentation_impl);
|
||||
member_action<main_grammar_local> check_code_block(
|
||||
local, &main_grammar_local::check_code_block_impl);
|
||||
member_action<main_grammar_local> start_blocks(
|
||||
local, &main_grammar_local::start_blocks_impl);
|
||||
member_action<main_grammar_local> start_nested_blocks(
|
||||
local, &main_grammar_local::start_nested_blocks_impl);
|
||||
member_action<main_grammar_local> end_blocks(
|
||||
local, &main_grammar_local::end_blocks_impl);
|
||||
|
||||
// clang-format off
|
||||
|
||||
@@ -1096,12 +1115,10 @@ namespace quickbook
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Indentation Handling
|
||||
|
||||
template <typename Iterator>
|
||||
int indent_length(Iterator first, Iterator end)
|
||||
template <typename Iterator> int indent_length(Iterator first, Iterator end)
|
||||
{
|
||||
int length = 0;
|
||||
for(; first != end; ++first)
|
||||
{
|
||||
for (; first != end; ++first) {
|
||||
if (*first == '\t') {
|
||||
// hardcoded tab to 4 for now
|
||||
length = length + 4 - (length % 4);
|
||||
@@ -1119,7 +1136,8 @@ namespace quickbook
|
||||
list_stack.push(list_stack_item(list_stack_item::top_level));
|
||||
}
|
||||
|
||||
void main_grammar_local::start_nested_blocks_impl(parse_iterator, parse_iterator)
|
||||
void main_grammar_local::start_nested_blocks_impl(
|
||||
parse_iterator, parse_iterator)
|
||||
{
|
||||
// If this nested block is part of a list, then tell the
|
||||
// output state.
|
||||
@@ -1135,13 +1153,13 @@ namespace quickbook
|
||||
list_stack.pop();
|
||||
}
|
||||
|
||||
void main_grammar_local::check_indentation_impl(parse_iterator first_, parse_iterator last_)
|
||||
void main_grammar_local::check_indentation_impl(
|
||||
parse_iterator first_, parse_iterator last_)
|
||||
{
|
||||
string_iterator first = first_.base();
|
||||
string_iterator last = last_.base();
|
||||
string_iterator mark_pos = boost::find_first_of(
|
||||
boost::make_iterator_range(first, last),
|
||||
boost::as_literal("#*"));
|
||||
boost::make_iterator_range(first, last), boost::as_literal("#*"));
|
||||
|
||||
if (mark_pos == last) {
|
||||
plain_block(first, last);
|
||||
@@ -1151,15 +1169,18 @@ namespace quickbook
|
||||
}
|
||||
}
|
||||
|
||||
void main_grammar_local::check_code_block_impl(parse_iterator first, parse_iterator last)
|
||||
void main_grammar_local::check_code_block_impl(
|
||||
parse_iterator first, parse_iterator last)
|
||||
{
|
||||
unsigned int new_indent = indent_length(first.base(), last.base());
|
||||
|
||||
block_type = (new_indent > list_stack.top().indent2) ?
|
||||
block_types::code : block_types::none;
|
||||
block_type = (new_indent > list_stack.top().indent2)
|
||||
? block_types::code
|
||||
: block_types::none;
|
||||
}
|
||||
|
||||
void main_grammar_local::plain_block(string_iterator first, string_iterator last)
|
||||
void main_grammar_local::plain_block(
|
||||
string_iterator first, string_iterator last)
|
||||
{
|
||||
if (qbk_version_n >= 106u) {
|
||||
unsigned int new_indent = indent_length(first, last);
|
||||
@@ -1173,18 +1194,17 @@ namespace quickbook
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (list_stack.top().type == list_stack_item::syntactic_list
|
||||
&& new_indent < list_stack.top().indent)
|
||||
{
|
||||
while (list_stack.top().type ==
|
||||
list_stack_item::syntactic_list &&
|
||||
new_indent < list_stack.top().indent) {
|
||||
state_.end_list_item();
|
||||
state_.end_list(list_stack.top().mark);
|
||||
list_stack.pop();
|
||||
list_indent = list_stack.top().indent;
|
||||
}
|
||||
|
||||
if (list_stack.top().type == list_stack_item::syntactic_list
|
||||
&& new_indent == list_stack.top().indent)
|
||||
{
|
||||
if (list_stack.top().type == list_stack_item::syntactic_list &&
|
||||
new_indent == list_stack.top().indent) {
|
||||
// If the paragraph is aligned with the list item's marker,
|
||||
// then end the current list item if that's aligned (or to
|
||||
// the left of) the parent's paragraph.
|
||||
@@ -1202,13 +1222,14 @@ namespace quickbook
|
||||
// * Level 2
|
||||
//
|
||||
// Back to Level 1
|
||||
|
||||
|
||||
list_stack_item save = list_stack.top();
|
||||
list_stack.pop();
|
||||
|
||||
assert(list_stack.top().type != list_stack_item::syntactic_list ?
|
||||
new_indent >= list_stack.top().indent :
|
||||
new_indent > list_stack.top().indent);
|
||||
assert(
|
||||
list_stack.top().type != list_stack_item::syntactic_list
|
||||
? new_indent >= list_stack.top().indent
|
||||
: new_indent > list_stack.top().indent);
|
||||
|
||||
if (new_indent <= list_stack.top().indent2) {
|
||||
state_.end_list_item();
|
||||
@@ -1224,7 +1245,7 @@ namespace quickbook
|
||||
}
|
||||
|
||||
if (qbk_version_n == 106u &&
|
||||
list_stack.top().type == list_stack_item::syntactic_list) {
|
||||
list_stack.top().type == list_stack_item::syntactic_list) {
|
||||
detail::outerr(state_.current_file, first)
|
||||
<< "Paragraphs in lists aren't supported in quickbook 1.6."
|
||||
<< std::endl;
|
||||
@@ -1235,29 +1256,30 @@ namespace quickbook
|
||||
clear_stack();
|
||||
|
||||
if (list_stack.top().type != list_stack_item::nested_block &&
|
||||
last != first)
|
||||
last != first)
|
||||
block_type = block_types::code;
|
||||
else
|
||||
block_type = block_types::paragraph;
|
||||
}
|
||||
}
|
||||
|
||||
void main_grammar_local::list_block(string_iterator first, string_iterator mark_pos,
|
||||
string_iterator last)
|
||||
void main_grammar_local::list_block(
|
||||
string_iterator first, string_iterator mark_pos, string_iterator last)
|
||||
{
|
||||
unsigned int new_indent = indent_length(first, mark_pos);
|
||||
unsigned int new_indent2 = indent_length(first, last);
|
||||
char list_mark = *mark_pos;
|
||||
|
||||
if (list_stack.top().type == list_stack_item::top_level &&
|
||||
new_indent > 0) {
|
||||
new_indent > 0) {
|
||||
block_type = block_types::code;
|
||||
return;
|
||||
}
|
||||
|
||||
if (list_stack.top().type != list_stack_item::syntactic_list ||
|
||||
new_indent > list_indent) {
|
||||
list_stack.push(list_stack_item(list_mark, new_indent, new_indent2));
|
||||
new_indent > list_indent) {
|
||||
list_stack.push(
|
||||
list_stack_item(list_mark, new_indent, new_indent2));
|
||||
state_.start_list(list_mark);
|
||||
}
|
||||
else if (new_indent == list_indent) {
|
||||
@@ -1266,9 +1288,8 @@ namespace quickbook
|
||||
else {
|
||||
// This should never reach root, since the first list
|
||||
// has indentation 0.
|
||||
while(list_stack.top().type == list_stack_item::syntactic_list &&
|
||||
new_indent < list_stack.top().indent)
|
||||
{
|
||||
while (list_stack.top().type == list_stack_item::syntactic_list &&
|
||||
new_indent < list_stack.top().indent) {
|
||||
state_.end_list_item();
|
||||
state_.end_list(list_stack.top().mark);
|
||||
list_stack.pop();
|
||||
@@ -1279,8 +1300,7 @@ namespace quickbook
|
||||
|
||||
list_indent = new_indent;
|
||||
|
||||
if (list_mark != list_stack.top().mark)
|
||||
{
|
||||
if (list_mark != list_stack.top().mark) {
|
||||
detail::outerr(state_.current_file, first)
|
||||
<< "Illegal change of list style.\n";
|
||||
detail::outwarn(state_.current_file, first)
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "quickbook.hpp"
|
||||
#include "markups.hpp"
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <boost/foreach.hpp>
|
||||
#include "block_tags.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <ostream>
|
||||
#include <map>
|
||||
#include "quickbook.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -25,55 +25,59 @@ namespace quickbook
|
||||
void initialise_markups()
|
||||
{
|
||||
markup init_markups[] = {
|
||||
{ block_tags::paragraph, "<para>\n", "</para>\n" },
|
||||
{ block_tags::paragraph_in_list, "<simpara>\n", "</simpara>\n" },
|
||||
{ block_tags::blurb, "<sidebar role=\"blurb\">\n", "</sidebar>\n" },
|
||||
{ block_tags::blockquote, "<blockquote>", "</blockquote>" },
|
||||
{ block_tags::preformatted, "<programlisting>", "</programlisting>" },
|
||||
{ block_tags::warning, "<warning>", "</warning>" },
|
||||
{ block_tags::caution, "<caution>", "</caution>" },
|
||||
{ block_tags::important, "<important>", "</important>" },
|
||||
{ block_tags::note, "<note>", "</note>" },
|
||||
{ block_tags::tip, "<tip>", "</tip>" },
|
||||
{ block_tags::block, "", "" },
|
||||
{ block_tags::ordered_list, "<orderedlist>", "</orderedlist>" },
|
||||
{ block_tags::itemized_list, "<itemizedlist>", "</itemizedlist>" },
|
||||
{ block_tags::hr, "<para/>", 0 },
|
||||
{ phrase_tags::url, "<ulink url=\"", "</ulink>" },
|
||||
{ phrase_tags::link, "<link linkend=\"", "</link>" },
|
||||
{ phrase_tags::funcref, "<functionname alt=\"", "</functionname>" },
|
||||
{ phrase_tags::classref, "<classname alt=\"", "</classname>" },
|
||||
{ phrase_tags::memberref, "<methodname alt=\"", "</methodname>" },
|
||||
{ phrase_tags::enumref, "<enumname alt=\"", "</enumname>" },
|
||||
{ phrase_tags::macroref, "<macroname alt=\"", "</macroname>" },
|
||||
{ phrase_tags::headerref, "<headername alt=\"", "</headername>" },
|
||||
{ phrase_tags::conceptref, "<conceptname alt=\"", "</conceptname>" },
|
||||
{ phrase_tags::globalref, "<globalname alt=\"", "</globalname>" },
|
||||
{ phrase_tags::bold, "<emphasis role=\"bold\">", "</emphasis>" },
|
||||
{ phrase_tags::italic, "<emphasis>", "</emphasis>" },
|
||||
{ phrase_tags::underline, "<emphasis role=\"underline\">", "</emphasis>" },
|
||||
{ phrase_tags::teletype, "<literal>", "</literal>" },
|
||||
{ phrase_tags::strikethrough, "<emphasis role=\"strikethrough\">", "</emphasis>" },
|
||||
{ phrase_tags::quote, "<quote>", "</quote>" },
|
||||
{ phrase_tags::replaceable, "<replaceable>", "</replaceable>" },
|
||||
{ phrase_tags::escape, "<!--quickbook-escape-prefix-->", "<!--quickbook-escape-postfix-->" },
|
||||
{ phrase_tags::break_mark, "<sbr/>\n", 0 }
|
||||
};
|
||||
{block_tags::paragraph, "<para>\n", "</para>\n"},
|
||||
{block_tags::paragraph_in_list, "<simpara>\n", "</simpara>\n"},
|
||||
{block_tags::blurb, "<sidebar role=\"blurb\">\n",
|
||||
"</sidebar>\n"},
|
||||
{block_tags::blockquote, "<blockquote>", "</blockquote>"},
|
||||
{block_tags::preformatted, "<programlisting>",
|
||||
"</programlisting>"},
|
||||
{block_tags::warning, "<warning>", "</warning>"},
|
||||
{block_tags::caution, "<caution>", "</caution>"},
|
||||
{block_tags::important, "<important>", "</important>"},
|
||||
{block_tags::note, "<note>", "</note>"},
|
||||
{block_tags::tip, "<tip>", "</tip>"},
|
||||
{block_tags::block, "", ""},
|
||||
{block_tags::ordered_list, "<orderedlist>", "</orderedlist>"},
|
||||
{block_tags::itemized_list, "<itemizedlist>",
|
||||
"</itemizedlist>"},
|
||||
{block_tags::hr, "<para/>", 0},
|
||||
{phrase_tags::url, "<ulink url=\"", "</ulink>"},
|
||||
{phrase_tags::link, "<link linkend=\"", "</link>"},
|
||||
{phrase_tags::funcref, "<functionname alt=\"",
|
||||
"</functionname>"},
|
||||
{phrase_tags::classref, "<classname alt=\"", "</classname>"},
|
||||
{phrase_tags::memberref, "<methodname alt=\"", "</methodname>"},
|
||||
{phrase_tags::enumref, "<enumname alt=\"", "</enumname>"},
|
||||
{phrase_tags::macroref, "<macroname alt=\"", "</macroname>"},
|
||||
{phrase_tags::headerref, "<headername alt=\"", "</headername>"},
|
||||
{phrase_tags::conceptref, "<conceptname alt=\"",
|
||||
"</conceptname>"},
|
||||
{phrase_tags::globalref, "<globalname alt=\"", "</globalname>"},
|
||||
{phrase_tags::bold, "<emphasis role=\"bold\">", "</emphasis>"},
|
||||
{phrase_tags::italic, "<emphasis>", "</emphasis>"},
|
||||
{phrase_tags::underline, "<emphasis role=\"underline\">",
|
||||
"</emphasis>"},
|
||||
{phrase_tags::teletype, "<literal>", "</literal>"},
|
||||
{phrase_tags::strikethrough,
|
||||
"<emphasis role=\"strikethrough\">", "</emphasis>"},
|
||||
{phrase_tags::quote, "<quote>", "</quote>"},
|
||||
{phrase_tags::replaceable, "<replaceable>", "</replaceable>"},
|
||||
{phrase_tags::escape, "<!--quickbook-escape-prefix-->",
|
||||
"<!--quickbook-escape-postfix-->"},
|
||||
{phrase_tags::break_mark, "<sbr/>\n", 0}};
|
||||
|
||||
BOOST_FOREACH(markup m, init_markups)
|
||||
{
|
||||
BOOST_FOREACH (markup m, init_markups) {
|
||||
markups[m.tag] = m;
|
||||
}
|
||||
}
|
||||
|
||||
markup const& get_markup(value::tag_type t)
|
||||
{
|
||||
return markups[t];
|
||||
}
|
||||
markup const& get_markup(value::tag_type t) { return markups[t]; }
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, markup const& m)
|
||||
{
|
||||
return out<<"{"<<m.tag<<": \""<<m.pre<<"\", \""<<m.post<<"\"}";
|
||||
return out << "{" << m.tag << ": \"" << m.pre << "\", \"" << m.post
|
||||
<< "\"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
namespace quickbook
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct markup {
|
||||
{
|
||||
struct markup
|
||||
{
|
||||
value::tag_type tag;
|
||||
char const* pre;
|
||||
char const* post;
|
||||
};
|
||||
|
||||
|
||||
markup const& get_markup(value::tag_type);
|
||||
std::ostream& operator<<(std::ostream&, markup const&);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_SPIRIT_MARKUPS_HPP
|
||||
|
||||
|
||||
@@ -6,50 +6,62 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <iostream>
|
||||
#include "native_text.hpp"
|
||||
#include <iostream>
|
||||
#include <boost/program_options.hpp>
|
||||
#include "utils.hpp"
|
||||
|
||||
#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <windows.h>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#endif
|
||||
|
||||
namespace quickbook {
|
||||
namespace detail {
|
||||
namespace quickbook
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// This is used for converting paths to UTF-8 on cygin.
|
||||
// Might be better not to use a windows
|
||||
// Might be better not to use a windows
|
||||
#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
|
||||
std::string to_utf8(std::wstring const& x)
|
||||
{
|
||||
int buffer_count = WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, 0, 0, 0, 0);
|
||||
|
||||
if (!buffer_count)
|
||||
throw conversion_error("Error converting wide string to utf-8.");
|
||||
std::string to_utf8(std::wstring const& x)
|
||||
{
|
||||
int buffer_count =
|
||||
WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, 0, 0, 0, 0);
|
||||
|
||||
boost::scoped_array<char> buffer(new char[buffer_count]);
|
||||
if (!buffer_count)
|
||||
throw conversion_error(
|
||||
"Error converting wide string to utf-8.");
|
||||
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count, 0, 0))
|
||||
throw conversion_error("Error converting wide string to utf-8.");
|
||||
|
||||
return std::string(buffer.get());
|
||||
}
|
||||
boost::scoped_array<char> buffer(new char[buffer_count]);
|
||||
|
||||
std::wstring from_utf8(quickbook::string_view text)
|
||||
{
|
||||
std::string x(text.begin(), text.end());
|
||||
int buffer_count = MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, 0, 0);
|
||||
if (!WideCharToMultiByte(
|
||||
CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count, 0,
|
||||
0))
|
||||
throw conversion_error(
|
||||
"Error converting wide string to utf-8.");
|
||||
|
||||
if (!buffer_count)
|
||||
throw conversion_error("Error converting utf-8 to wide string.");
|
||||
return std::string(buffer.get());
|
||||
}
|
||||
|
||||
boost::scoped_array<wchar_t> buffer(new wchar_t[buffer_count]);
|
||||
std::wstring from_utf8(quickbook::string_view text)
|
||||
{
|
||||
std::string x(text.begin(), text.end());
|
||||
int buffer_count =
|
||||
MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, 0, 0);
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count))
|
||||
throw conversion_error("Error converting utf-8 to wide string.");
|
||||
if (!buffer_count)
|
||||
throw conversion_error(
|
||||
"Error converting utf-8 to wide string.");
|
||||
|
||||
return std::wstring(buffer.get());
|
||||
}
|
||||
boost::scoped_array<wchar_t> buffer(new wchar_t[buffer_count]);
|
||||
|
||||
if (!MultiByteToWideChar(
|
||||
CP_UTF8, 0, x.c_str(), -1, buffer.get(), buffer_count))
|
||||
throw conversion_error(
|
||||
"Error converting utf-8 to wide string.");
|
||||
|
||||
return std::wstring(buffer.get());
|
||||
}
|
||||
#endif
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,22 +11,22 @@
|
||||
#if !defined(BOOST_QUICKBOOK_DETAIL_NATIVE_TEXT_HPP)
|
||||
#define BOOST_QUICKBOOK_DETAIL_NATIVE_TEXT_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include "string_view.hpp"
|
||||
#include <string>
|
||||
#include <boost/config.hpp>
|
||||
#include "fwd.hpp"
|
||||
#include "string_view.hpp"
|
||||
|
||||
#if defined(__cygwin__) || defined(__CYGWIN__)
|
||||
# define QUICKBOOK_CYGWIN_PATHS 1
|
||||
#define QUICKBOOK_CYGWIN_PATHS 1
|
||||
#elif defined(_WIN32)
|
||||
# define QUICKBOOK_WIDE_PATHS 1
|
||||
// Wide streams work okay for me with older versions of Visual C++,
|
||||
// but I've had reports of problems. My guess is that it's an
|
||||
// incompatibility with later versions of windows.
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC >= 1700
|
||||
# define QUICKBOOK_WIDE_STREAMS 1
|
||||
# endif
|
||||
#define QUICKBOOK_WIDE_PATHS 1
|
||||
// Wide streams work okay for me with older versions of Visual C++,
|
||||
// but I've had reports of problems. My guess is that it's an
|
||||
// incompatibility with later versions of windows.
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC >= 1700
|
||||
#define QUICKBOOK_WIDE_STREAMS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(QUICKBOOK_WIDE_PATHS)
|
||||
|
||||
165
src/parsers.hpp
165
src/parsers.hpp
@@ -8,21 +8,22 @@
|
||||
=============================================================================*/
|
||||
|
||||
// Some custom parsers for use in quickbook.
|
||||
|
||||
|
||||
#ifndef BOOST_QUICKBOOK_PARSERS_HPP
|
||||
#define BOOST_QUICKBOOK_PARSERS_HPP
|
||||
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_nil.hpp>
|
||||
#include <boost/spirit/include/phoenix1_binders.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include <boost/spirit/include/phoenix1_tuples.hpp>
|
||||
#include <boost/spirit/include/phoenix1_binders.hpp>
|
||||
#include "fwd.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
namespace quickbook {
|
||||
namespace quickbook
|
||||
{
|
||||
namespace cl = boost::spirit::classic;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// scoped_parser<Impl>
|
||||
@@ -38,53 +39,57 @@ namespace quickbook {
|
||||
|
||||
template <typename Impl, typename Arguments, typename ParserT>
|
||||
struct scoped_parser_impl
|
||||
: public cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > >
|
||||
: public cl::unary<
|
||||
ParserT,
|
||||
cl::parser<scoped_parser_impl<Impl, Arguments, ParserT> > >
|
||||
{
|
||||
typedef scoped_parser_impl<Impl, Arguments, ParserT> self_t;
|
||||
typedef cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > > base_t;
|
||||
typedef cl::unary<
|
||||
ParserT,
|
||||
cl::parser<scoped_parser_impl<Impl, Arguments, ParserT> > >
|
||||
base_t;
|
||||
|
||||
template <typename ScannerT>
|
||||
struct result { typedef cl::match<> type; };
|
||||
template <typename ScannerT> struct result
|
||||
{
|
||||
typedef cl::match<> type;
|
||||
};
|
||||
|
||||
scoped_parser_impl(
|
||||
Impl const& impl,
|
||||
Arguments const& arguments,
|
||||
ParserT const &p)
|
||||
: base_t(p)
|
||||
, impl_(impl)
|
||||
, arguments_(arguments)
|
||||
{}
|
||||
Impl const& impl, Arguments const& arguments, ParserT const& p)
|
||||
: base_t(p), impl_(impl), arguments_(arguments)
|
||||
{
|
||||
}
|
||||
|
||||
struct scoped
|
||||
{
|
||||
explicit scoped(Impl const& impl)
|
||||
: impl_(impl)
|
||||
, in_progress_(false)
|
||||
{}
|
||||
|
||||
explicit scoped(Impl const& impl) : impl_(impl), in_progress_(false)
|
||||
{
|
||||
}
|
||||
|
||||
typedef phoenix::tuple_index<0> t0;
|
||||
typedef phoenix::tuple_index<1> t1;
|
||||
|
||||
|
||||
bool start(phoenix::tuple<> const&)
|
||||
{
|
||||
in_progress_ = impl_.start();
|
||||
return in_progress_;
|
||||
}
|
||||
|
||||
template <typename Arg1>
|
||||
bool start(phoenix::tuple<Arg1> const& x)
|
||||
|
||||
template <typename Arg1> bool start(phoenix::tuple<Arg1> const& x)
|
||||
{
|
||||
in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()])();
|
||||
in_progress_ =
|
||||
phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()])();
|
||||
return in_progress_;
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2>
|
||||
bool start(phoenix::tuple<Arg1, Arg2> const& x)
|
||||
{
|
||||
in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()], x[t1()])();
|
||||
in_progress_ = phoenix::bind(&Impl::start)(
|
||||
phoenix::var(impl_), x[t0()], x[t1()])();
|
||||
return in_progress_;
|
||||
}
|
||||
|
||||
|
||||
void success(parse_iterator f, parse_iterator l)
|
||||
{
|
||||
in_progress_ = false;
|
||||
@@ -102,23 +107,22 @@ namespace quickbook {
|
||||
if (in_progress_) impl_.failure();
|
||||
impl_.cleanup();
|
||||
}
|
||||
|
||||
|
||||
Impl impl_;
|
||||
bool in_progress_;
|
||||
};
|
||||
|
||||
|
||||
template <typename ScannerT>
|
||||
typename result<ScannerT>::type parse(ScannerT const &scan) const
|
||||
typename result<ScannerT>::type parse(ScannerT const& scan) const
|
||||
{
|
||||
typedef typename ScannerT::iterator_t iterator_t;
|
||||
iterator_t save = scan.first;
|
||||
|
||||
scoped scope(impl_);
|
||||
if (!scope.start(arguments_))
|
||||
return scan.no_match();
|
||||
if (!scope.start(arguments_)) return scan.no_match();
|
||||
|
||||
typename cl::parser_result<ParserT, ScannerT>::type r
|
||||
= this->subject().parse(scan);
|
||||
typename cl::parser_result<ParserT, ScannerT>::type r =
|
||||
this->subject().parse(scan);
|
||||
|
||||
bool success = scope.impl_.result(r, scan);
|
||||
|
||||
@@ -126,10 +130,13 @@ namespace quickbook {
|
||||
scope.success(save, scan.first);
|
||||
|
||||
if (r) {
|
||||
return scan.create_match(r.length(), cl::nil_t(), save, scan.first);
|
||||
return scan.create_match(
|
||||
r.length(), cl::nil_t(), save, scan.first);
|
||||
}
|
||||
else {
|
||||
return scan.create_match(scan.first.base() - save.base(), cl::nil_t(), save, scan.first);
|
||||
return scan.create_match(
|
||||
scan.first.base() - save.base(), cl::nil_t(), save,
|
||||
scan.first);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -137,61 +144,56 @@ namespace quickbook {
|
||||
return scan.no_match();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Impl impl_;
|
||||
Arguments arguments_;
|
||||
};
|
||||
|
||||
template <typename Impl, typename Arguments>
|
||||
struct scoped_parser_gen
|
||||
{
|
||||
template <typename Impl, typename Arguments> struct scoped_parser_gen
|
||||
{
|
||||
explicit scoped_parser_gen(Impl impl, Arguments const& arguments)
|
||||
: impl_(impl), arguments_(arguments) {}
|
||||
: impl_(impl), arguments_(arguments)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ParserT>
|
||||
scoped_parser_impl
|
||||
<
|
||||
template <typename ParserT>
|
||||
scoped_parser_impl<
|
||||
Impl,
|
||||
Arguments,
|
||||
typename cl::as_parser<ParserT>::type
|
||||
>
|
||||
operator[](ParserT const &p) const
|
||||
typename cl::as_parser<ParserT>::type>
|
||||
operator[](ParserT const& p) const
|
||||
{
|
||||
typedef cl::as_parser<ParserT> as_parser_t;
|
||||
typedef typename as_parser_t::type parser_t;
|
||||
|
||||
return scoped_parser_impl<Impl, Arguments, parser_t>
|
||||
(impl_, arguments_, p);
|
||||
return scoped_parser_impl<Impl, Arguments, parser_t>(
|
||||
impl_, arguments_, p);
|
||||
}
|
||||
|
||||
Impl impl_;
|
||||
Arguments arguments_;
|
||||
};
|
||||
|
||||
template <typename Impl>
|
||||
struct scoped_parser
|
||||
template <typename Impl> struct scoped_parser
|
||||
{
|
||||
scoped_parser(Impl const& impl)
|
||||
: impl_(impl) {}
|
||||
|
||||
scoped_parser_gen<Impl, phoenix::tuple<> >
|
||||
operator()() const
|
||||
scoped_parser(Impl const& impl) : impl_(impl) {}
|
||||
|
||||
scoped_parser_gen<Impl, phoenix::tuple<> > operator()() const
|
||||
{
|
||||
typedef phoenix::tuple<> tuple;
|
||||
return scoped_parser_gen<Impl, tuple>(impl_, tuple());
|
||||
}
|
||||
|
||||
template <typename Arg1>
|
||||
scoped_parser_gen<Impl, phoenix::tuple<Arg1> >
|
||||
operator()(Arg1 x1) const
|
||||
scoped_parser_gen<Impl, phoenix::tuple<Arg1> > operator()(Arg1 x1) const
|
||||
{
|
||||
typedef phoenix::tuple<Arg1> tuple;
|
||||
return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1));
|
||||
}
|
||||
|
||||
|
||||
template <typename Arg1, typename Arg2>
|
||||
scoped_parser_gen<Impl, phoenix::tuple<Arg1, Arg2> >
|
||||
operator()(Arg1 x1, Arg2 x2) const
|
||||
scoped_parser_gen<Impl, phoenix::tuple<Arg1, Arg2> > operator()(
|
||||
Arg1 x1, Arg2 x2) const
|
||||
{
|
||||
typedef phoenix::tuple<Arg1, Arg2> tuple;
|
||||
return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1, x2));
|
||||
@@ -199,7 +201,7 @@ namespace quickbook {
|
||||
|
||||
Impl impl_;
|
||||
|
||||
private:
|
||||
private:
|
||||
scoped_parser& operator=(scoped_parser const&);
|
||||
};
|
||||
|
||||
@@ -216,37 +218,37 @@ namespace quickbook {
|
||||
|
||||
template <typename ParserT>
|
||||
struct lookback_parser
|
||||
: public cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > >
|
||||
: public cl::unary<ParserT, cl::parser<lookback_parser<ParserT> > >
|
||||
{
|
||||
typedef lookback_parser<ParserT> self_t;
|
||||
typedef cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > > base_t;
|
||||
typedef cl::unary<ParserT, cl::parser<lookback_parser<ParserT> > >
|
||||
base_t;
|
||||
|
||||
template <typename ScannerT>
|
||||
struct result
|
||||
template <typename ScannerT> struct result
|
||||
{
|
||||
typedef typename cl::parser_result<ParserT, ScannerT>::type type;
|
||||
};
|
||||
|
||||
lookback_parser(ParserT const& p)
|
||||
: base_t(p)
|
||||
{}
|
||||
lookback_parser(ParserT const& p) : base_t(p) {}
|
||||
|
||||
template <typename ScannerT>
|
||||
typename result<ScannerT>::type parse(ScannerT const &scan) const
|
||||
typename result<ScannerT>::type parse(ScannerT const& scan) const
|
||||
{
|
||||
typedef typename ScannerT::iterator_t::lookback_range::iterator iterator_t;
|
||||
typedef cl::scanner<iterator_t, typename ScannerT::policies_t> scanner_t;
|
||||
typedef typename ScannerT::iterator_t::lookback_range::iterator
|
||||
iterator_t;
|
||||
typedef cl::scanner<iterator_t, typename ScannerT::policies_t>
|
||||
scanner_t;
|
||||
|
||||
iterator_t begin = scan.first.lookback().begin();
|
||||
scanner_t lookback_scan(begin, scan.first.lookback().end(), scan);
|
||||
|
||||
|
||||
if (this->subject().parse(lookback_scan))
|
||||
return scan.empty_match();
|
||||
else
|
||||
return scan.no_match();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct lookback_gen
|
||||
{
|
||||
template <typename ParserT>
|
||||
@@ -255,9 +257,9 @@ namespace quickbook {
|
||||
return lookback_parser<ParserT>(p);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
lookback_gen const lookback = lookback_gen();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UTF-8 code point
|
||||
@@ -273,8 +275,7 @@ namespace quickbook {
|
||||
{
|
||||
typedef u8_codepoint_parser self_t;
|
||||
|
||||
template <typename Scanner>
|
||||
struct result
|
||||
template <typename Scanner> struct result
|
||||
{
|
||||
typedef cl::match<> type;
|
||||
};
|
||||
@@ -291,13 +292,13 @@ namespace quickbook {
|
||||
do {
|
||||
++scan.first;
|
||||
} while (!scan.at_end() &&
|
||||
((unsigned char) *scan.first & 0xc0) == 0x80);
|
||||
((unsigned char)*scan.first & 0xc0) == 0x80);
|
||||
|
||||
return scan.create_match(scan.first.base() - save.base(),
|
||||
cl::nil_t(), save, scan.first);
|
||||
return scan.create_match(
|
||||
scan.first.base() - save.base(), cl::nil_t(), save, scan.first);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
u8_codepoint_parser const u8_codepoint_p = u8_codepoint_parser();
|
||||
}
|
||||
|
||||
|
||||
117
src/path.cpp
117
src/path.cpp
@@ -10,18 +10,18 @@
|
||||
=============================================================================*/
|
||||
|
||||
#include "path.hpp"
|
||||
#include <cassert>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/range/algorithm/replace.hpp>
|
||||
#include "glob.hpp"
|
||||
#include "include_paths.hpp"
|
||||
#include "state.hpp"
|
||||
#include "utils.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/range/algorithm/replace.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <cassert>
|
||||
|
||||
#if QUICKBOOK_CYGWIN_PATHS
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <sys/cygwin.h>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#endif
|
||||
|
||||
namespace quickbook
|
||||
@@ -35,8 +35,7 @@ namespace quickbook
|
||||
|
||||
std::vector<fs::path> parts;
|
||||
|
||||
BOOST_FOREACH(fs::path const& part, path)
|
||||
{
|
||||
BOOST_FOREACH (fs::path const& part, path) {
|
||||
if (part.empty() || part == ".") {
|
||||
}
|
||||
else if (part == "..") {
|
||||
@@ -51,42 +50,39 @@ namespace quickbook
|
||||
}
|
||||
|
||||
// The relative path from base to path
|
||||
fs::path path_difference(fs::path const& base, fs::path const& path, bool is_file)
|
||||
fs::path path_difference(
|
||||
fs::path const& base, fs::path const& path, bool is_file)
|
||||
{
|
||||
fs::path
|
||||
absolute_base = fs::absolute(base),
|
||||
absolute_path = fs::absolute(path);
|
||||
fs::path absolute_base = fs::absolute(base),
|
||||
absolute_path = fs::absolute(path);
|
||||
|
||||
// Remove '.', '..' and empty parts from the remaining path
|
||||
std::vector<fs::path>
|
||||
base_parts = remove_dots_from_path(absolute_base.relative_path()),
|
||||
path_parts = remove_dots_from_path(absolute_path.relative_path());
|
||||
std::vector<fs::path> base_parts = remove_dots_from_path(
|
||||
absolute_base.relative_path()),
|
||||
path_parts = remove_dots_from_path(
|
||||
absolute_path.relative_path());
|
||||
|
||||
std::vector<fs::path>::iterator
|
||||
base_it = base_parts.begin(),
|
||||
base_end = base_parts.end(),
|
||||
path_it = path_parts.begin(),
|
||||
path_end = path_parts.end();
|
||||
std::vector<fs::path>::iterator base_it = base_parts.begin(),
|
||||
base_end = base_parts.end(),
|
||||
path_it = path_parts.begin(),
|
||||
path_end = path_parts.end();
|
||||
|
||||
// Build up the two paths in these variables, checking for the first
|
||||
// difference.
|
||||
fs::path
|
||||
base_tmp = absolute_base.root_path(),
|
||||
path_tmp = absolute_path.root_path();
|
||||
fs::path base_tmp = absolute_base.root_path(),
|
||||
path_tmp = absolute_path.root_path();
|
||||
|
||||
fs::path result;
|
||||
|
||||
// If they have different roots then there's no relative path so
|
||||
// just build an absolute path.
|
||||
if (!fs::equivalent(base_tmp, path_tmp))
|
||||
{
|
||||
if (!fs::equivalent(base_tmp, path_tmp)) {
|
||||
result = path_tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Find the point at which the paths differ
|
||||
for(; base_it != base_end && path_it != path_end; ++base_it, ++path_it)
|
||||
{
|
||||
for (; base_it != base_end && path_it != path_end;
|
||||
++base_it, ++path_it) {
|
||||
base_tmp /= *base_it;
|
||||
path_tmp /= *path_it;
|
||||
if (*base_it != *path_it) {
|
||||
@@ -97,19 +93,23 @@ namespace quickbook
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file && path_it == path_end && path_it != path_parts.begin()) {
|
||||
if (is_file && path_it == path_end &&
|
||||
path_it != path_parts.begin()) {
|
||||
--path_it;
|
||||
result = "..";
|
||||
} else if (base_it == base_end && path_it == path_end) {
|
||||
result = ".";
|
||||
}
|
||||
else if (base_it == base_end && path_it == path_end) {
|
||||
result = ".";
|
||||
}
|
||||
|
||||
// Build a relative path to that point
|
||||
for(; base_it != base_end; ++base_it) result /= "..";
|
||||
for (; base_it != base_end; ++base_it)
|
||||
result /= "..";
|
||||
}
|
||||
|
||||
// Build the rest of our path
|
||||
for(; path_it != path_end; ++path_it) result /= *path_it;
|
||||
for (; path_it != path_end; ++path_it)
|
||||
result /= *path_it;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -124,7 +124,9 @@ namespace quickbook
|
||||
std::string file_path_to_url_impl(fs::path const& x, bool is_dir)
|
||||
{
|
||||
fs::path::const_iterator it = x.begin(), end = x.end();
|
||||
if (it == end) { return is_dir ? "./" : ""; }
|
||||
if (it == end) {
|
||||
return is_dir ? "./" : "";
|
||||
}
|
||||
|
||||
std::string result;
|
||||
bool sep = false;
|
||||
@@ -141,7 +143,8 @@ namespace quickbook
|
||||
sep = false;
|
||||
++it;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
result = "file:///";
|
||||
}
|
||||
|
||||
@@ -149,35 +152,39 @@ namespace quickbook
|
||||
if (it != end) {
|
||||
part = detail::path_to_generic(*it);
|
||||
if (part.size() >= 2 && part[part.size() - 1] == ':') {
|
||||
result += detail::escape_uri(part.substr(0, part.size()- 1));
|
||||
result +=
|
||||
detail::escape_uri(part.substr(0, part.size() - 1));
|
||||
result += ':';
|
||||
sep = false;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
} else if (x.has_root_directory()) {
|
||||
}
|
||||
else if (x.has_root_directory()) {
|
||||
result = "file://";
|
||||
sep = true;
|
||||
} else if (*it == ".") {
|
||||
}
|
||||
else if (*it == ".") {
|
||||
result = ".";
|
||||
sep = true;
|
||||
++it;
|
||||
}
|
||||
|
||||
for (;it != end; ++it)
|
||||
{
|
||||
for (; it != end; ++it) {
|
||||
part = detail::path_to_generic(*it);
|
||||
if (part == "/") {
|
||||
result += "/";
|
||||
sep = false;
|
||||
} else if (part == ".") {
|
||||
}
|
||||
else if (part == ".") {
|
||||
// If the path has a trailing slash, write it out,
|
||||
// even if is_dir is false.
|
||||
if (sep) {
|
||||
result += "/";
|
||||
sep = false;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (sep) {
|
||||
result += "/";
|
||||
}
|
||||
@@ -193,7 +200,8 @@ namespace quickbook
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string file_path_to_url(fs::path const& x) {
|
||||
std::string file_path_to_url(fs::path const& x)
|
||||
{
|
||||
return file_path_to_url_impl(x, false);
|
||||
}
|
||||
|
||||
@@ -202,7 +210,8 @@ namespace quickbook
|
||||
return file_path_to_url_impl(x, true);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
namespace detail
|
||||
{
|
||||
#if QUICKBOOK_WIDE_PATHS
|
||||
std::string command_line_to_utf8(command_line_string const& x)
|
||||
{
|
||||
@@ -245,13 +254,15 @@ namespace quickbook
|
||||
ssize_t size = cygwin_conv_path(flags, path.c_str(), NULL, 0);
|
||||
|
||||
if (size < 0)
|
||||
throw conversion_error("Error converting cygwin path to windows.");
|
||||
throw conversion_error(
|
||||
"Error converting cygwin path to windows.");
|
||||
|
||||
boost::scoped_array<char> result(new char[size]);
|
||||
void* ptr = result.get();
|
||||
|
||||
if(cygwin_conv_path(flags, path.c_str(), ptr, size))
|
||||
throw conversion_error("Error converting cygwin path to windows.");
|
||||
if (cygwin_conv_path(flags, path.c_str(), ptr, size))
|
||||
throw conversion_error(
|
||||
"Error converting cygwin path to windows.");
|
||||
|
||||
return fs::path(static_cast<wchar_t*>(ptr));
|
||||
}
|
||||
@@ -260,15 +271,19 @@ namespace quickbook
|
||||
{
|
||||
cygwin_conv_path_t flags = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
|
||||
|
||||
ssize_t size = cygwin_conv_path(flags, path.native().c_str(), NULL, 0);
|
||||
ssize_t size =
|
||||
cygwin_conv_path(flags, path.native().c_str(), NULL, 0);
|
||||
|
||||
if (size < 0)
|
||||
throw conversion_error("Error converting windows path to cygwin.");
|
||||
throw conversion_error(
|
||||
"Error converting windows path to cygwin.");
|
||||
|
||||
boost::scoped_array<char> result(new char[size]);
|
||||
|
||||
if(cygwin_conv_path(flags, path.native().c_str(), result.get(), size))
|
||||
throw conversion_error("Error converting windows path to cygwin.");
|
||||
if (cygwin_conv_path(
|
||||
flags, path.native().c_str(), result.get(), size))
|
||||
throw conversion_error(
|
||||
"Error converting windows path to cygwin.");
|
||||
|
||||
return std::string(result.get());
|
||||
}
|
||||
|
||||
28
src/path.hpp
28
src/path.hpp
@@ -20,24 +20,26 @@ namespace quickbook
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
// The relative path from base to path
|
||||
fs::path path_difference(fs::path const& base, fs::path const& path, bool is_file = false);
|
||||
fs::path path_difference(
|
||||
fs::path const& base, fs::path const& path, bool is_file = false);
|
||||
|
||||
// Convert a Boost.Filesystem path to a URL.
|
||||
std::string file_path_to_url(fs::path const&);
|
||||
std::string dir_path_to_url(fs::path const&);
|
||||
|
||||
namespace detail {
|
||||
// 'generic': Paths in quickbook source and the generated boostbook.
|
||||
// Always UTF-8.
|
||||
// 'command_line':
|
||||
// Paths (or other parameters) from the command line and
|
||||
// possibly other sources in the future. Wide strings on
|
||||
// normal windows, UTF-8 for cygwin and other platforms
|
||||
// (hopefully).
|
||||
// 'path': Stored as a boost::filesystem::path. Since
|
||||
// Boost.Filesystem doesn't support cygwin, this
|
||||
// is always wide on windows. UTF-8 on other
|
||||
// platforms (again, hopefully).
|
||||
namespace detail
|
||||
{
|
||||
// 'generic': Paths in quickbook source and the generated boostbook.
|
||||
// Always UTF-8.
|
||||
// 'command_line':
|
||||
// Paths (or other parameters) from the command line and
|
||||
// possibly other sources in the future. Wide strings on
|
||||
// normal windows, UTF-8 for cygwin and other platforms
|
||||
// (hopefully).
|
||||
// 'path': Stored as a boost::filesystem::path. Since
|
||||
// Boost.Filesystem doesn't support cygwin, this
|
||||
// is always wide on windows. UTF-8 on other
|
||||
// platforms (again, hopefully).
|
||||
|
||||
#if QUICKBOOK_WIDE_PATHS
|
||||
typedef std::wstring command_line_string;
|
||||
|
||||
@@ -8,18 +8,18 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "grammar_impl.hpp"
|
||||
#include "state.hpp"
|
||||
#include "actions.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/spirit/include/classic_assign_actor.hpp>
|
||||
#include <boost/spirit/include/classic_clear_actor.hpp>
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_if.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include <boost/spirit/include/phoenix1_casts.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/spirit/include/phoenix1_primitives.hpp>
|
||||
#include "actions.hpp"
|
||||
#include "grammar_impl.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "state.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -27,16 +27,14 @@ namespace quickbook
|
||||
|
||||
struct phrase_element_grammar_local
|
||||
{
|
||||
cl::rule<scanner>
|
||||
image, anchor, link, empty, cond_phrase, inner_phrase,
|
||||
role, source_mode
|
||||
;
|
||||
cl::rule<scanner> image, anchor, link, empty, cond_phrase, inner_phrase,
|
||||
role, source_mode;
|
||||
};
|
||||
|
||||
void quickbook_grammar::impl::init_phrase_elements()
|
||||
{
|
||||
phrase_element_grammar_local& local = cleanup_.add(
|
||||
new phrase_element_grammar_local);
|
||||
phrase_element_grammar_local& local =
|
||||
cleanup_.add(new phrase_element_grammar_local);
|
||||
|
||||
error_action error(state);
|
||||
raw_char_action raw_char(state);
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#include "post_process.hpp"
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <cctype>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <cctype>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -21,8 +21,14 @@ namespace quickbook
|
||||
struct printer
|
||||
{
|
||||
printer(std::string& out_, int& current_indent_, int linewidth_)
|
||||
: prev(0), out(out_), current_indent(current_indent_) , column(0)
|
||||
, in_string(false), linewidth(linewidth_) {}
|
||||
: prev(0)
|
||||
, out(out_)
|
||||
, current_indent(current_indent_)
|
||||
, column(0)
|
||||
, in_string(false)
|
||||
, linewidth(linewidth_)
|
||||
{
|
||||
}
|
||||
|
||||
void indent()
|
||||
{
|
||||
@@ -34,7 +40,7 @@ namespace quickbook
|
||||
|
||||
void trim_spaces()
|
||||
{
|
||||
out.erase(out.find_last_not_of(' ')+1); // trim trailing spaces
|
||||
out.erase(out.find_last_not_of(' ') + 1); // trim trailing spaces
|
||||
}
|
||||
|
||||
void break_line()
|
||||
@@ -46,10 +52,9 @@ namespace quickbook
|
||||
|
||||
bool line_is_empty() const
|
||||
{
|
||||
for (iter_type i = out.end()-(column-current_indent); i != out.end(); ++i)
|
||||
{
|
||||
if (*i != ' ')
|
||||
return false;
|
||||
for (iter_type i = out.end() - (column - current_indent);
|
||||
i != out.end(); ++i) {
|
||||
if (*i != ' ') return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -57,27 +62,23 @@ namespace quickbook
|
||||
void align_indent()
|
||||
{
|
||||
// make sure we are at the proper indent position
|
||||
if (column != current_indent)
|
||||
{
|
||||
if (column > current_indent)
|
||||
{
|
||||
if (line_is_empty())
|
||||
{
|
||||
// trim just enough trailing spaces down to current_indent position
|
||||
out.erase(out.end()-(column-current_indent), out.end());
|
||||
if (column != current_indent) {
|
||||
if (column > current_indent) {
|
||||
if (line_is_empty()) {
|
||||
// trim just enough trailing spaces down to
|
||||
// current_indent position
|
||||
out.erase(
|
||||
out.end() - (column - current_indent), out.end());
|
||||
column = current_indent;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// nope, line is not empty. do a hard CR
|
||||
break_line();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// will this happen? (i.e. column <= current_indent)
|
||||
while (column != current_indent)
|
||||
{
|
||||
while (column != current_indent) {
|
||||
out += ' ';
|
||||
++column;
|
||||
}
|
||||
@@ -101,38 +102,31 @@ namespace quickbook
|
||||
// Strings will occur only in tag attributes. Normal content
|
||||
// will have " instead. We shall deal only with tag
|
||||
// attributes here.
|
||||
if (ch == '"')
|
||||
in_string = !in_string; // don't break strings!
|
||||
if (ch == '"') in_string = !in_string; // don't break strings!
|
||||
|
||||
if (!in_string && std::isspace(static_cast<unsigned char>(ch)))
|
||||
{
|
||||
if (!in_string && std::isspace(static_cast<unsigned char>(ch))) {
|
||||
// we can break spaces if they are not inside strings
|
||||
if (!std::isspace(static_cast<unsigned char>(prev)))
|
||||
{
|
||||
if (column >= linewidth)
|
||||
{
|
||||
if (!std::isspace(static_cast<unsigned char>(prev))) {
|
||||
if (column >= linewidth) {
|
||||
break_line();
|
||||
if (column == 0 && ch == ' ')
|
||||
{
|
||||
if (column == 0 && ch == ' ') {
|
||||
++column;
|
||||
out += ' ';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
++column;
|
||||
out += ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// we can break tag boundaries and stuff after
|
||||
// delimiters if they are not inside strings
|
||||
// and *only-if* the preceding char is a space
|
||||
if (!in_string
|
||||
&& column >= linewidth
|
||||
&& (ch == '<' && std::isspace(static_cast<unsigned char>(prev))))
|
||||
if (!in_string && column >= linewidth &&
|
||||
(ch == '<' &&
|
||||
std::isspace(static_cast<unsigned char>(prev))))
|
||||
break_line();
|
||||
out += ch;
|
||||
++column;
|
||||
@@ -141,29 +135,26 @@ namespace quickbook
|
||||
prev = ch;
|
||||
}
|
||||
|
||||
void
|
||||
print(iter_type f, iter_type l)
|
||||
void print(iter_type f, iter_type l)
|
||||
{
|
||||
for (iter_type i = f; i != l; ++i)
|
||||
print(*i);
|
||||
}
|
||||
|
||||
void
|
||||
print_tag(iter_type f, iter_type l, bool is_flow_tag)
|
||||
void print_tag(iter_type f, iter_type l, bool is_flow_tag)
|
||||
{
|
||||
if (is_flow_tag)
|
||||
{
|
||||
if (is_flow_tag) {
|
||||
print(f, l);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// This is not a flow tag, so, we're going to do a
|
||||
// carriage return anyway. Let us remove extra right
|
||||
// spaces.
|
||||
std::string str(f, l);
|
||||
BOOST_ASSERT(f != l); // this should not happen
|
||||
iter_type i = str.end();
|
||||
while (i != str.begin() && std::isspace(static_cast<unsigned char>(*(i-1))))
|
||||
while (i != str.begin() &&
|
||||
std::isspace(static_cast<unsigned char>(*(i - 1))))
|
||||
--i;
|
||||
print(str.begin(), i);
|
||||
}
|
||||
@@ -176,73 +167,40 @@ namespace quickbook
|
||||
bool in_string;
|
||||
int linewidth;
|
||||
|
||||
private:
|
||||
private:
|
||||
printer& operator=(printer const&);
|
||||
};
|
||||
|
||||
char const* block_tags_[] =
|
||||
{
|
||||
"author"
|
||||
, "blockquote"
|
||||
, "bridgehead"
|
||||
, "callout"
|
||||
, "calloutlist"
|
||||
, "caution"
|
||||
, "copyright"
|
||||
, "entry"
|
||||
, "important"
|
||||
, "informaltable"
|
||||
, "itemizedlist"
|
||||
, "legalnotice"
|
||||
, "listitem"
|
||||
, "note"
|
||||
, "orderedlist"
|
||||
, "para"
|
||||
, "row"
|
||||
, "section"
|
||||
, "simpara"
|
||||
, "table"
|
||||
, "tbody"
|
||||
, "textobject"
|
||||
, "tgroup"
|
||||
, "thead"
|
||||
, "tip"
|
||||
, "variablelist"
|
||||
, "varlistentry"
|
||||
, "warning"
|
||||
, "xml"
|
||||
, "xi:include"
|
||||
};
|
||||
char const* block_tags_[] = {
|
||||
"author", "blockquote", "bridgehead", "callout",
|
||||
"calloutlist", "caution", "copyright", "entry",
|
||||
"important", "informaltable", "itemizedlist", "legalnotice",
|
||||
"listitem", "note", "orderedlist", "para",
|
||||
"row", "section", "simpara", "table",
|
||||
"tbody", "textobject", "tgroup", "thead",
|
||||
"tip", "variablelist", "varlistentry", "warning",
|
||||
"xml", "xi:include"};
|
||||
|
||||
char const* doc_types_[] =
|
||||
{
|
||||
"book"
|
||||
, "article"
|
||||
, "library"
|
||||
, "chapter"
|
||||
, "part"
|
||||
, "appendix"
|
||||
, "preface"
|
||||
, "qandadiv"
|
||||
, "qandaset"
|
||||
, "reference"
|
||||
, "set"
|
||||
};
|
||||
char const* doc_types_[] = {"book", "article", "library", "chapter",
|
||||
"part", "appendix", "preface", "qandadiv",
|
||||
"qandaset", "reference", "set"};
|
||||
|
||||
struct tidy_compiler
|
||||
{
|
||||
tidy_compiler(std::string& out_, int linewidth_)
|
||||
: out(out_), current_indent(0), printer_(out, current_indent, linewidth_)
|
||||
: out(out_)
|
||||
, current_indent(0)
|
||||
, printer_(out, current_indent, linewidth_)
|
||||
{
|
||||
static std::size_t const n_block_tags = sizeof(block_tags_)/sizeof(char const*);
|
||||
for (std::size_t i = 0; i != n_block_tags; ++i)
|
||||
{
|
||||
static std::size_t const n_block_tags =
|
||||
sizeof(block_tags_) / sizeof(char const*);
|
||||
for (std::size_t i = 0; i != n_block_tags; ++i) {
|
||||
block_tags.insert(block_tags_[i]);
|
||||
}
|
||||
|
||||
static std::size_t const n_doc_types = sizeof(doc_types_)/sizeof(char const*);
|
||||
for (std::size_t i = 0; i != n_doc_types; ++i)
|
||||
{
|
||||
static std::size_t const n_doc_types =
|
||||
sizeof(doc_types_) / sizeof(char const*);
|
||||
for (std::size_t i = 0; i != n_doc_types; ++i) {
|
||||
block_tags.insert(doc_types_[i]);
|
||||
block_tags.insert(doc_types_[i] + std::string("info"));
|
||||
block_tags.insert(doc_types_[i] + std::string("purpose"));
|
||||
@@ -261,17 +219,18 @@ namespace quickbook
|
||||
printer printer_;
|
||||
std::string current_tag;
|
||||
|
||||
private:
|
||||
private:
|
||||
tidy_compiler& operator=(tidy_compiler const&);
|
||||
};
|
||||
|
||||
struct tidy_grammar : cl::grammar<tidy_grammar>
|
||||
{
|
||||
tidy_grammar(tidy_compiler& state_, int indent_)
|
||||
: state(state_), indent(indent_) {}
|
||||
: state(state_), indent(indent_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Scanner>
|
||||
struct definition
|
||||
template <typename Scanner> struct definition
|
||||
{
|
||||
definition(tidy_grammar const& self)
|
||||
{
|
||||
@@ -329,12 +288,10 @@ namespace quickbook
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
cl::rule<Scanner> const&
|
||||
start() { return tidy; }
|
||||
cl::rule<Scanner> const& start() { return tidy; }
|
||||
|
||||
cl::rule<Scanner>
|
||||
tidy, tag, start_tag, start_end_tag,
|
||||
content, end_tag, markup, code, escape;
|
||||
cl::rule<Scanner> tidy, tag, start_tag, start_end_tag, content,
|
||||
end_tag, markup, code, escape;
|
||||
};
|
||||
|
||||
void do_escape_post(iter_type f, iter_type l) const
|
||||
@@ -348,7 +305,7 @@ namespace quickbook
|
||||
while (f != l && std::isspace(*f)) {
|
||||
++f;
|
||||
}
|
||||
while (f != l && std::isspace(*(l-1))) {
|
||||
while (f != l && std::isspace(*(l - 1))) {
|
||||
--l;
|
||||
}
|
||||
for (iter_type i = f; i != l; ++i) {
|
||||
@@ -359,30 +316,23 @@ namespace quickbook
|
||||
void do_code(iter_type f, iter_type l) const
|
||||
{
|
||||
state.printer_.trim_spaces();
|
||||
if (state.out[state.out.size() - 1] != '\n')
|
||||
state.out += '\n';
|
||||
if (state.out[state.out.size() - 1] != '\n') state.out += '\n';
|
||||
// print the string taking care of line
|
||||
// ending CR/LF platform issues
|
||||
for (iter_type i = f; i != l; ++i)
|
||||
{
|
||||
if (*i == '\n')
|
||||
{
|
||||
for (iter_type i = f; i != l; ++i) {
|
||||
if (*i == '\n') {
|
||||
state.printer_.trim_spaces();
|
||||
state.out += '\n';
|
||||
++i;
|
||||
if (i != l && *i != '\r')
|
||||
state.out += *i;
|
||||
if (i != l && *i != '\r') state.out += *i;
|
||||
}
|
||||
else if (*i == '\r')
|
||||
{
|
||||
else if (*i == '\r') {
|
||||
state.printer_.trim_spaces();
|
||||
state.out += '\n';
|
||||
++i;
|
||||
if (i != l && *i != '\n')
|
||||
state.out += *i;
|
||||
if (i != l && *i != '\n') state.out += *i;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
state.out += *i;
|
||||
}
|
||||
}
|
||||
@@ -398,22 +348,18 @@ namespace quickbook
|
||||
void do_start_end_tag(iter_type f, iter_type l) const
|
||||
{
|
||||
bool is_flow_tag = state.is_flow_tag(state.current_tag);
|
||||
if (!is_flow_tag)
|
||||
state.printer_.align_indent();
|
||||
if (!is_flow_tag) state.printer_.align_indent();
|
||||
state.printer_.print_tag(f, l, is_flow_tag);
|
||||
if (!is_flow_tag)
|
||||
state.printer_.break_line();
|
||||
if (!is_flow_tag) state.printer_.break_line();
|
||||
}
|
||||
|
||||
void do_start_tag(iter_type f, iter_type l) const
|
||||
{
|
||||
state.tags.push(state.current_tag);
|
||||
bool is_flow_tag = state.is_flow_tag(state.current_tag);
|
||||
if (!is_flow_tag)
|
||||
state.printer_.align_indent();
|
||||
if (!is_flow_tag) state.printer_.align_indent();
|
||||
state.printer_.print_tag(f, l, is_flow_tag);
|
||||
if (!is_flow_tag)
|
||||
{
|
||||
if (!is_flow_tag) {
|
||||
state.current_indent += indent;
|
||||
state.printer_.break_line();
|
||||
}
|
||||
@@ -428,48 +374,39 @@ namespace quickbook
|
||||
{
|
||||
if (state.tags.empty())
|
||||
throw quickbook::post_process_failure("Mismatched tags.");
|
||||
|
||||
|
||||
bool is_flow_tag = state.is_flow_tag(state.tags.top());
|
||||
if (!is_flow_tag)
|
||||
{
|
||||
if (!is_flow_tag) {
|
||||
state.current_indent -= indent;
|
||||
state.printer_.align_indent();
|
||||
}
|
||||
state.printer_.print_tag(f, l, is_flow_tag);
|
||||
if (!is_flow_tag)
|
||||
state.printer_.break_line();
|
||||
if (!is_flow_tag) state.printer_.break_line();
|
||||
state.tags.pop();
|
||||
}
|
||||
|
||||
tidy_compiler& state;
|
||||
int indent;
|
||||
|
||||
private:
|
||||
private:
|
||||
tidy_grammar& operator=(tidy_grammar const&);
|
||||
};
|
||||
|
||||
std::string post_process(
|
||||
std::string const& in
|
||||
, int indent
|
||||
, int linewidth)
|
||||
std::string post_process(std::string const& in, int indent, int linewidth)
|
||||
{
|
||||
if (indent == -1)
|
||||
indent = 2; // set default to 2
|
||||
if (linewidth == -1)
|
||||
linewidth = 80; // set default to 80
|
||||
if (indent == -1) indent = 2; // set default to 2
|
||||
if (linewidth == -1) linewidth = 80; // set default to 80
|
||||
|
||||
std::string tidy;
|
||||
tidy_compiler state(tidy, linewidth);
|
||||
tidy_grammar g(state, indent);
|
||||
cl::parse_info<iter_type> r = parse(in.begin(), in.end(), g, cl::space_p);
|
||||
if (r.full)
|
||||
{
|
||||
cl::parse_info<iter_type> r =
|
||||
parse(in.begin(), in.end(), g, cl::space_p);
|
||||
if (r.full) {
|
||||
return tidy;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
throw quickbook::post_process_failure("Post Processing Failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,23 +9,22 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
std::string post_process(
|
||||
std::string const& in
|
||||
, int indent = -1
|
||||
, int linewidth = -1);
|
||||
std::string const& in, int indent = -1, int linewidth = -1);
|
||||
|
||||
struct post_process_failure : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
public:
|
||||
explicit post_process_failure(std::string const& error)
|
||||
: std::runtime_error(error) {}
|
||||
: std::runtime_error(error)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP
|
||||
|
||||
|
||||
@@ -7,30 +7,30 @@
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#include "grammar.hpp"
|
||||
#include "quickbook.hpp"
|
||||
#include "state.hpp"
|
||||
#include "actions.hpp"
|
||||
#include "post_process.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "files.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "path.hpp"
|
||||
#include "document_state.hpp"
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include "actions.hpp"
|
||||
#include "document_state.hpp"
|
||||
#include "files.hpp"
|
||||
#include "grammar.hpp"
|
||||
#include "path.hpp"
|
||||
#include "post_process.hpp"
|
||||
#include "state.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
@@ -38,7 +38,7 @@
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
|
||||
#pragma warning(disable:4355)
|
||||
#pragma warning(disable : 4355)
|
||||
#endif
|
||||
|
||||
#define QUICKBOOK_VERSION "Quickbook Version 1.7.0"
|
||||
@@ -48,9 +48,9 @@ namespace quickbook
|
||||
namespace cl = boost::spirit::classic;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
tm* current_time; // the current time
|
||||
tm* current_time; // the current time
|
||||
tm* current_gm_time; // the current UTC time
|
||||
bool debug_mode; // for quickbook developers only
|
||||
bool debug_mode; // for quickbook developers only
|
||||
bool self_linked_headers;
|
||||
std::vector<fs::path> include_path;
|
||||
std::vector<std::string> preset_defines;
|
||||
@@ -58,11 +58,10 @@ namespace quickbook
|
||||
|
||||
static void set_macros(quickbook::state& state)
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator
|
||||
it = preset_defines.begin(),
|
||||
end = preset_defines.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
for (std::vector<std::string>::const_iterator
|
||||
it = preset_defines.begin(),
|
||||
end = preset_defines.end();
|
||||
it != end; ++it) {
|
||||
quickbook::string_view val(*it);
|
||||
parse_iterator first(val.begin());
|
||||
parse_iterator last(val.end());
|
||||
@@ -71,11 +70,8 @@ namespace quickbook
|
||||
cl::parse(first, last, state.grammar().command_line_macro);
|
||||
|
||||
if (!info.full) {
|
||||
detail::outerr()
|
||||
<< "Error parsing command line definition: '"
|
||||
<< *it
|
||||
<< "'"
|
||||
<< std::endl;
|
||||
detail::outerr() << "Error parsing command line definition: '"
|
||||
<< *it << "'" << std::endl;
|
||||
++state.error_count;
|
||||
}
|
||||
}
|
||||
@@ -86,25 +82,29 @@ namespace quickbook
|
||||
// Parse a file
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
void parse_file(quickbook::state& state, value include_doc_id, bool nested_file)
|
||||
void parse_file(
|
||||
quickbook::state& state, value include_doc_id, bool nested_file)
|
||||
{
|
||||
parse_iterator first(state.current_file->source().begin());
|
||||
parse_iterator last(state.current_file->source().end());
|
||||
|
||||
cl::parse_info<parse_iterator> info = cl::parse(first, last, state.grammar().doc_info);
|
||||
cl::parse_info<parse_iterator> info =
|
||||
cl::parse(first, last, state.grammar().doc_info);
|
||||
assert(info.hit);
|
||||
|
||||
if (!state.error_count)
|
||||
{
|
||||
std::string doc_type = pre(state, info.stop, include_doc_id, nested_file);
|
||||
if (!state.error_count) {
|
||||
std::string doc_type =
|
||||
pre(state, info.stop, include_doc_id, nested_file);
|
||||
|
||||
info = cl::parse(info.hit ? info.stop : first, last, state.grammar().block_start);
|
||||
info = cl::parse(
|
||||
info.hit ? info.stop : first, last,
|
||||
state.grammar().block_start);
|
||||
|
||||
post(state, doc_type);
|
||||
|
||||
if (!info.full)
|
||||
{
|
||||
file_position const& pos = state.current_file->position_of(info.stop.base());
|
||||
if (!info.full) {
|
||||
file_position const& pos =
|
||||
state.current_file->position_of(info.stop.base());
|
||||
detail::outerr(state.current_file->path, pos.line)
|
||||
<< "Syntax Error near column " << pos.column << ".\n";
|
||||
++state.error_count;
|
||||
@@ -114,13 +114,14 @@ namespace quickbook
|
||||
|
||||
struct parse_document_options
|
||||
{
|
||||
parse_document_options() :
|
||||
indent(-1),
|
||||
linewidth(-1),
|
||||
pretty_print(true),
|
||||
strict_mode(false),
|
||||
deps_out_flags(quickbook::dependency_tracker::default_)
|
||||
{}
|
||||
parse_document_options()
|
||||
: indent(-1)
|
||||
, linewidth(-1)
|
||||
, pretty_print(true)
|
||||
, strict_mode(false)
|
||||
, deps_out_flags(quickbook::dependency_tracker::default_)
|
||||
{
|
||||
}
|
||||
|
||||
int indent;
|
||||
int linewidth;
|
||||
@@ -132,11 +133,10 @@ namespace quickbook
|
||||
fs::path xinclude_base;
|
||||
};
|
||||
|
||||
static int
|
||||
parse_document(
|
||||
fs::path const& filein_
|
||||
, fs::path const& fileout_
|
||||
, parse_document_options const& options_)
|
||||
static int parse_document(
|
||||
fs::path const& filein_,
|
||||
fs::path const& fileout_,
|
||||
parse_document_options const& options_)
|
||||
{
|
||||
string_stream buffer;
|
||||
document_state output;
|
||||
@@ -144,7 +144,8 @@ namespace quickbook
|
||||
int result = 0;
|
||||
|
||||
try {
|
||||
quickbook::state state(filein_, options_.xinclude_base, buffer, output);
|
||||
quickbook::state state(
|
||||
filein_, options_.xinclude_base, buffer, output);
|
||||
state.strict_mode = options_.strict_mode;
|
||||
set_macros(state);
|
||||
|
||||
@@ -154,7 +155,7 @@ namespace quickbook
|
||||
|
||||
parse_file(state);
|
||||
|
||||
if(state.error_count) {
|
||||
if (state.error_count) {
|
||||
detail::outerr()
|
||||
<< "Error count: " << state.error_count << ".\n";
|
||||
}
|
||||
@@ -162,70 +163,55 @@ namespace quickbook
|
||||
|
||||
result = state.error_count ? 1 : 0;
|
||||
|
||||
if (!options_.deps_out.empty())
|
||||
{
|
||||
state.dependencies.write_dependencies(options_.deps_out,
|
||||
options_.deps_out_flags);
|
||||
if (!options_.deps_out.empty()) {
|
||||
state.dependencies.write_dependencies(
|
||||
options_.deps_out, options_.deps_out_flags);
|
||||
}
|
||||
|
||||
if (!options_.locations_out.empty())
|
||||
{
|
||||
if (!options_.locations_out.empty()) {
|
||||
fs::ofstream out(options_.locations_out);
|
||||
state.dependencies.write_dependencies(options_.locations_out,
|
||||
dependency_tracker::checked);
|
||||
state.dependencies.write_dependencies(
|
||||
options_.locations_out, dependency_tracker::checked);
|
||||
}
|
||||
}
|
||||
catch (load_error& e) {
|
||||
} catch (load_error& e) {
|
||||
detail::outerr(filein_) << e.what() << std::endl;
|
||||
result = 1;
|
||||
}
|
||||
catch (std::runtime_error& e) {
|
||||
} catch (std::runtime_error& e) {
|
||||
detail::outerr() << e.what() << std::endl;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
if (!fileout_.empty() && result == 0)
|
||||
{
|
||||
if (!fileout_.empty() && result == 0) {
|
||||
std::string stage2 = output.replace_placeholders(buffer.str());
|
||||
|
||||
fs::ofstream fileout(fileout_);
|
||||
|
||||
if (fileout.fail()) {
|
||||
::quickbook::detail::outerr()
|
||||
<< "Error opening output file "
|
||||
<< fileout_
|
||||
<< std::endl;
|
||||
<< "Error opening output file " << fileout_ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (options_.pretty_print)
|
||||
{
|
||||
try
|
||||
{
|
||||
fileout << post_process(stage2, options_.indent,
|
||||
options_.linewidth);
|
||||
}
|
||||
catch (quickbook::post_process_failure&)
|
||||
{
|
||||
if (options_.pretty_print) {
|
||||
try {
|
||||
fileout << post_process(
|
||||
stage2, options_.indent, options_.linewidth);
|
||||
} catch (quickbook::post_process_failure&) {
|
||||
// fallback!
|
||||
::quickbook::detail::outerr()
|
||||
<< "Post Processing Failed."
|
||||
<< std::endl;
|
||||
<< "Post Processing Failed." << std::endl;
|
||||
fileout << stage2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
fileout << stage2;
|
||||
}
|
||||
|
||||
if (fileout.fail()) {
|
||||
::quickbook::detail::outerr()
|
||||
<< "Error writing to output file "
|
||||
<< fileout_
|
||||
<< std::endl;
|
||||
<< "Error writing to output file " << fileout_ << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -240,11 +226,9 @@ namespace quickbook
|
||||
// Main program
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
namespace fs = boost::filesystem;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
@@ -260,7 +244,8 @@ main(int argc, char* argv[])
|
||||
using namespace quickbook;
|
||||
using quickbook::detail::command_line_string;
|
||||
|
||||
// First thing, the filesystem should record the current working directory.
|
||||
// First thing, the filesystem should record the current working
|
||||
// directory.
|
||||
fs::initial_path<fs::path>();
|
||||
|
||||
// Various initialisation methods
|
||||
@@ -335,9 +320,9 @@ main(int argc, char* argv[])
|
||||
|
||||
int wide_argc;
|
||||
LPWSTR* wide_argv = CommandLineToArgvW(GetCommandLineW(), &wide_argc);
|
||||
if (!wide_argv)
|
||||
{
|
||||
quickbook::detail::outerr() << "Error getting argument values." << std::endl;
|
||||
if (!wide_argv) {
|
||||
quickbook::detail::outerr()
|
||||
<< "Error getting argument values." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -345,14 +330,14 @@ main(int argc, char* argv[])
|
||||
wcommand_line_parser(wide_argc, wide_argv)
|
||||
.options(all)
|
||||
.positional(p)
|
||||
.run(), vm);
|
||||
.run(),
|
||||
vm);
|
||||
|
||||
LocalFree(wide_argv);
|
||||
#else
|
||||
store(command_line_parser(argc, argv)
|
||||
.options(all)
|
||||
.positional(p)
|
||||
.run(), vm);
|
||||
store(
|
||||
command_line_parser(argc, argv).options(all).positional(p).run(),
|
||||
vm);
|
||||
#endif
|
||||
|
||||
notify(vm);
|
||||
@@ -363,8 +348,7 @@ main(int argc, char* argv[])
|
||||
bool expect_errors = vm.count("expect-errors");
|
||||
int error_count = 0;
|
||||
|
||||
if (vm.count("help"))
|
||||
{
|
||||
if (vm.count("help")) {
|
||||
std::ostringstream description_text;
|
||||
description_text << desc;
|
||||
|
||||
@@ -373,37 +357,29 @@ main(int argc, char* argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vm.count("version"))
|
||||
{
|
||||
if (vm.count("version")) {
|
||||
std::string boost_version = BOOST_LIB_VERSION;
|
||||
boost::replace(boost_version, '_', '.');
|
||||
|
||||
quickbook::detail::out()
|
||||
<< QUICKBOOK_VERSION
|
||||
<< " (Boost "
|
||||
<< boost_version
|
||||
<< ")"
|
||||
<< std::endl;
|
||||
quickbook::detail::out() << QUICKBOOK_VERSION << " (Boost "
|
||||
<< boost_version << ")" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
quickbook::detail::set_ms_errors(vm.count("ms-errors"));
|
||||
|
||||
if (vm.count("no-pretty-print"))
|
||||
options.pretty_print = false;
|
||||
if (vm.count("no-pretty-print")) options.pretty_print = false;
|
||||
|
||||
options.strict_mode = !!vm.count("strict");
|
||||
|
||||
quickbook::self_linked_headers = !vm.count("no-self-linked-headers");
|
||||
|
||||
if (vm.count("indent"))
|
||||
options.indent = vm["indent"].as<int>();
|
||||
if (vm.count("indent")) options.indent = vm["indent"].as<int>();
|
||||
|
||||
if (vm.count("linewidth"))
|
||||
options.linewidth = vm["linewidth"].as<int>();
|
||||
|
||||
if (vm.count("debug"))
|
||||
{
|
||||
if (vm.count("debug")) {
|
||||
static tm timeinfo;
|
||||
timeinfo.tm_year = 2000 - 1900;
|
||||
timeinfo.tm_mon = 12 - 1;
|
||||
@@ -417,8 +393,7 @@ main(int argc, char* argv[])
|
||||
quickbook::current_gm_time = &timeinfo;
|
||||
quickbook::debug_mode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
time_t t = std::time(0);
|
||||
static tm lt = *localtime(&t);
|
||||
static tm gmt = *gmtime(&t);
|
||||
@@ -428,8 +403,7 @@ main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
quickbook::include_path.clear();
|
||||
if (vm.count("include-path"))
|
||||
{
|
||||
if (vm.count("include-path")) {
|
||||
boost::transform(
|
||||
vm["include-path"].as<std::vector<command_line_string> >(),
|
||||
std::back_inserter(quickbook::include_path),
|
||||
@@ -437,57 +411,49 @@ main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
quickbook::preset_defines.clear();
|
||||
if (vm.count("define"))
|
||||
{
|
||||
if (vm.count("define")) {
|
||||
boost::transform(
|
||||
vm["define"].as<std::vector<command_line_string> >(),
|
||||
std::back_inserter(quickbook::preset_defines),
|
||||
quickbook::detail::command_line_to_utf8);
|
||||
}
|
||||
|
||||
if (vm.count("input-file"))
|
||||
{
|
||||
if (vm.count("input-file")) {
|
||||
fs::path filein = quickbook::detail::command_line_to_path(
|
||||
vm["input-file"].as<command_line_string>());
|
||||
fs::path fileout;
|
||||
|
||||
if (!fs::exists(filein)) {
|
||||
quickbook::detail::outerr()
|
||||
<< "file not found: "
|
||||
<< filein
|
||||
<< std::endl;
|
||||
<< "file not found: " << filein << std::endl;
|
||||
++error_count;
|
||||
}
|
||||
|
||||
bool default_output = true;
|
||||
|
||||
if (vm.count("no-output"))
|
||||
{
|
||||
if (vm.count("no-output")) {
|
||||
default_output = false;
|
||||
}
|
||||
|
||||
if (vm.count("output-deps"))
|
||||
{
|
||||
options.deps_out =
|
||||
quickbook::detail::command_line_to_path(
|
||||
vm["output-deps"].as<command_line_string>());
|
||||
if (vm.count("output-deps")) {
|
||||
options.deps_out = quickbook::detail::command_line_to_path(
|
||||
vm["output-deps"].as<command_line_string>());
|
||||
default_output = false;
|
||||
}
|
||||
|
||||
if (vm.count("output-deps-format"))
|
||||
{
|
||||
if (vm.count("output-deps-format")) {
|
||||
std::string format_flags =
|
||||
quickbook::detail::command_line_to_utf8(
|
||||
vm["output-deps-format"].as<command_line_string>());
|
||||
|
||||
std::vector<std::string> flag_names;
|
||||
boost::algorithm::split(flag_names, format_flags,
|
||||
boost::algorithm::is_any_of(", "),
|
||||
boost::algorithm::token_compress_on);
|
||||
boost::algorithm::split(
|
||||
flag_names, format_flags, boost::algorithm::is_any_of(", "),
|
||||
boost::algorithm::token_compress_on);
|
||||
|
||||
unsigned flags = 0;
|
||||
|
||||
BOOST_FOREACH(std::string const& flag, flag_names) {
|
||||
BOOST_FOREACH (std::string const& flag, flag_names) {
|
||||
if (flag == "checked") {
|
||||
flags |= quickbook::dependency_tracker::checked;
|
||||
}
|
||||
@@ -496,9 +462,8 @@ main(int argc, char* argv[])
|
||||
}
|
||||
else if (!flag.empty()) {
|
||||
quickbook::detail::outerr()
|
||||
<< "Unknown dependency format flag: "
|
||||
<< flag
|
||||
<<std::endl;
|
||||
<< "Unknown dependency format flag: " << flag
|
||||
<< std::endl;
|
||||
|
||||
++error_count;
|
||||
}
|
||||
@@ -508,114 +473,102 @@ main(int argc, char* argv[])
|
||||
quickbook::dependency_tracker::flags(flags);
|
||||
}
|
||||
|
||||
if (vm.count("output-checked-locations"))
|
||||
{
|
||||
options.locations_out =
|
||||
quickbook::detail::command_line_to_path(
|
||||
vm["output-checked-locations"].as<command_line_string>());
|
||||
if (vm.count("output-checked-locations")) {
|
||||
options.locations_out = quickbook::detail::command_line_to_path(
|
||||
vm["output-checked-locations"].as<command_line_string>());
|
||||
default_output = false;
|
||||
}
|
||||
|
||||
if (vm.count("output-file"))
|
||||
{
|
||||
if (vm.count("output-file")) {
|
||||
fileout = quickbook::detail::command_line_to_path(
|
||||
vm["output-file"].as<command_line_string>());
|
||||
|
||||
fs::path parent = fileout.parent_path();
|
||||
if (!parent.empty() && !fs::is_directory(parent))
|
||||
{
|
||||
if (!parent.empty() && !fs::is_directory(parent)) {
|
||||
quickbook::detail::outerr()
|
||||
<< "parent directory not found for output file"
|
||||
<< std::endl;
|
||||
++error_count;
|
||||
}
|
||||
}
|
||||
else if (default_output)
|
||||
{
|
||||
else if (default_output) {
|
||||
fileout = filein;
|
||||
fileout.replace_extension(".xml");
|
||||
}
|
||||
|
||||
if (vm.count("xinclude-base"))
|
||||
{
|
||||
options.xinclude_base =
|
||||
quickbook::detail::command_line_to_path(
|
||||
vm["xinclude-base"].as<command_line_string>());
|
||||
if (vm.count("xinclude-base")) {
|
||||
options.xinclude_base = quickbook::detail::command_line_to_path(
|
||||
vm["xinclude-base"].as<command_line_string>());
|
||||
|
||||
// I'm not sure if this error check is necessary.
|
||||
// There might be valid reasons to use a path that doesn't
|
||||
// exist yet, or a path that just generates valid relative
|
||||
// paths.
|
||||
if (!fs::is_directory(options.xinclude_base))
|
||||
{
|
||||
if (!fs::is_directory(options.xinclude_base)) {
|
||||
quickbook::detail::outerr()
|
||||
<< "xinclude-base is not a directory"
|
||||
<< std::endl;
|
||||
<< "xinclude-base is not a directory" << std::endl;
|
||||
++error_count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
options.xinclude_base = fileout.parent_path();
|
||||
if (options.xinclude_base.empty()) {
|
||||
options.xinclude_base = ".";
|
||||
}
|
||||
|
||||
// If fileout was implicitly created from filein, then it should be in filein's directory.
|
||||
// If fileout was explicitly specified, then it's already been checked.
|
||||
// If fileout was implicitly created from filein, then it should
|
||||
// be in filein's directory.
|
||||
// If fileout was explicitly specified, then it's already been
|
||||
// checked.
|
||||
assert(error_count || fs::is_directory(options.xinclude_base));
|
||||
}
|
||||
|
||||
if (vm.count("image-location"))
|
||||
{
|
||||
quickbook::image_location = quickbook::detail::command_line_to_path(
|
||||
vm["image-location"].as<command_line_string>());
|
||||
if (vm.count("image-location")) {
|
||||
quickbook::image_location =
|
||||
quickbook::detail::command_line_to_path(
|
||||
vm["image-location"].as<command_line_string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
quickbook::image_location = filein.parent_path() / "html";
|
||||
}
|
||||
|
||||
if (!error_count) {
|
||||
if (!fileout.empty()) {
|
||||
quickbook::detail::out() << "Generating Output File: "
|
||||
<< fileout
|
||||
<< std::endl;
|
||||
quickbook::detail::out()
|
||||
<< "Generating Output File: " << fileout << std::endl;
|
||||
}
|
||||
|
||||
error_count += quickbook::parse_document(
|
||||
filein, fileout, options);
|
||||
error_count +=
|
||||
quickbook::parse_document(filein, fileout, options);
|
||||
}
|
||||
|
||||
if (expect_errors)
|
||||
{
|
||||
if (!error_count) quickbook::detail::outerr() << "No errors detected for --expect-errors." << std::endl;
|
||||
if (expect_errors) {
|
||||
if (!error_count)
|
||||
quickbook::detail::outerr()
|
||||
<< "No errors detected for --expect-errors."
|
||||
<< std::endl;
|
||||
return !error_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
return error_count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
std::ostringstream description_text;
|
||||
description_text << desc;
|
||||
|
||||
quickbook::detail::outerr() << "No filename given\n\n"
|
||||
<< description_text.str() << std::endl;
|
||||
<< description_text.str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
catch(std::exception& e)
|
||||
{
|
||||
catch (std::exception& e) {
|
||||
quickbook::detail::outerr() << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
catch(...)
|
||||
{
|
||||
catch (...) {
|
||||
quickbook::detail::outerr() << "Exception of unknown type caught\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_QUICKBOOK_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_QUICKBOOK_HPP
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "fwd.hpp"
|
||||
#include "values.hpp"
|
||||
@@ -23,7 +23,7 @@ namespace quickbook
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
extern tm* current_time; // the current time
|
||||
extern tm* current_time; // the current time
|
||||
extern tm* current_gm_time; // the current UTC time
|
||||
extern bool debug_mode;
|
||||
extern bool self_linked_headers;
|
||||
@@ -31,9 +31,10 @@ namespace quickbook
|
||||
extern std::vector<std::string> preset_defines;
|
||||
extern fs::path image_location;
|
||||
|
||||
void parse_file(quickbook::state& state,
|
||||
value include_doc_id = value(),
|
||||
bool nested_file = false);
|
||||
void parse_file(
|
||||
quickbook::state& state,
|
||||
value include_doc_id = value(),
|
||||
bool nested_file = false);
|
||||
// Some initialisation methods
|
||||
//
|
||||
// Declared here to avoid including other headers
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace quickbook {
|
||||
namespace quickbook
|
||||
{
|
||||
|
||||
struct scoped_action_base
|
||||
{
|
||||
bool start() { return true; }
|
||||
template <typename Iterator>
|
||||
void success(Iterator, Iterator) {}
|
||||
template <typename Iterator> void success(Iterator, Iterator) {}
|
||||
void failure() {}
|
||||
void cleanup() {}
|
||||
|
||||
|
||||
template <typename ResultT, typename ScannerT>
|
||||
bool result(ResultT r, ScannerT const&)
|
||||
{
|
||||
|
||||
@@ -9,17 +9,17 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#include "state.hpp"
|
||||
#include "state_save.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include "document_state.hpp"
|
||||
#include "quickbook.hpp"
|
||||
#include "grammar.hpp"
|
||||
#include "path.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include "quickbook.hpp"
|
||||
#include "state_save.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
|
||||
#pragma warning(disable:4355)
|
||||
#pragma warning(disable : 4355)
|
||||
#endif
|
||||
|
||||
namespace quickbook
|
||||
@@ -29,8 +29,11 @@ namespace quickbook
|
||||
|
||||
unsigned qbk_version_n = 0; // qbk_major_version * 100 + qbk_minor_version
|
||||
|
||||
state::state(fs::path const& filein_, fs::path const& xinclude_base_,
|
||||
string_stream& out_, document_state& document_)
|
||||
state::state(
|
||||
fs::path const& filein_,
|
||||
fs::path const& xinclude_base_,
|
||||
string_stream& out_,
|
||||
document_state& document_)
|
||||
: grammar_()
|
||||
|
||||
, order_pos(0)
|
||||
@@ -67,77 +70,78 @@ namespace quickbook
|
||||
, values(¤t_file)
|
||||
{
|
||||
// add the predefined macros
|
||||
macro.add
|
||||
("__DATE__", std::string(quickbook_get_date))
|
||||
("__TIME__", std::string(quickbook_get_time))
|
||||
("__FILENAME__", std::string())
|
||||
;
|
||||
macro.add("__DATE__", std::string(quickbook_get_date))(
|
||||
"__TIME__",
|
||||
std::string(quickbook_get_time))("__FILENAME__", std::string());
|
||||
update_filename_macro();
|
||||
|
||||
boost::scoped_ptr<quickbook_grammar> g(
|
||||
new quickbook_grammar(*this));
|
||||
boost::scoped_ptr<quickbook_grammar> g(new quickbook_grammar(*this));
|
||||
grammar_.swap(g);
|
||||
}
|
||||
|
||||
quickbook_grammar& state::grammar() const {
|
||||
return *grammar_;
|
||||
quickbook_grammar& state::grammar() const { return *grammar_; }
|
||||
|
||||
void state::update_filename_macro()
|
||||
{
|
||||
*boost::spirit::classic::find(macro, "__FILENAME__") =
|
||||
detail::encode_string(
|
||||
detail::path_to_generic(current_path.abstract_file_path));
|
||||
}
|
||||
|
||||
void state::update_filename_macro() {
|
||||
*boost::spirit::classic::find(macro, "__FILENAME__")
|
||||
= detail::encode_string(
|
||||
detail::path_to_generic(current_path.abstract_file_path));
|
||||
}
|
||||
|
||||
unsigned state::get_new_order_pos() {
|
||||
return ++order_pos;
|
||||
}
|
||||
unsigned state::get_new_order_pos() { return ++order_pos; }
|
||||
|
||||
void state::push_output() {
|
||||
void state::push_output()
|
||||
{
|
||||
out.push();
|
||||
phrase.push();
|
||||
in_list_save.push(in_list);
|
||||
}
|
||||
|
||||
void state::pop_output() {
|
||||
void state::pop_output()
|
||||
{
|
||||
phrase.pop();
|
||||
out.pop();
|
||||
in_list = in_list_save.top();
|
||||
in_list_save.pop();
|
||||
}
|
||||
|
||||
source_mode_info state::tagged_source_mode() const {
|
||||
source_mode_info state::tagged_source_mode() const
|
||||
{
|
||||
source_mode_info result;
|
||||
|
||||
BOOST_FOREACH(source_mode_info const& s, tagged_source_mode_stack) {
|
||||
BOOST_FOREACH (source_mode_info const& s, tagged_source_mode_stack) {
|
||||
result.update(s);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
source_mode_info state::current_source_mode() const {
|
||||
source_mode_info state::current_source_mode() const
|
||||
{
|
||||
source_mode_info result = source_mode;
|
||||
|
||||
result.update(document.section_source_mode());
|
||||
|
||||
BOOST_FOREACH(source_mode_info const& s, tagged_source_mode_stack) {
|
||||
BOOST_FOREACH (source_mode_info const& s, tagged_source_mode_stack) {
|
||||
result.update(s);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void state::change_source_mode(source_mode_type s) {
|
||||
void state::change_source_mode(source_mode_type s)
|
||||
{
|
||||
source_mode = source_mode_info(s, get_new_order_pos());
|
||||
}
|
||||
|
||||
void state::push_tagged_source_mode(source_mode_type s) {
|
||||
void state::push_tagged_source_mode(source_mode_type s)
|
||||
{
|
||||
tagged_source_mode_stack.push_back(
|
||||
source_mode_info(s, s ? get_new_order_pos() : 0));
|
||||
}
|
||||
|
||||
void state::pop_tagged_source_mode() {
|
||||
void state::pop_tagged_source_mode()
|
||||
{
|
||||
assert(!tagged_source_mode_stack.empty());
|
||||
tagged_source_mode_stack.pop_back();
|
||||
}
|
||||
|
||||
103
src/state.hpp
103
src/state.hpp
@@ -12,14 +12,14 @@
|
||||
|
||||
#include <map>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include "parsers.hpp"
|
||||
#include "values_parse.hpp"
|
||||
#include "collector.hpp"
|
||||
#include "template_stack.hpp"
|
||||
#include "symbols.hpp"
|
||||
#include "dependency_tracker.hpp"
|
||||
#include "syntax_highlight.hpp"
|
||||
#include "include_paths.hpp"
|
||||
#include "parsers.hpp"
|
||||
#include "symbols.hpp"
|
||||
#include "syntax_highlight.hpp"
|
||||
#include "template_stack.hpp"
|
||||
#include "values_parse.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -28,65 +28,67 @@ namespace quickbook
|
||||
|
||||
struct state
|
||||
{
|
||||
state(fs::path const& filein_, fs::path const& xinclude_base, string_stream& out_,
|
||||
document_state&);
|
||||
state(
|
||||
fs::path const& filein_,
|
||||
fs::path const& xinclude_base,
|
||||
string_stream& out_,
|
||||
document_state&);
|
||||
|
||||
private:
|
||||
private:
|
||||
boost::scoped_ptr<quickbook_grammar> grammar_;
|
||||
|
||||
public:
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// State
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// State
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::vector<std::string> string_list;
|
||||
|
||||
static int const max_template_depth = 100;
|
||||
|
||||
// global state
|
||||
unsigned order_pos;
|
||||
fs::path xinclude_base;
|
||||
template_stack templates;
|
||||
int error_count;
|
||||
string_list anchors;
|
||||
bool warned_about_breaks;
|
||||
bool conditional;
|
||||
document_state& document;
|
||||
value_builder callouts; // callouts are global as
|
||||
int callout_depth; // they don't nest.
|
||||
dependency_tracker dependencies;
|
||||
bool explicit_list; // set when using a list
|
||||
bool strict_mode;
|
||||
// global state
|
||||
unsigned order_pos;
|
||||
fs::path xinclude_base;
|
||||
template_stack templates;
|
||||
int error_count;
|
||||
string_list anchors;
|
||||
bool warned_about_breaks;
|
||||
bool conditional;
|
||||
document_state& document;
|
||||
value_builder callouts; // callouts are global as
|
||||
int callout_depth; // they don't nest.
|
||||
dependency_tracker dependencies;
|
||||
bool explicit_list; // set when using a list
|
||||
bool strict_mode;
|
||||
|
||||
// state saved for files and templates.
|
||||
bool imported;
|
||||
string_symbols macro;
|
||||
source_mode_info source_mode;
|
||||
source_mode_type source_mode_next;
|
||||
value source_mode_next_pos;
|
||||
std::vector<source_mode_info>
|
||||
tagged_source_mode_stack;
|
||||
file_ptr current_file;
|
||||
quickbook_path current_path;
|
||||
// state saved for files and templates.
|
||||
bool imported;
|
||||
string_symbols macro;
|
||||
source_mode_info source_mode;
|
||||
source_mode_type source_mode_next;
|
||||
value source_mode_next_pos;
|
||||
std::vector<source_mode_info> tagged_source_mode_stack;
|
||||
file_ptr current_file;
|
||||
quickbook_path current_path;
|
||||
|
||||
// state saved for templates.
|
||||
int template_depth;
|
||||
int min_section_level;
|
||||
// state saved for templates.
|
||||
int template_depth;
|
||||
int min_section_level;
|
||||
|
||||
// output state - scoped by templates and grammar
|
||||
bool in_list; // generating a list
|
||||
std::stack<bool> in_list_save; // save the in_list state
|
||||
collector out; // main output stream
|
||||
collector phrase; // phrase output stream
|
||||
// output state - scoped by templates and grammar
|
||||
bool in_list; // generating a list
|
||||
std::stack<bool> in_list_save; // save the in_list state
|
||||
collector out; // main output stream
|
||||
collector phrase; // phrase output stream
|
||||
|
||||
// values state - scoped by everything.
|
||||
value_parser values; // parsed values
|
||||
// values state - scoped by everything.
|
||||
value_parser values; // parsed values
|
||||
|
||||
quickbook_grammar& grammar() const;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// actions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// actions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void update_filename_macro();
|
||||
|
||||
@@ -111,7 +113,8 @@ namespace quickbook
|
||||
void pop_tagged_source_mode();
|
||||
};
|
||||
|
||||
extern unsigned qbk_version_n; // qbk_major_version * 100 + qbk_minor_version
|
||||
extern unsigned
|
||||
qbk_version_n; // qbk_major_version * 100 + qbk_minor_version
|
||||
extern char const* quickbook_get_date;
|
||||
extern char const* quickbook_get_time;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace quickbook
|
||||
|
||||
struct state_save
|
||||
{
|
||||
enum scope_flags {
|
||||
enum scope_flags
|
||||
{
|
||||
scope_none = 0,
|
||||
scope_macros = 1,
|
||||
scope_templates = 2,
|
||||
@@ -44,7 +45,8 @@ namespace quickbook
|
||||
string_symbols macro;
|
||||
int template_depth;
|
||||
int min_section_level;
|
||||
private:
|
||||
|
||||
private:
|
||||
state_save(state_save const&);
|
||||
state_save& operator=(state_save const&);
|
||||
};
|
||||
|
||||
298
src/stream.cpp
298
src/stream.cpp
@@ -7,196 +7,208 @@
|
||||
=============================================================================*/
|
||||
|
||||
#include "stream.hpp"
|
||||
#include "path.hpp"
|
||||
#include "files.hpp"
|
||||
#include "path.hpp"
|
||||
|
||||
#if QUICKBOOK_WIDE_PATHS || QUICKBOOK_WIDE_STREAMS
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
namespace quickbook {
|
||||
namespace detail {
|
||||
namespace {
|
||||
bool ms_errors = false;
|
||||
}
|
||||
namespace quickbook
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool ms_errors = false;
|
||||
}
|
||||
|
||||
void set_ms_errors(bool x) {
|
||||
ms_errors = x;
|
||||
}
|
||||
void set_ms_errors(bool x) { ms_errors = x; }
|
||||
|
||||
#if QUICKBOOK_WIDE_STREAMS
|
||||
|
||||
void initialise_output()
|
||||
{
|
||||
if (_isatty(_fileno(stdout))) _setmode(_fileno(stdout), _O_U16TEXT);
|
||||
if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT);
|
||||
}
|
||||
|
||||
void write_utf8(ostream::base_ostream& out, quickbook::string_view x)
|
||||
{
|
||||
out << from_utf8(x);
|
||||
}
|
||||
|
||||
ostream& out()
|
||||
{
|
||||
static ostream x(std::wcout);
|
||||
return x;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
inline ostream& error_stream()
|
||||
void initialise_output()
|
||||
{
|
||||
static ostream x(std::wcerr);
|
||||
if (_isatty(_fileno(stdout))) _setmode(_fileno(stdout), _O_U16TEXT);
|
||||
if (_isatty(_fileno(stderr))) _setmode(_fileno(stderr), _O_U16TEXT);
|
||||
}
|
||||
|
||||
void write_utf8(ostream::base_ostream& out, quickbook::string_view x)
|
||||
{
|
||||
out << from_utf8(x);
|
||||
}
|
||||
|
||||
ostream& out()
|
||||
{
|
||||
static ostream x(std::wcout);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
inline ostream& error_stream()
|
||||
{
|
||||
static ostream x(std::wcerr);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void initialise_output()
|
||||
{
|
||||
}
|
||||
void initialise_output() {}
|
||||
|
||||
void write_utf8(ostream::base_ostream& out, quickbook::string_view x)
|
||||
{
|
||||
out << x;
|
||||
}
|
||||
|
||||
ostream& out()
|
||||
{
|
||||
static ostream x(std::cout);
|
||||
return x;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
inline ostream& error_stream()
|
||||
void write_utf8(ostream::base_ostream& out, quickbook::string_view x)
|
||||
{
|
||||
static ostream x(std::clog);
|
||||
out << x;
|
||||
}
|
||||
|
||||
ostream& out()
|
||||
{
|
||||
static ostream x(std::cout);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
inline ostream& error_stream()
|
||||
{
|
||||
static ostream x(std::clog);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ostream& outerr()
|
||||
{
|
||||
return error_stream() << "Error: ";
|
||||
}
|
||||
ostream& outerr() { return error_stream() << "Error: "; }
|
||||
|
||||
ostream& outerr(fs::path const& file, std::ptrdiff_t line)
|
||||
{
|
||||
if (line >= 0)
|
||||
ostream& outerr(fs::path const& file, std::ptrdiff_t line)
|
||||
{
|
||||
if (ms_errors)
|
||||
return error_stream() << path_to_stream(file) << "(" << line << "): error: ";
|
||||
else
|
||||
return error_stream() << path_to_stream(file) << ":" << line << ": error: ";
|
||||
if (line >= 0) {
|
||||
if (ms_errors)
|
||||
return error_stream() << path_to_stream(file) << "(" << line
|
||||
<< "): error: ";
|
||||
else
|
||||
return error_stream() << path_to_stream(file) << ":" << line
|
||||
<< ": error: ";
|
||||
}
|
||||
else {
|
||||
return error_stream() << path_to_stream(file) << ": error: ";
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
ostream& outerr(file_ptr const& f, string_iterator pos)
|
||||
{
|
||||
return error_stream() << path_to_stream(file) << ": error: ";
|
||||
return outerr(f->path, f->position_of(pos).line);
|
||||
}
|
||||
}
|
||||
|
||||
ostream& outerr(file_ptr const& f, string_iterator pos)
|
||||
{
|
||||
return outerr(f->path, f->position_of(pos).line);
|
||||
}
|
||||
|
||||
ostream& outwarn(fs::path const& file, std::ptrdiff_t line)
|
||||
{
|
||||
if (line >= 0)
|
||||
ostream& outwarn(fs::path const& file, std::ptrdiff_t line)
|
||||
{
|
||||
if (ms_errors)
|
||||
return error_stream() << path_to_stream(file) << "(" << line << "): warning: ";
|
||||
else
|
||||
return error_stream() << path_to_stream(file) << ":" << line << ": warning: ";
|
||||
if (line >= 0) {
|
||||
if (ms_errors)
|
||||
return error_stream() << path_to_stream(file) << "(" << line
|
||||
<< "): warning: ";
|
||||
else
|
||||
return error_stream() << path_to_stream(file) << ":" << line
|
||||
<< ": warning: ";
|
||||
}
|
||||
else {
|
||||
return error_stream() << path_to_stream(file) << ": warning: ";
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
ostream& outwarn(file_ptr const& f, string_iterator pos)
|
||||
{
|
||||
return error_stream() << path_to_stream(file) << ": warning: ";
|
||||
return outwarn(f->path, f->position_of(pos).line);
|
||||
}
|
||||
}
|
||||
|
||||
ostream& outwarn(file_ptr const& f, string_iterator pos)
|
||||
{
|
||||
return outwarn(f->path, f->position_of(pos).line);
|
||||
}
|
||||
ostream& ostream::operator<<(char c)
|
||||
{
|
||||
assert(c && !(c & 0x80));
|
||||
base << c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(char c) {
|
||||
assert(c && !(c & 0x80));
|
||||
base << c;
|
||||
return *this;
|
||||
}
|
||||
inline bool check_ascii(char const* x)
|
||||
{
|
||||
for (; *x; ++x)
|
||||
if (*x & 0x80) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool check_ascii(char const* x) {
|
||||
for(;*x;++x) if(*x & 0x80) return false;
|
||||
return true;
|
||||
}
|
||||
ostream& ostream::operator<<(char const* x)
|
||||
{
|
||||
assert(check_ascii(x));
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(char const* x) {
|
||||
assert(check_ascii(x));
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(std::string const& x)
|
||||
{
|
||||
write_utf8(base, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(std::string const& x) {
|
||||
write_utf8(base, x);
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(quickbook::string_view x)
|
||||
{
|
||||
write_utf8(base, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(quickbook::string_view x) {
|
||||
write_utf8(base, x);
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(int x)
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(int x) {
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(unsigned int x)
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(unsigned int x) {
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(long x)
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(long x) {
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(unsigned long x) {
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(unsigned long x)
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
ostream& ostream::operator<<(boost::long_long_type x) {
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(boost::long_long_type x)
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(boost::ulong_long_type x) {
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(boost::ulong_long_type x)
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
ostream& ostream::operator<<(fs::path const& x) {
|
||||
base << path_to_stream(x);
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(fs::path const& x)
|
||||
{
|
||||
base << path_to_stream(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(base_ostream& (*x)(base_ostream&)) {
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
ostream& ostream::operator<<(base_ostream& (*x)(base_ostream&))
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(base_ios& (*x)(base_ios&)) {
|
||||
base << x;
|
||||
return *this;
|
||||
ostream& ostream::operator<<(base_ios& (*x)(base_ios&))
|
||||
{
|
||||
base << x;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#if !defined(BOOST_QUICKBOOK_DETAIL_STREAM_HPP)
|
||||
#define BOOST_QUICKBOOK_DETAIL_STREAM_HPP
|
||||
|
||||
#include "native_text.hpp"
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <iostream>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "native_text.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
namespace quickbook {
|
||||
namespace quickbook
|
||||
{
|
||||
// boost::string_view now can't be constructed from an rvalue std::string,
|
||||
// which is something that quickbook does in several places, so this wraps
|
||||
// it to allow that.
|
||||
|
||||
struct string_view : boost::string_view {
|
||||
struct string_view : boost::string_view
|
||||
{
|
||||
typedef boost::string_view base;
|
||||
|
||||
string_view() : base() {}
|
||||
|
||||
147
src/symbols.hpp
147
src/symbols.hpp
@@ -12,58 +12,58 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/spirit/home/classic/symbols.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/spirit/home/classic/symbols.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace quickbook
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// tst class
|
||||
//
|
||||
// This it the Ternary Search Tree from
|
||||
// <boost/spirit/home/classic/symbols/impl/tst.ipp> adapted to be cheap
|
||||
// to copy.
|
||||
//
|
||||
// Ternary Search Tree implementation. The data structure is faster than
|
||||
// hashing for many typical search problems especially when the search
|
||||
// interface is iterator based. Searching for a string of length k in a
|
||||
// ternary search tree with n strings will require at most O(log n+k)
|
||||
// character comparisons. TSTs are many times faster than hash tables
|
||||
// for unsuccessful searches since mismatches are discovered earlier
|
||||
// after examining only a few characters. Hash tables always examine an
|
||||
// entire key when searching.
|
||||
//
|
||||
// For details see http://www.cs.princeton.edu/~rs/strings/.
|
||||
//
|
||||
// *** This is a low level class and is
|
||||
// not meant for public consumption ***
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// tst class
|
||||
//
|
||||
// This it the Ternary Search Tree from
|
||||
// <boost/spirit/home/classic/symbols/impl/tst.ipp> adapted to be cheap
|
||||
// to copy.
|
||||
//
|
||||
// Ternary Search Tree implementation. The data structure is faster
|
||||
// than
|
||||
// hashing for many typical search problems especially when the search
|
||||
// interface is iterator based. Searching for a string of length k in a
|
||||
// ternary search tree with n strings will require at most O(log n+k)
|
||||
// character comparisons. TSTs are many times faster than hash tables
|
||||
// for unsuccessful searches since mismatches are discovered earlier
|
||||
// after examining only a few characters. Hash tables always examine an
|
||||
// entire key when searching.
|
||||
//
|
||||
// For details see http://www.cs.princeton.edu/~rs/strings/.
|
||||
//
|
||||
// *** This is a low level class and is
|
||||
// not meant for public consumption ***
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, typename CharT>
|
||||
struct tst_node
|
||||
template <typename T, typename CharT> struct tst_node
|
||||
{
|
||||
tst_node(CharT value_)
|
||||
: reference_count(0)
|
||||
, left()
|
||||
, middle()
|
||||
, right()
|
||||
, data()
|
||||
, value(value_)
|
||||
: reference_count(0)
|
||||
, left()
|
||||
, middle()
|
||||
, right()
|
||||
, data()
|
||||
, value(value_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
tst_node(tst_node const& other)
|
||||
: reference_count(0)
|
||||
, left(other.left)
|
||||
, middle(other.middle)
|
||||
, right(other.right)
|
||||
, data(other.data ? new T(*other.data) : 0)
|
||||
, value(other.value)
|
||||
: reference_count(0)
|
||||
, left(other.left)
|
||||
, middle(other.middle)
|
||||
, right(other.right)
|
||||
, data(other.data ? new T(*other.data) : 0)
|
||||
, value(other.value)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -76,39 +76,38 @@ namespace quickbook
|
||||
boost::intrusive_ptr<tst_node> right;
|
||||
boost::scoped_ptr<T> data;
|
||||
CharT value;
|
||||
private:
|
||||
|
||||
private:
|
||||
tst_node& operator=(tst_node const&);
|
||||
};
|
||||
|
||||
template <typename T, typename CharT>
|
||||
void intrusive_ptr_add_ref(tst_node<T, CharT>* ptr)
|
||||
{ ++ptr->reference_count; }
|
||||
{
|
||||
++ptr->reference_count;
|
||||
}
|
||||
|
||||
template <typename T, typename CharT>
|
||||
void intrusive_ptr_release(tst_node<T, CharT>* ptr)
|
||||
{ if(--ptr->reference_count == 0) delete ptr; }
|
||||
|
||||
{
|
||||
if (--ptr->reference_count == 0) delete ptr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename CharT>
|
||||
class tst
|
||||
template <typename T, typename CharT> class tst
|
||||
{
|
||||
typedef tst_node<T, CharT> node_t;
|
||||
typedef boost::intrusive_ptr<node_t> node_ptr;
|
||||
node_ptr root;
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
struct search_info
|
||||
{
|
||||
T* data;
|
||||
T* data;
|
||||
std::size_t length;
|
||||
};
|
||||
|
||||
void swap(tst& other)
|
||||
{
|
||||
root.swap(other.root);
|
||||
}
|
||||
void swap(tst& other) { root.swap(other.root); }
|
||||
|
||||
// Adds symbol to ternary search tree.
|
||||
// If it already exists, then replace it with new value.
|
||||
@@ -117,35 +116,29 @@ namespace quickbook
|
||||
template <typename IteratorT>
|
||||
T* add(IteratorT first, IteratorT const& last, T const& data)
|
||||
{
|
||||
assert (first != last);
|
||||
assert(first != last);
|
||||
|
||||
node_ptr* np = &root;
|
||||
CharT ch = *first;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (!*np)
|
||||
{
|
||||
for (;;) {
|
||||
if (!*np) {
|
||||
*np = new node_t(ch);
|
||||
}
|
||||
else if ((*np)->reference_count > 1)
|
||||
{
|
||||
else if ((*np)->reference_count > 1) {
|
||||
*np = new node_t(**np);
|
||||
}
|
||||
|
||||
if (ch < (*np)->value)
|
||||
{
|
||||
if (ch < (*np)->value) {
|
||||
np = &(*np)->left;
|
||||
}
|
||||
else if (ch == (*np)->value)
|
||||
{
|
||||
else if (ch == (*np)->value) {
|
||||
++first;
|
||||
if (first == last) break;
|
||||
ch = *first;
|
||||
np = &(*np)->middle;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
np = &(*np)->right;
|
||||
}
|
||||
}
|
||||
@@ -154,23 +147,22 @@ namespace quickbook
|
||||
boost::swap((*np)->data, new_data);
|
||||
return (*np)->data.get();
|
||||
}
|
||||
|
||||
|
||||
template <typename ScannerT>
|
||||
search_info find(ScannerT const& scan) const
|
||||
{
|
||||
search_info result = { 0, 0 };
|
||||
search_info result = {0, 0};
|
||||
if (scan.at_end()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef typename ScannerT::iterator_t iterator_t;
|
||||
node_ptr np = root;
|
||||
CharT ch = *scan;
|
||||
iterator_t latest = scan.first;
|
||||
node_ptr np = root;
|
||||
CharT ch = *scan;
|
||||
iterator_t latest = scan.first;
|
||||
std::size_t length = 0;
|
||||
|
||||
while (np)
|
||||
{
|
||||
while (np) {
|
||||
if (ch < np->value) // => go left!
|
||||
{
|
||||
np = np->left;
|
||||
@@ -181,8 +173,7 @@ namespace quickbook
|
||||
++length;
|
||||
|
||||
// Found a potential match.
|
||||
if (np->data.get())
|
||||
{
|
||||
if (np->data.get()) {
|
||||
result.data = np->data.get();
|
||||
result.length = length;
|
||||
latest = scan.first;
|
||||
@@ -203,11 +194,9 @@ namespace quickbook
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::spirit::classic::symbols<
|
||||
std::string,
|
||||
char,
|
||||
quickbook::tst<std::string, char>
|
||||
> string_symbols;
|
||||
typedef boost::spirit::classic::
|
||||
symbols<std::string, char, quickbook::tst<std::string, char> >
|
||||
string_symbols;
|
||||
} // namespace quickbook
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,22 +7,22 @@
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_confix.hpp>
|
||||
#include <boost/spirit/include/classic_chset.hpp>
|
||||
#include <boost/spirit/include/classic_symbols.hpp>
|
||||
#include <boost/spirit/include/classic_loops.hpp>
|
||||
#include "grammar.hpp"
|
||||
#include "state.hpp"
|
||||
#include "actions.hpp"
|
||||
#include "syntax_highlight.hpp"
|
||||
#include "utils.hpp"
|
||||
#include <boost/spirit/include/classic_chset.hpp>
|
||||
#include <boost/spirit/include/classic_confix.hpp>
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_loops.hpp>
|
||||
#include <boost/spirit/include/classic_symbols.hpp>
|
||||
#include "actions.hpp"
|
||||
#include "files.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "grammar.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "state.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
{
|
||||
namespace cl = boost::spirit::classic;
|
||||
|
||||
// Syntax Highlight Actions
|
||||
@@ -36,13 +36,15 @@ namespace quickbook
|
||||
bool support_callouts;
|
||||
quickbook::string_view marked_text;
|
||||
|
||||
syntax_highlight_actions(quickbook::state& state_, bool is_block_) :
|
||||
state(state_),
|
||||
do_macro_impl(state_),
|
||||
support_callouts(is_block_ && (qbk_version_n >= 107u ||
|
||||
state.current_file->is_code_snippets)),
|
||||
marked_text()
|
||||
{}
|
||||
syntax_highlight_actions(quickbook::state& state_, bool is_block_)
|
||||
: state(state_)
|
||||
, do_macro_impl(state_)
|
||||
, support_callouts(
|
||||
is_block_ && (qbk_version_n >= 107u ||
|
||||
state.current_file->is_code_snippets))
|
||||
, marked_text()
|
||||
{
|
||||
}
|
||||
|
||||
void span(parse_iterator, parse_iterator, char const*);
|
||||
void span_start(parse_iterator, parse_iterator, char const*);
|
||||
@@ -57,8 +59,8 @@ namespace quickbook
|
||||
void callout(parse_iterator, parse_iterator);
|
||||
};
|
||||
|
||||
void syntax_highlight_actions::span(parse_iterator first,
|
||||
parse_iterator last, char const* name)
|
||||
void syntax_highlight_actions::span(
|
||||
parse_iterator first, parse_iterator last, char const* name)
|
||||
{
|
||||
state.phrase << "<phrase role=\"" << name << "\">";
|
||||
while (first != last)
|
||||
@@ -66,31 +68,30 @@ namespace quickbook
|
||||
state.phrase << "</phrase>";
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::span_start(parse_iterator first,
|
||||
parse_iterator last, char const* name)
|
||||
void syntax_highlight_actions::span_start(
|
||||
parse_iterator first, parse_iterator last, char const* name)
|
||||
{
|
||||
state.phrase << "<phrase role=\"" << name << "\">";
|
||||
while (first != last)
|
||||
detail::print_char(*first++, state.phrase.get());
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::span_end(parse_iterator first,
|
||||
parse_iterator last)
|
||||
void syntax_highlight_actions::span_end(
|
||||
parse_iterator first, parse_iterator last)
|
||||
{
|
||||
while (first != last)
|
||||
detail::print_char(*first++, state.phrase.get());
|
||||
state.phrase << "</phrase>";
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::unexpected_char(parse_iterator first,
|
||||
parse_iterator last)
|
||||
void syntax_highlight_actions::unexpected_char(
|
||||
parse_iterator first, parse_iterator last)
|
||||
{
|
||||
file_position const pos = state.current_file->position_of(first.base());
|
||||
|
||||
detail::outwarn(state.current_file->path, pos.line)
|
||||
<< "in column:" << pos.column
|
||||
<< ", unexpected character: " << std::string(first.base(), last.base())
|
||||
<< "\n";
|
||||
<< "in column:" << pos.column << ", unexpected character: "
|
||||
<< std::string(first.base(), last.base()) << "\n";
|
||||
|
||||
// print out an unexpected character
|
||||
state.phrase << "<phrase role=\"error\">";
|
||||
@@ -99,21 +100,21 @@ namespace quickbook
|
||||
state.phrase << "</phrase>";
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::plain_char(parse_iterator first,
|
||||
parse_iterator last)
|
||||
void syntax_highlight_actions::plain_char(
|
||||
parse_iterator first, parse_iterator last)
|
||||
{
|
||||
while (first != last)
|
||||
detail::print_char(*first++, state.phrase.get());
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::pre_escape_back(parse_iterator,
|
||||
parse_iterator)
|
||||
void syntax_highlight_actions::pre_escape_back(
|
||||
parse_iterator, parse_iterator)
|
||||
{
|
||||
state.push_output(); // save the stream
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::post_escape_back(parse_iterator,
|
||||
parse_iterator)
|
||||
void syntax_highlight_actions::post_escape_back(
|
||||
parse_iterator, parse_iterator)
|
||||
{
|
||||
std::string tmp;
|
||||
state.phrase.swap(tmp);
|
||||
@@ -126,16 +127,17 @@ namespace quickbook
|
||||
do_macro_impl(v);
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::mark_text(parse_iterator first,
|
||||
parse_iterator last)
|
||||
void syntax_highlight_actions::mark_text(
|
||||
parse_iterator first, parse_iterator last)
|
||||
{
|
||||
marked_text = quickbook::string_view(first.base(), last.base() - first.base());
|
||||
marked_text =
|
||||
quickbook::string_view(first.base(), last.base() - first.base());
|
||||
}
|
||||
|
||||
void syntax_highlight_actions::callout(parse_iterator, parse_iterator)
|
||||
{
|
||||
state.phrase << state.add_callout(qbk_value(state.current_file,
|
||||
marked_text.begin(), marked_text.end()));
|
||||
state.phrase << state.add_callout(qbk_value(
|
||||
state.current_file, marked_text.begin(), marked_text.end()));
|
||||
marked_text.clear();
|
||||
}
|
||||
|
||||
@@ -189,7 +191,8 @@ namespace quickbook
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
keywords_holder keywords;
|
||||
}
|
||||
|
||||
@@ -197,10 +200,11 @@ namespace quickbook
|
||||
struct cpp_highlight : public cl::grammar<cpp_highlight>
|
||||
{
|
||||
explicit cpp_highlight(syntax_highlight_actions& actions_)
|
||||
: actions(actions_) {}
|
||||
: actions(actions_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Scanner>
|
||||
struct definition
|
||||
template <typename Scanner> struct definition
|
||||
{
|
||||
definition(cpp_highlight const& self)
|
||||
: g(self.actions.state.grammar())
|
||||
@@ -349,17 +353,14 @@ namespace quickbook
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
cl::rule<Scanner>
|
||||
program, line_start, rest_of_line, macro, preprocessor,
|
||||
inline_callout, line_callout, comment,
|
||||
special, string_,
|
||||
char_, number, identifier, keyword, escape,
|
||||
string_char;
|
||||
cl::rule<Scanner> program, line_start, rest_of_line, macro,
|
||||
preprocessor, inline_callout, line_callout, comment, special,
|
||||
string_, char_, number, identifier, keyword, escape,
|
||||
string_char;
|
||||
|
||||
quickbook_grammar& g;
|
||||
|
||||
cl::rule<Scanner> const&
|
||||
start() const { return program; }
|
||||
cl::rule<Scanner> const& start() const { return program; }
|
||||
};
|
||||
|
||||
syntax_highlight_actions& actions;
|
||||
@@ -371,10 +372,11 @@ namespace quickbook
|
||||
struct python_highlight : public cl::grammar<python_highlight>
|
||||
{
|
||||
explicit python_highlight(syntax_highlight_actions& actions_)
|
||||
: actions(actions_) {}
|
||||
: actions(actions_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Scanner>
|
||||
struct definition
|
||||
template <typename Scanner> struct definition
|
||||
{
|
||||
definition(python_highlight const& self)
|
||||
: g(self.actions.state.grammar())
|
||||
@@ -510,16 +512,13 @@ namespace quickbook
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
cl::rule<Scanner>
|
||||
program, macro, inline_callout, line_callout,
|
||||
comment, special, string_, string_prefix,
|
||||
short_string, long_string, number, identifier, keyword,
|
||||
escape, string_char;
|
||||
cl::rule<Scanner> program, macro, inline_callout, line_callout,
|
||||
comment, special, string_, string_prefix, short_string,
|
||||
long_string, number, identifier, keyword, escape, string_char;
|
||||
|
||||
quickbook_grammar& g;
|
||||
|
||||
cl::rule<Scanner> const&
|
||||
start() const { return program; }
|
||||
cl::rule<Scanner> const& start() const { return program; }
|
||||
};
|
||||
|
||||
syntax_highlight_actions& actions;
|
||||
@@ -529,19 +528,25 @@ namespace quickbook
|
||||
struct teletype_highlight : public cl::grammar<teletype_highlight>
|
||||
{
|
||||
teletype_highlight(syntax_highlight_actions& actions_)
|
||||
: actions(actions_) {}
|
||||
: actions(actions_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Scanner>
|
||||
struct definition
|
||||
template <typename Scanner> struct definition
|
||||
{
|
||||
definition(teletype_highlight const& self)
|
||||
: g(self.actions.state.grammar())
|
||||
{
|
||||
member_action<syntax_highlight_actions>
|
||||
plain_char(self.actions, &syntax_highlight_actions::plain_char),
|
||||
pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
|
||||
post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back);
|
||||
member_action_value<syntax_highlight_actions, std::string const&>
|
||||
member_action<syntax_highlight_actions> plain_char(
|
||||
self.actions, &syntax_highlight_actions::plain_char),
|
||||
pre_escape_back(
|
||||
self.actions,
|
||||
&syntax_highlight_actions::pre_escape_back),
|
||||
post_escape_back(
|
||||
self.actions,
|
||||
&syntax_highlight_actions::post_escape_back);
|
||||
member_action_value<
|
||||
syntax_highlight_actions, std::string const&>
|
||||
do_macro(self.actions, &syntax_highlight_actions::do_macro);
|
||||
error_action error(self.actions.state);
|
||||
|
||||
@@ -589,8 +594,7 @@ namespace quickbook
|
||||
|
||||
quickbook_grammar& g;
|
||||
|
||||
cl::rule<Scanner> const&
|
||||
start() const { return program; }
|
||||
cl::rule<Scanner> const& start() const { return program; }
|
||||
};
|
||||
|
||||
syntax_highlight_actions& actions;
|
||||
@@ -606,25 +610,24 @@ namespace quickbook
|
||||
syntax_highlight_actions syn_actions(state, is_block);
|
||||
|
||||
// print the code with syntax coloring
|
||||
switch(source_mode)
|
||||
{
|
||||
case source_mode_tags::cpp: {
|
||||
cpp_highlight cpp_p(syn_actions);
|
||||
boost::spirit::classic::parse(first, last, cpp_p);
|
||||
break;
|
||||
}
|
||||
case source_mode_tags::python: {
|
||||
python_highlight python_p(syn_actions);
|
||||
boost::spirit::classic::parse(first, last, python_p);
|
||||
break;
|
||||
}
|
||||
case source_mode_tags::teletype: {
|
||||
teletype_highlight teletype_p(syn_actions);
|
||||
boost::spirit::classic::parse(first, last, teletype_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
switch (source_mode) {
|
||||
case source_mode_tags::cpp: {
|
||||
cpp_highlight cpp_p(syn_actions);
|
||||
boost::spirit::classic::parse(first, last, cpp_p);
|
||||
break;
|
||||
}
|
||||
case source_mode_tags::python: {
|
||||
python_highlight python_p(syn_actions);
|
||||
boost::spirit::classic::parse(first, last, python_p);
|
||||
break;
|
||||
}
|
||||
case source_mode_tags::teletype: {
|
||||
teletype_highlight teletype_p(syn_actions);
|
||||
boost::spirit::classic::parse(first, last, teletype_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#if !defined(BOOST_QUICKBOOK_SYNTAX_HIGHLIGHT_HPP)
|
||||
#define BOOST_QUICKBOOK_SYNTAX_HIGHLIGHT_HPP
|
||||
|
||||
#include "fwd.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
#include "iterator.hpp"
|
||||
#include <boost/swap.hpp>
|
||||
#include "fwd.hpp"
|
||||
#include "iterator.hpp"
|
||||
#include "phrase_tags.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -22,35 +22,38 @@ namespace quickbook
|
||||
// The source mode is stored in a few places, so the order needs to also be
|
||||
// stored to work out which is the current source mode.
|
||||
|
||||
struct source_mode_info {
|
||||
struct source_mode_info
|
||||
{
|
||||
source_mode_type source_mode;
|
||||
unsigned order;
|
||||
|
||||
source_mode_info() : source_mode(source_mode_tags::cpp), order(0) {}
|
||||
|
||||
source_mode_info(source_mode_type source_mode_, unsigned order_) :
|
||||
source_mode(source_mode_),
|
||||
order(order_) {}
|
||||
source_mode_info(source_mode_type source_mode_, unsigned order_)
|
||||
: source_mode(source_mode_), order(order_)
|
||||
{
|
||||
}
|
||||
|
||||
void update(source_mode_info const& x) {
|
||||
void update(source_mode_info const& x)
|
||||
{
|
||||
if (x.order > order) {
|
||||
source_mode = x.source_mode;
|
||||
order = x.order;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(source_mode_info& x) {
|
||||
void swap(source_mode_info& x)
|
||||
{
|
||||
boost::swap(source_mode, x.source_mode);
|
||||
boost::swap(order, x.order);
|
||||
}
|
||||
};
|
||||
|
||||
inline void swap(source_mode_info& x, source_mode_info& y) {
|
||||
x.swap(y);
|
||||
}
|
||||
inline void swap(source_mode_info& x, source_mode_info& y) { x.swap(y); }
|
||||
|
||||
void syntax_highlight(
|
||||
parse_iterator first, parse_iterator last,
|
||||
parse_iterator first,
|
||||
parse_iterator last,
|
||||
quickbook::state& state,
|
||||
source_mode_type source_mode,
|
||||
bool is_block);
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include <cassert>
|
||||
#include "template_stack.hpp"
|
||||
#include <cassert>
|
||||
#include "files.hpp"
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
@@ -18,42 +18,44 @@
|
||||
namespace quickbook
|
||||
{
|
||||
template_symbol::template_symbol(
|
||||
std::string const& identifier_,
|
||||
std::vector<std::string> const& params_,
|
||||
value const& content_,
|
||||
template_scope const* lexical_parent_)
|
||||
: identifier(identifier_)
|
||||
, params(params_)
|
||||
, content(content_)
|
||||
, lexical_parent(lexical_parent_)
|
||||
std::string const& identifier_,
|
||||
std::vector<std::string> const& params_,
|
||||
value const& content_,
|
||||
template_scope const* lexical_parent_)
|
||||
: identifier(identifier_)
|
||||
, params(params_)
|
||||
, content(content_)
|
||||
, lexical_parent(lexical_parent_)
|
||||
{
|
||||
assert(content.get_tag() == template_tags::block ||
|
||||
assert(
|
||||
content.get_tag() == template_tags::block ||
|
||||
content.get_tag() == template_tags::phrase ||
|
||||
content.get_tag() == template_tags::snippet);
|
||||
}
|
||||
|
||||
template_stack::template_stack()
|
||||
: scope(template_stack::parser(*this))
|
||||
, scopes()
|
||||
, parent_1_4(0)
|
||||
: scope(template_stack::parser(*this)), scopes(), parent_1_4(0)
|
||||
{
|
||||
scopes.push_front(template_scope());
|
||||
parent_1_4 = &scopes.front();
|
||||
}
|
||||
|
||||
|
||||
template_symbol* template_stack::find(std::string const& symbol) const
|
||||
{
|
||||
for (template_scope const* i = &*scopes.begin(); i; i = i->parent_scope)
|
||||
{
|
||||
if (template_symbol* ts = boost::spirit::classic::find(i->symbols, symbol.c_str()))
|
||||
for (template_scope const* i = &*scopes.begin(); i;
|
||||
i = i->parent_scope) {
|
||||
if (template_symbol* ts =
|
||||
boost::spirit::classic::find(i->symbols, symbol.c_str()))
|
||||
return ts;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template_symbol* template_stack::find_top_scope(std::string const& symbol) const
|
||||
template_symbol* template_stack::find_top_scope(
|
||||
std::string const& symbol) const
|
||||
{
|
||||
return boost::spirit::classic::find(scopes.front().symbols, symbol.c_str());
|
||||
return boost::spirit::classic::find(
|
||||
scopes.front().symbols, symbol.c_str());
|
||||
}
|
||||
|
||||
template_symbols const& template_stack::top() const
|
||||
@@ -67,22 +69,22 @@ namespace quickbook
|
||||
BOOST_ASSERT(!scopes.empty());
|
||||
return scopes.front();
|
||||
}
|
||||
|
||||
|
||||
bool template_stack::add(template_symbol const& ts)
|
||||
{
|
||||
BOOST_ASSERT(!scopes.empty());
|
||||
BOOST_ASSERT(ts.lexical_parent);
|
||||
|
||||
|
||||
if (this->find_top_scope(ts.identifier)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::spirit::classic::add(scopes.front().symbols,
|
||||
ts.identifier.c_str(), ts);
|
||||
|
||||
boost::spirit::classic::add(
|
||||
scopes.front().symbols, ts.identifier.c_str(), ts);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void template_stack::push()
|
||||
{
|
||||
template_scope const& old_front = scopes.front();
|
||||
@@ -104,16 +106,12 @@ namespace quickbook
|
||||
// current scope (the dynamic scope).
|
||||
// Quickbook 1.5+: Use the scope the template was defined in
|
||||
// (the static scope).
|
||||
if (symbol->content.get_file()->version() >= 105u)
|
||||
{
|
||||
if (symbol->content.get_file()->version() >= 105u) {
|
||||
parent_1_4 = scopes.front().parent_1_4;
|
||||
scopes.front().parent_scope = symbol->lexical_parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
scopes.front().parent_scope = scopes.front().parent_1_4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,19 +9,19 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/spirit/include/classic_functor_parser.hpp>
|
||||
#include <boost/spirit/include/classic_symbols.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include "fwd.hpp"
|
||||
#include "values.hpp"
|
||||
#include "template_tags.hpp"
|
||||
#include "values.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -32,10 +32,10 @@ namespace quickbook
|
||||
struct template_symbol
|
||||
{
|
||||
template_symbol(
|
||||
std::string const& identifier,
|
||||
std::vector<std::string> const& params,
|
||||
value const& content,
|
||||
template_scope const* parent = 0);
|
||||
std::string const& identifier,
|
||||
std::vector<std::string> const& params,
|
||||
value const& content,
|
||||
template_scope const* parent = 0);
|
||||
|
||||
std::string identifier;
|
||||
std::vector<std::string> params;
|
||||
@@ -45,7 +45,7 @@ namespace quickbook
|
||||
};
|
||||
|
||||
typedef boost::spirit::classic::symbols<template_symbol> template_symbols;
|
||||
|
||||
|
||||
// template scope
|
||||
//
|
||||
// 1.4-: parent_scope is the previous scope on the dynamic
|
||||
@@ -57,7 +57,7 @@ namespace quickbook
|
||||
// correct lookup chain for that version of quickboook.
|
||||
//
|
||||
// symbols contains the templates defined in this scope.
|
||||
|
||||
|
||||
struct template_scope
|
||||
{
|
||||
template_scope() : parent_scope(), parent_1_4() {}
|
||||
@@ -74,31 +74,27 @@ namespace quickbook
|
||||
{
|
||||
typedef boost::spirit::classic::nil_t result_t;
|
||||
|
||||
parser(template_stack& ts_)
|
||||
: ts(ts_) {}
|
||||
parser(template_stack& ts_) : ts(ts_) {}
|
||||
|
||||
template <typename Scanner>
|
||||
std::ptrdiff_t
|
||||
operator()(Scanner const& scan, result_t) const
|
||||
std::ptrdiff_t operator()(Scanner const& scan, result_t) const
|
||||
{
|
||||
// search all scopes for the longest matching symbol.
|
||||
typename Scanner::iterator_t f = scan.first;
|
||||
std::ptrdiff_t len = -1;
|
||||
for (template_scope const* i = &*ts.scopes.begin(); i; i = i->parent_scope)
|
||||
{
|
||||
for (template_scope const* i = &*ts.scopes.begin(); i;
|
||||
i = i->parent_scope) {
|
||||
boost::spirit::classic::match<> m = i->symbols.parse(scan);
|
||||
if (m.length() > len)
|
||||
len = m.length();
|
||||
if (m.length() > len) len = m.length();
|
||||
scan.first = f;
|
||||
}
|
||||
if (len >= 0)
|
||||
scan.first = boost::next(f, len);
|
||||
if (len >= 0) scan.first = boost::next(f, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
template_stack& ts;
|
||||
|
||||
private:
|
||||
private:
|
||||
parser& operator=(parser const&);
|
||||
};
|
||||
|
||||
@@ -108,7 +104,8 @@ namespace quickbook
|
||||
template_symbols const& top() const;
|
||||
template_scope const& top_scope() const;
|
||||
// Add the given template symbol to the current scope.
|
||||
// If it doesn't have a scope, sets the symbol's scope to the current scope.
|
||||
// If it doesn't have a scope, sets the symbol's scope to the current
|
||||
// scope.
|
||||
bool add(template_symbol const&);
|
||||
void push();
|
||||
void pop();
|
||||
@@ -117,8 +114,7 @@ namespace quickbook
|
||||
|
||||
boost::spirit::classic::functor_parser<parser> scope;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
friend struct parser;
|
||||
deque scopes;
|
||||
template_scope const* parent_1_4;
|
||||
@@ -128,4 +124,3 @@ namespace quickbook
|
||||
}
|
||||
|
||||
#endif // BOOST_SPIRIT_QUICKBOOK_TEMPLATE_STACK_HPP
|
||||
|
||||
|
||||
184
src/utils.cpp
184
src/utils.cpp
@@ -13,104 +13,122 @@
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
|
||||
namespace quickbook { namespace detail
|
||||
namespace quickbook
|
||||
{
|
||||
std::string encode_string(quickbook::string_view str)
|
||||
namespace detail
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(str.size());
|
||||
|
||||
for (string_iterator it = str.begin();
|
||||
it != str.end(); ++it)
|
||||
std::string encode_string(quickbook::string_view str)
|
||||
{
|
||||
switch (*it)
|
||||
{
|
||||
case '<': result += "<"; break;
|
||||
case '>': result += ">"; break;
|
||||
case '&': result += "&"; break;
|
||||
case '"': result += """; break;
|
||||
default: result += *it; break;
|
||||
std::string result;
|
||||
result.reserve(str.size());
|
||||
|
||||
for (string_iterator it = str.begin(); it != str.end(); ++it) {
|
||||
switch (*it) {
|
||||
case '<':
|
||||
result += "<";
|
||||
break;
|
||||
case '>':
|
||||
result += ">";
|
||||
break;
|
||||
case '&':
|
||||
result += "&";
|
||||
break;
|
||||
case '"':
|
||||
result += """;
|
||||
break;
|
||||
default:
|
||||
result += *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void print_char(char ch, std::ostream& out)
|
||||
{
|
||||
switch (ch) {
|
||||
case '<':
|
||||
out << "<";
|
||||
break;
|
||||
case '>':
|
||||
out << ">";
|
||||
break;
|
||||
case '&':
|
||||
out << "&";
|
||||
break;
|
||||
case '"':
|
||||
out << """;
|
||||
break;
|
||||
default:
|
||||
out << ch;
|
||||
break;
|
||||
// note ' is not included. see the curse of apos:
|
||||
// http://fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void print_char(char ch, std::ostream& out)
|
||||
{
|
||||
switch (ch)
|
||||
void print_string(quickbook::string_view str, std::ostream& out)
|
||||
{
|
||||
case '<': out << "<"; break;
|
||||
case '>': out << ">"; break;
|
||||
case '&': out << "&"; break;
|
||||
case '"': out << """; break;
|
||||
default: out << ch; break;
|
||||
// note ' is not included. see the curse of apos:
|
||||
// http://fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
|
||||
}
|
||||
}
|
||||
|
||||
void print_string(quickbook::string_view str, std::ostream& out)
|
||||
{
|
||||
for (string_iterator cur = str.begin();
|
||||
cur != str.end(); ++cur)
|
||||
{
|
||||
print_char(*cur, out);
|
||||
}
|
||||
}
|
||||
|
||||
std::string make_identifier(quickbook::string_view text)
|
||||
{
|
||||
std::string id(text.begin(), text.end());
|
||||
for (std::string::iterator i = id.begin(); i != id.end(); ++i) {
|
||||
if (!std::isalnum(static_cast<unsigned char>(*i))) {
|
||||
*i = '_';
|
||||
}
|
||||
else {
|
||||
*i = static_cast<char>(std::tolower(static_cast<unsigned char>(*i)));
|
||||
for (string_iterator cur = str.begin(); cur != str.end(); ++cur) {
|
||||
print_char(*cur, out);
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static std::string escape_uri_impl(quickbook::string_view uri_param, char const* mark)
|
||||
{
|
||||
// Extra capital characters for validating percent escapes.
|
||||
static char const hex[] = "0123456789abcdefABCDEF";
|
||||
|
||||
std::string uri;
|
||||
uri.reserve(uri_param.size());
|
||||
|
||||
for (std::string::size_type n = 0; n < uri_param.size(); ++n)
|
||||
std::string make_identifier(quickbook::string_view text)
|
||||
{
|
||||
if (static_cast<unsigned char>(uri_param[n]) > 127 ||
|
||||
std::string id(text.begin(), text.end());
|
||||
for (std::string::iterator i = id.begin(); i != id.end(); ++i) {
|
||||
if (!std::isalnum(static_cast<unsigned char>(*i))) {
|
||||
*i = '_';
|
||||
}
|
||||
else {
|
||||
*i = static_cast<char>(
|
||||
std::tolower(static_cast<unsigned char>(*i)));
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static std::string escape_uri_impl(
|
||||
quickbook::string_view uri_param, char const* mark)
|
||||
{
|
||||
// Extra capital characters for validating percent escapes.
|
||||
static char const hex[] = "0123456789abcdefABCDEF";
|
||||
|
||||
std::string uri;
|
||||
uri.reserve(uri_param.size());
|
||||
|
||||
for (std::string::size_type n = 0; n < uri_param.size(); ++n) {
|
||||
if (static_cast<unsigned char>(uri_param[n]) > 127 ||
|
||||
(!std::isalnum(static_cast<unsigned char>(uri_param[n])) &&
|
||||
!std::strchr(mark, uri_param[n])) ||
|
||||
(uri_param[n] == '%' && !(n + 2 < uri_param.size() &&
|
||||
std::strchr(hex, uri_param[n+1]) &&
|
||||
std::strchr(hex, uri_param[n+2]))))
|
||||
{
|
||||
char escape[] = { '%', hex[uri_param[n] / 16], hex[uri_param[n] % 16], '\0' };
|
||||
uri += escape;
|
||||
}
|
||||
else
|
||||
{
|
||||
uri += uri_param[n];
|
||||
(uri_param[n] == '%' &&
|
||||
!(n + 2 < uri_param.size() &&
|
||||
std::strchr(hex, uri_param[n + 1]) &&
|
||||
std::strchr(hex, uri_param[n + 2])))) {
|
||||
char escape[] = {'%', hex[uri_param[n] / 16],
|
||||
hex[uri_param[n] % 16], '\0'};
|
||||
uri += escape;
|
||||
}
|
||||
else {
|
||||
uri += uri_param[n];
|
||||
}
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
std::string escape_uri(quickbook::string_view uri_param)
|
||||
{
|
||||
std::string uri(uri_param.begin(), uri_param.end());
|
||||
return escape_uri_impl(uri_param, "-_.!~*'()?\\/");
|
||||
}
|
||||
|
||||
std::string escape_uri(quickbook::string_view uri_param)
|
||||
{
|
||||
std::string uri(uri_param.begin(), uri_param.end());
|
||||
return escape_uri_impl(uri_param, "-_.!~*'()?\\/");
|
||||
std::string partially_escape_uri(quickbook::string_view uri_param)
|
||||
{
|
||||
return escape_uri_impl(uri_param, "-_.!~*'()?\\/:&=#%+");
|
||||
}
|
||||
}
|
||||
|
||||
std::string partially_escape_uri(quickbook::string_view uri_param)
|
||||
{
|
||||
return escape_uri_impl(uri_param, "-_.!~*'()?\\/:&=#%+");
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -10,25 +10,29 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_UTILS_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include "string_view.hpp"
|
||||
|
||||
namespace quickbook { namespace detail {
|
||||
std::string encode_string(quickbook::string_view);
|
||||
void print_char(char ch, std::ostream& out);
|
||||
void print_string(quickbook::string_view str, std::ostream& out);
|
||||
std::string make_identifier(quickbook::string_view);
|
||||
namespace quickbook
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
std::string encode_string(quickbook::string_view);
|
||||
void print_char(char ch, std::ostream& out);
|
||||
void print_string(quickbook::string_view str, std::ostream& out);
|
||||
std::string make_identifier(quickbook::string_view);
|
||||
|
||||
// URI escape string
|
||||
std::string escape_uri(quickbook::string_view);
|
||||
// URI escape string
|
||||
std::string escape_uri(quickbook::string_view);
|
||||
|
||||
// URI escape string, leaving characters generally used in URIs.
|
||||
std::string partially_escape_uri(quickbook::string_view);
|
||||
// URI escape string, leaving characters generally used in URIs.
|
||||
std::string partially_escape_uri(quickbook::string_view);
|
||||
|
||||
// Defined in id_xml.cpp. Just because.
|
||||
std::string linkify(quickbook::string_view source, quickbook::string_view linkend);
|
||||
}}
|
||||
// Defined in id_xml.cpp. Just because.
|
||||
std::string linkify(
|
||||
quickbook::string_view source, quickbook::string_view linkend);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_SPIRIT_QUICKBOOK_UTILS_HPP
|
||||
|
||||
|
||||
@@ -9,71 +9,82 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_VALUES_TAGS_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_VALUES_TAGS_HPP
|
||||
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <cassert>
|
||||
#include <boost/preprocessor/seq/elem.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <boost/preprocessor/seq/elem.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <boost/range/irange.hpp>
|
||||
#include <cassert>
|
||||
|
||||
#define QUICKBOOK_VALUE_TAGS(tags_name, start_index, values) \
|
||||
struct tags_name { \
|
||||
enum tags_name##_enum { \
|
||||
previous_index = start_index - 1, \
|
||||
BOOST_PP_SEQ_ENUM(values), \
|
||||
end_index \
|
||||
}; \
|
||||
\
|
||||
static char const* name(int value) { \
|
||||
switch(value) {\
|
||||
case 0: \
|
||||
return "null"; \
|
||||
BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_CASE, _, values) \
|
||||
default: \
|
||||
assert(false); return ""; \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
typedef boost::integer_range<int> range_type; \
|
||||
static range_type tags() { return boost::irange(start_index, (int) end_index); } \
|
||||
static bool is_tag(int value) { \
|
||||
return value >= start_index && value < (int) end_index; \
|
||||
} \
|
||||
#define QUICKBOOK_VALUE_TAGS(tags_name, start_index, values) \
|
||||
struct tags_name \
|
||||
{ \
|
||||
enum tags_name##_enum{previous_index = start_index - 1, \
|
||||
BOOST_PP_SEQ_ENUM(values), end_index}; \
|
||||
\
|
||||
static char const* name(int value) \
|
||||
{ \
|
||||
switch (value) { \
|
||||
case 0: \
|
||||
return "null"; \
|
||||
BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_CASE, _, values) \
|
||||
default: \
|
||||
assert(false); \
|
||||
return ""; \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
typedef boost::integer_range<int> range_type; \
|
||||
static range_type tags() \
|
||||
{ \
|
||||
return boost::irange(start_index, (int)end_index); \
|
||||
} \
|
||||
static bool is_tag(int value) \
|
||||
{ \
|
||||
return value >= start_index && value < (int)end_index; \
|
||||
} \
|
||||
};
|
||||
|
||||
#define QUICKBOOK_VALUE_CASE(r, _, value) \
|
||||
case value: return BOOST_PP_STRINGIZE(value);
|
||||
#define QUICKBOOK_VALUE_CASE(r, _, value) \
|
||||
case value: \
|
||||
return BOOST_PP_STRINGIZE(value);
|
||||
|
||||
#define QUICKBOOK_VALUE_NAMED_TAGS(tags_name, start_index, values) \
|
||||
struct tags_name { \
|
||||
enum tags_name##_enum { \
|
||||
previous_index = start_index - 1 \
|
||||
BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_NAMED_ENUM, _, values), \
|
||||
end_index \
|
||||
}; \
|
||||
\
|
||||
static char const* name(int value) { \
|
||||
switch(value) {\
|
||||
case 0: \
|
||||
return "null"; \
|
||||
BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_NAMED_CASE, _, values) \
|
||||
default: \
|
||||
assert(false); return ""; \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
typedef boost::integer_range<int> range_type; \
|
||||
static range_type tags() { return boost::irange(start_index, (int) end_index); } \
|
||||
static bool is_tag(int value) { \
|
||||
return value >= start_index && value < (int) end_index; \
|
||||
} \
|
||||
#define QUICKBOOK_VALUE_NAMED_TAGS(tags_name, start_index, values) \
|
||||
struct tags_name \
|
||||
{ \
|
||||
enum tags_name##_enum{previous_index = \
|
||||
start_index - \
|
||||
1 BOOST_PP_SEQ_FOR_EACH( \
|
||||
QUICKBOOK_VALUE_NAMED_ENUM, _, values), \
|
||||
end_index}; \
|
||||
\
|
||||
static char const* name(int value) \
|
||||
{ \
|
||||
switch (value) { \
|
||||
case 0: \
|
||||
return "null"; \
|
||||
BOOST_PP_SEQ_FOR_EACH(QUICKBOOK_VALUE_NAMED_CASE, _, values) \
|
||||
default: \
|
||||
assert(false); \
|
||||
return ""; \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
typedef boost::integer_range<int> range_type; \
|
||||
static range_type tags() \
|
||||
{ \
|
||||
return boost::irange(start_index, (int)end_index); \
|
||||
} \
|
||||
static bool is_tag(int value) \
|
||||
{ \
|
||||
return value >= start_index && value < (int)end_index; \
|
||||
} \
|
||||
};
|
||||
|
||||
#define QUICKBOOK_VALUE_NAMED_ENUM(r, _, value) \
|
||||
, BOOST_PP_SEQ_ELEM(0, value)
|
||||
|
||||
#define QUICKBOOK_VALUE_NAMED_CASE(r, _, value) \
|
||||
case BOOST_PP_SEQ_ELEM(0, value): return BOOST_PP_SEQ_ELEM(1, value);
|
||||
#define QUICKBOOK_VALUE_NAMED_ENUM(r, _, value) , BOOST_PP_SEQ_ELEM(0, value)
|
||||
|
||||
#define QUICKBOOK_VALUE_NAMED_CASE(r, _, value) \
|
||||
case BOOST_PP_SEQ_ELEM(0, value): \
|
||||
return BOOST_PP_SEQ_ELEM(1, value);
|
||||
|
||||
#endif
|
||||
|
||||
681
src/values.cpp
681
src/values.cpp
File diff suppressed because it is too large
Load Diff
244
src/values.hpp
244
src/values.hpp
@@ -11,16 +11,16 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_VALUES_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_VALUES_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include "string_view.hpp"
|
||||
#include "fwd.hpp"
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include "files.hpp"
|
||||
#include "fwd.hpp"
|
||||
#include "string_view.hpp"
|
||||
|
||||
namespace quickbook
|
||||
{
|
||||
@@ -32,21 +32,21 @@ namespace quickbook
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Node
|
||||
|
||||
|
||||
struct value_node
|
||||
{
|
||||
private:
|
||||
private:
|
||||
value_node(value_node const&);
|
||||
value_node& operator=(value_node const&);
|
||||
|
||||
public:
|
||||
public:
|
||||
typedef int tag_type;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
explicit value_node(tag_type);
|
||||
virtual ~value_node();
|
||||
|
||||
public:
|
||||
public:
|
||||
virtual char const* type_name() const = 0;
|
||||
virtual value_node* clone() const = 0;
|
||||
|
||||
@@ -63,15 +63,19 @@ namespace quickbook
|
||||
virtual bool equals(value_node*) const;
|
||||
|
||||
virtual value_node* get_list() const;
|
||||
|
||||
|
||||
int ref_count_;
|
||||
const tag_type tag_;
|
||||
value_node* next_;
|
||||
|
||||
friend void intrusive_ptr_add_ref(value_node* ptr)
|
||||
{ ++ptr->ref_count_; }
|
||||
{
|
||||
++ptr->ref_count_;
|
||||
}
|
||||
friend void intrusive_ptr_release(value_node* ptr)
|
||||
{ if(--ptr->ref_count_ == 0) delete ptr; }
|
||||
{
|
||||
if (--ptr->ref_count_ == 0) delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -79,19 +83,21 @@ namespace quickbook
|
||||
//
|
||||
// This defines most of the public methods for value.
|
||||
// 'begin' and 'end' are defined with the iterators later.
|
||||
|
||||
|
||||
struct value_base
|
||||
{
|
||||
public:
|
||||
public:
|
||||
struct iterator;
|
||||
|
||||
typedef iterator const_iterator;
|
||||
typedef value_node::tag_type tag_type;
|
||||
enum { default_tag = 0 };
|
||||
enum
|
||||
{
|
||||
default_tag = 0
|
||||
};
|
||||
|
||||
protected:
|
||||
explicit value_base(value_node* base)
|
||||
: value_(base)
|
||||
protected:
|
||||
explicit value_base(value_node* base) : value_(base)
|
||||
{
|
||||
assert(value_);
|
||||
}
|
||||
@@ -99,7 +105,8 @@ namespace quickbook
|
||||
~value_base() {}
|
||||
|
||||
void swap(value_base& x) { std::swap(value_, x.value_); }
|
||||
public:
|
||||
|
||||
public:
|
||||
bool check() const { return value_->check(); }
|
||||
bool empty() const { return value_->empty(); }
|
||||
bool is_encoded() const { return value_->is_encoded(); }
|
||||
@@ -110,63 +117,76 @@ namespace quickbook
|
||||
|
||||
// Item accessors
|
||||
tag_type get_tag() const { return value_->tag_; }
|
||||
file_ptr get_file() const
|
||||
{ return value_->get_file(); }
|
||||
file_ptr get_file() const { return value_->get_file(); }
|
||||
string_iterator get_position() const
|
||||
{ return value_->get_position(); }
|
||||
{
|
||||
return value_->get_position();
|
||||
}
|
||||
quickbook::string_view get_quickbook() const
|
||||
{ return value_->get_quickbook(); }
|
||||
std::string get_encoded() const
|
||||
{ return value_->get_encoded(); }
|
||||
int get_int() const
|
||||
{ return value_->get_int(); }
|
||||
{
|
||||
return value_->get_quickbook();
|
||||
}
|
||||
std::string get_encoded() const { return value_->get_encoded(); }
|
||||
int get_int() const { return value_->get_int(); }
|
||||
|
||||
// Equality is pretty inefficient. Not really designed for anything
|
||||
// more than testing purposes.
|
||||
friend bool operator==(value_base const& x, value_base const& y)
|
||||
{ return x.value_->equals(y.value_); }
|
||||
{
|
||||
return x.value_->equals(y.value_);
|
||||
}
|
||||
|
||||
protected:
|
||||
protected:
|
||||
value_node* value_;
|
||||
|
||||
// value_builder needs to access 'value_' to get the node
|
||||
// from a value.
|
||||
friend struct quickbook::value_builder;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Reference and proxy values for use in iterators
|
||||
|
||||
struct value_ref : public value_base
|
||||
{
|
||||
public:
|
||||
public:
|
||||
explicit value_ref(value_node* base) : value_base(base) {}
|
||||
};
|
||||
|
||||
|
||||
struct value_proxy : public value_base
|
||||
{
|
||||
public:
|
||||
public:
|
||||
explicit value_proxy(value_node* base) : value_base(base) {}
|
||||
value_proxy* operator->() { return this; }
|
||||
value_ref operator*() const { return value_ref(value_); }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Iterators
|
||||
|
||||
struct value_base::iterator
|
||||
: public boost::forward_iterator_helper<
|
||||
iterator, value, int, value_proxy, value_ref>
|
||||
struct value_base::iterator : public boost::forward_iterator_helper<
|
||||
iterator,
|
||||
value,
|
||||
int,
|
||||
value_proxy,
|
||||
value_ref>
|
||||
{
|
||||
public:
|
||||
public:
|
||||
iterator();
|
||||
explicit iterator(value_node* p) : ptr_(p) {}
|
||||
friend bool operator==(iterator x, iterator y)
|
||||
{ return x.ptr_ == y.ptr_; }
|
||||
iterator& operator++() { ptr_ = ptr_->next_; return *this; }
|
||||
{
|
||||
return x.ptr_ == y.ptr_;
|
||||
}
|
||||
iterator& operator++()
|
||||
{
|
||||
ptr_ = ptr_->next_;
|
||||
return *this;
|
||||
}
|
||||
value_ref operator*() const { return value_ref(ptr_); }
|
||||
value_proxy operator->() const { return value_proxy(ptr_); }
|
||||
private:
|
||||
|
||||
private:
|
||||
value_node* ptr_;
|
||||
};
|
||||
|
||||
@@ -186,7 +206,8 @@ namespace quickbook
|
||||
struct value_counted : public value_base
|
||||
{
|
||||
value_counted& operator=(value_counted const&);
|
||||
protected:
|
||||
|
||||
protected:
|
||||
value_counted();
|
||||
value_counted(value_counted const&);
|
||||
value_counted(value_base const&);
|
||||
@@ -200,10 +221,12 @@ namespace quickbook
|
||||
// Values are immutable, so this class is used to build a list of
|
||||
// value nodes before constructing the value.
|
||||
|
||||
struct value_list_builder {
|
||||
struct value_list_builder
|
||||
{
|
||||
value_list_builder(value_list_builder const&);
|
||||
value_list_builder& operator=(value_list_builder const&);
|
||||
public:
|
||||
|
||||
public:
|
||||
value_list_builder();
|
||||
value_list_builder(value_node*);
|
||||
~value_list_builder();
|
||||
@@ -214,12 +237,13 @@ namespace quickbook
|
||||
void sort();
|
||||
|
||||
bool empty() const;
|
||||
private:
|
||||
|
||||
private:
|
||||
value_node* head_;
|
||||
value_node** back_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Value
|
||||
//
|
||||
@@ -227,7 +251,7 @@ namespace quickbook
|
||||
|
||||
struct value : public detail::value_counted
|
||||
{
|
||||
public:
|
||||
public:
|
||||
value();
|
||||
value(value const&);
|
||||
value(detail::value_base const&);
|
||||
@@ -235,7 +259,7 @@ namespace quickbook
|
||||
value& operator=(value);
|
||||
void swap(value& x) { detail::value_counted::swap(x); }
|
||||
};
|
||||
|
||||
|
||||
// Empty
|
||||
value empty_value(value::tag_type = value::default_tag);
|
||||
|
||||
@@ -245,28 +269,36 @@ namespace quickbook
|
||||
// String types
|
||||
|
||||
// Quickbook strings contain a reference to the original quickbook source.
|
||||
value qbk_value(file_ptr const&, string_iterator, string_iterator,
|
||||
value::tag_type = value::default_tag);
|
||||
value qbk_value(
|
||||
file_ptr const&,
|
||||
string_iterator,
|
||||
string_iterator,
|
||||
value::tag_type = value::default_tag);
|
||||
|
||||
// Encoded strings are either plain text or boostbook.
|
||||
value encoded_value(std::string const&,
|
||||
value::tag_type = value::default_tag);
|
||||
value encoded_value(
|
||||
std::string const&, value::tag_type = value::default_tag);
|
||||
|
||||
// An encoded quickbook string is an encoded string that contains a
|
||||
// reference to the quickbook source it was generated from.
|
||||
value encoded_qbk_value(file_ptr const&, string_iterator, string_iterator,
|
||||
std::string const&, value::tag_type = value::default_tag);
|
||||
value encoded_qbk_value(
|
||||
file_ptr const&,
|
||||
string_iterator,
|
||||
string_iterator,
|
||||
std::string const&,
|
||||
value::tag_type = value::default_tag);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Value Builder
|
||||
//
|
||||
// Used to incrementally build a valueeter tree.
|
||||
|
||||
struct value_builder {
|
||||
public:
|
||||
struct value_builder
|
||||
{
|
||||
public:
|
||||
value_builder();
|
||||
void swap(value_builder& b);
|
||||
|
||||
|
||||
void save();
|
||||
void restore();
|
||||
|
||||
@@ -282,7 +314,7 @@ namespace quickbook
|
||||
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
private:
|
||||
detail::value_list_builder current;
|
||||
value::tag_type list_tag;
|
||||
boost::scoped_ptr<value_builder> saved;
|
||||
@@ -291,10 +323,10 @@ namespace quickbook
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Value Error
|
||||
//
|
||||
|
||||
|
||||
struct value_error : public std::logic_error
|
||||
{
|
||||
public:
|
||||
public:
|
||||
explicit value_error(std::string const&);
|
||||
};
|
||||
|
||||
@@ -303,41 +335,46 @@ namespace quickbook
|
||||
//
|
||||
// Convenience class for unpacking value values.
|
||||
|
||||
struct value_consumer {
|
||||
public:
|
||||
struct iterator
|
||||
: public boost::input_iterator_helper<iterator,
|
||||
boost::iterator_value<value::iterator>::type,
|
||||
boost::iterator_difference<value::iterator>::type,
|
||||
boost::iterator_pointer<value::iterator>::type,
|
||||
boost::iterator_reference<value::iterator>::type>
|
||||
struct value_consumer
|
||||
{
|
||||
public:
|
||||
struct iterator : public boost::input_iterator_helper<
|
||||
iterator,
|
||||
boost::iterator_value<value::iterator>::type,
|
||||
boost::iterator_difference<value::iterator>::type,
|
||||
boost::iterator_pointer<value::iterator>::type,
|
||||
boost::iterator_reference<value::iterator>::type>
|
||||
{
|
||||
public:
|
||||
public:
|
||||
iterator();
|
||||
explicit iterator(value::iterator* p) : ptr_(p) {}
|
||||
friend bool operator==(iterator x, iterator y)
|
||||
{ return *x.ptr_ == *y.ptr_; }
|
||||
iterator& operator++() { ++*ptr_; return *this; }
|
||||
{
|
||||
return *x.ptr_ == *y.ptr_;
|
||||
}
|
||||
iterator& operator++()
|
||||
{
|
||||
++*ptr_;
|
||||
return *this;
|
||||
}
|
||||
reference operator*() const { return **ptr_; }
|
||||
pointer operator->() const { return ptr_->operator->(); }
|
||||
private:
|
||||
|
||||
private:
|
||||
value::iterator* ptr_;
|
||||
};
|
||||
|
||||
typedef iterator const_iterator;
|
||||
typedef iterator::reference reference;
|
||||
|
||||
value_consumer(value const& x)
|
||||
: list_(x)
|
||||
, pos_(x.begin())
|
||||
, end_(x.end())
|
||||
{}
|
||||
|
||||
value_consumer(reference x)
|
||||
: list_(x)
|
||||
, pos_(x.begin())
|
||||
, end_(x.end())
|
||||
{}
|
||||
value_consumer(value const& x)
|
||||
: list_(x), pos_(x.begin()), end_(x.end())
|
||||
{
|
||||
}
|
||||
|
||||
value_consumer(reference x) : list_(x), pos_(x.begin()), end_(x.end())
|
||||
{
|
||||
}
|
||||
|
||||
reference consume()
|
||||
{
|
||||
@@ -353,7 +390,7 @@ namespace quickbook
|
||||
|
||||
value optional_consume()
|
||||
{
|
||||
if(check()) {
|
||||
if (check()) {
|
||||
return *pos_++;
|
||||
}
|
||||
else {
|
||||
@@ -363,7 +400,7 @@ namespace quickbook
|
||||
|
||||
value optional_consume(value::tag_type t)
|
||||
{
|
||||
if(check(t)) {
|
||||
if (check(t)) {
|
||||
return *pos_++;
|
||||
}
|
||||
else {
|
||||
@@ -371,38 +408,33 @@ namespace quickbook
|
||||
}
|
||||
}
|
||||
|
||||
bool check() const
|
||||
{
|
||||
return pos_ != end_;
|
||||
}
|
||||
bool check() const { return pos_ != end_; }
|
||||
|
||||
bool check(value::tag_type t) const
|
||||
{
|
||||
return pos_ != end_ && t == pos_->get_tag();
|
||||
}
|
||||
|
||||
|
||||
void finish() const
|
||||
{
|
||||
if (pos_ != end_)
|
||||
throw value_error("Not all values handled.");
|
||||
if (pos_ != end_) throw value_error("Not all values handled.");
|
||||
}
|
||||
|
||||
iterator begin() { return iterator(&pos_); }
|
||||
iterator end() { return iterator(&end_); }
|
||||
private:
|
||||
|
||||
void assert_check() const
|
||||
{
|
||||
if (pos_ == end_)
|
||||
throw value_error("Attempt to read past end of value list.");
|
||||
}
|
||||
private:
|
||||
void assert_check() const
|
||||
{
|
||||
if (pos_ == end_)
|
||||
throw value_error("Attempt to read past end of value list.");
|
||||
}
|
||||
|
||||
void assert_check(value::tag_type t) const
|
||||
{
|
||||
assert_check();
|
||||
if (t != pos_->get_tag())
|
||||
throw value_error("Incorrect value tag.");
|
||||
}
|
||||
void assert_check(value::tag_type t) const
|
||||
{
|
||||
assert_check();
|
||||
if (t != pos_->get_tag()) throw value_error("Incorrect value tag.");
|
||||
}
|
||||
|
||||
value list_;
|
||||
value::iterator pos_, end_;
|
||||
|
||||
@@ -9,19 +9,22 @@
|
||||
#if !defined(BOOST_SPIRIT_QUICKBOOK_VALUES_PARSE_HPP)
|
||||
#define BOOST_SPIRIT_QUICKBOOK_VALUES_PARSE_HPP
|
||||
|
||||
#include "values.hpp"
|
||||
#include <boost/spirit/include/phoenix1_functions.hpp>
|
||||
#include "parsers.hpp"
|
||||
#include "scoped.hpp"
|
||||
#include <boost/spirit/include/phoenix1_functions.hpp>
|
||||
#include "values.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace quickbook {
|
||||
namespace quickbook
|
||||
{
|
||||
namespace ph = phoenix;
|
||||
|
||||
struct value_builder_save : scoped_action_base
|
||||
{
|
||||
explicit value_builder_save(value_builder& builder_) : builder(builder_) {}
|
||||
explicit value_builder_save(value_builder& builder_) : builder(builder_)
|
||||
{
|
||||
}
|
||||
|
||||
bool start()
|
||||
{
|
||||
@@ -33,13 +36,15 @@ namespace quickbook {
|
||||
|
||||
value_builder& builder;
|
||||
|
||||
private:
|
||||
private:
|
||||
value_builder_save& operator=(value_builder_save const&);
|
||||
};
|
||||
|
||||
struct value_builder_list : scoped_action_base
|
||||
{
|
||||
explicit value_builder_list(value_builder& builder_) : builder(builder_) {}
|
||||
explicit value_builder_list(value_builder& builder_) : builder(builder_)
|
||||
{
|
||||
}
|
||||
|
||||
bool start(value::tag_type tag = value::default_tag)
|
||||
{
|
||||
@@ -52,28 +57,37 @@ namespace quickbook {
|
||||
|
||||
value_builder& builder;
|
||||
|
||||
private:
|
||||
private:
|
||||
value_builder_list& operator=(value_builder_list const&);
|
||||
};
|
||||
|
||||
struct value_entry
|
||||
{
|
||||
template <typename Arg1, typename Arg2 = void, typename Arg3 = void, typename Arg4 = void>
|
||||
struct result {
|
||||
template <
|
||||
typename Arg1,
|
||||
typename Arg2 = void,
|
||||
typename Arg3 = void,
|
||||
typename Arg4 = void>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit value_entry(value_builder& builder_, file_ptr* current_file_)
|
||||
: builder(builder_), current_file(current_file_) {}
|
||||
|
||||
void operator()(parse_iterator begin, parse_iterator end,
|
||||
value::tag_type tag = value::default_tag) const
|
||||
: builder(builder_), current_file(current_file_)
|
||||
{
|
||||
builder.insert(qbk_value(*current_file, begin.base(), end.base(), tag));
|
||||
}
|
||||
|
||||
void operator()(int v,
|
||||
void operator()(
|
||||
parse_iterator begin,
|
||||
parse_iterator end,
|
||||
value::tag_type tag = value::default_tag) const
|
||||
{
|
||||
builder.insert(
|
||||
qbk_value(*current_file, begin.base(), end.base(), tag));
|
||||
}
|
||||
|
||||
void operator()(int v, value::tag_type tag = value::default_tag) const
|
||||
{
|
||||
builder.insert(int_value(v, tag));
|
||||
}
|
||||
@@ -81,24 +95,21 @@ namespace quickbook {
|
||||
value_builder& builder;
|
||||
file_ptr* current_file;
|
||||
|
||||
private:
|
||||
private:
|
||||
value_entry& operator=(value_entry const&);
|
||||
};
|
||||
|
||||
struct value_sort
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
explicit value_sort(value_builder& builder_)
|
||||
: builder(builder_) {}
|
||||
|
||||
void operator()() const {
|
||||
builder.sort_list();
|
||||
}
|
||||
explicit value_sort(value_builder& builder_) : builder(builder_) {}
|
||||
|
||||
void operator()() const { builder.sort_list(); }
|
||||
|
||||
value_builder& builder;
|
||||
|
||||
private:
|
||||
private:
|
||||
value_sort& operator=(value_sort const&);
|
||||
};
|
||||
|
||||
@@ -110,8 +121,9 @@ namespace quickbook {
|
||||
, list(value_builder_list(builder))
|
||||
, entry(value_entry(builder, current_file))
|
||||
, sort(value_sort(builder))
|
||||
{}
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
value release() { return builder.release(); }
|
||||
|
||||
value_builder builder;
|
||||
|
||||
@@ -7,4 +7,3 @@
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/spirit/include/classic_scanner.hpp>
|
||||
#include <boost/spirit/include/classic_primitives.hpp>
|
||||
#include <boost/spirit/include/classic_scanner.hpp>
|
||||
|
||||
namespace spirit = boost::spirit::classic;
|
||||
|
||||
typedef std::istream_iterator<char, char> iterator;
|
||||
typedef spirit::scanner<iterator> scanner;
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::vector<char*> args;
|
||||
bool usage_error = false;
|
||||
@@ -30,17 +30,18 @@ int main(int argc, char * argv[])
|
||||
if (strcmp(argv[i], "--strict") == 0) {
|
||||
// Ignore --strict because the build file accidentally
|
||||
// uses it. Why yes, this is a horrible hack.
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR: Invalid flag: " << argv[i] << std::endl;
|
||||
usage_error = true;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
args.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!usage_error && args.size() != 2)
|
||||
{
|
||||
if (!usage_error && args.size() != 2) {
|
||||
std::cerr << "ERROR: Wrong number of arguments." << std::endl;
|
||||
usage_error = true;
|
||||
}
|
||||
@@ -50,12 +51,10 @@ int main(int argc, char * argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ifstream
|
||||
file1(args[0], std::ios_base::binary | std::ios_base::in),
|
||||
std::ifstream file1(args[0], std::ios_base::binary | std::ios_base::in),
|
||||
file2(args[1], std::ios_base::binary | std::ios_base::in);
|
||||
|
||||
if (!file1 || !file2)
|
||||
{
|
||||
if (!file1 || !file2) {
|
||||
std::cerr << "ERROR: Unable to open one or both files." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
@@ -63,24 +62,17 @@ int main(int argc, char * argv[])
|
||||
file1.unsetf(std::ios_base::skipws);
|
||||
file2.unsetf(std::ios_base::skipws);
|
||||
|
||||
iterator
|
||||
iter_file1(file1),
|
||||
iter_file2(file2);
|
||||
iterator iter_file1(file1), iter_file2(file2);
|
||||
|
||||
scanner
|
||||
scan1(iter_file1, iterator()),
|
||||
scan2(iter_file2, iterator());
|
||||
scanner scan1(iter_file1, iterator()), scan2(iter_file2, iterator());
|
||||
|
||||
std::size_t line = 1, column = 1;
|
||||
|
||||
while (!scan1.at_end() && !scan2.at_end())
|
||||
{
|
||||
if (spirit::eol_p.parse(scan1))
|
||||
{
|
||||
if (!spirit::eol_p.parse(scan2))
|
||||
{
|
||||
std::cout << "Files differ at line " << line << ", column " <<
|
||||
column << '.' << std::endl;
|
||||
while (!scan1.at_end() && !scan2.at_end()) {
|
||||
if (spirit::eol_p.parse(scan1)) {
|
||||
if (!spirit::eol_p.parse(scan2)) {
|
||||
std::cout << "Files differ at line " << line << ", column "
|
||||
<< column << '.' << std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -88,18 +80,16 @@ int main(int argc, char * argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*scan1 != *scan2)
|
||||
{
|
||||
std::cout << "Files differ at line " << line << ", column " <<
|
||||
column << '.' << std::endl;
|
||||
if (*scan1 != *scan2) {
|
||||
std::cout << "Files differ at line " << line << ", column "
|
||||
<< column << '.' << std::endl;
|
||||
return 4;
|
||||
}
|
||||
|
||||
++scan1, ++scan2, ++column;
|
||||
}
|
||||
|
||||
if (scan1.at_end() != scan2.at_end())
|
||||
{
|
||||
if (scan1.at_end() != scan2.at_end()) {
|
||||
std::cout << "Files differ in length." << std::endl;
|
||||
return 5;
|
||||
}
|
||||
|
||||
@@ -7,31 +7,36 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "cleanup.hpp"
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <vector>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include "cleanup.hpp"
|
||||
|
||||
struct counted {
|
||||
struct counted
|
||||
{
|
||||
static int count;
|
||||
static std::vector<int> destroyed;
|
||||
static void reset() {
|
||||
static void reset()
|
||||
{
|
||||
count = 0;
|
||||
destroyed.clear();
|
||||
}
|
||||
|
||||
int value;
|
||||
|
||||
counted(int v) : value(v) {
|
||||
counted(int v) : value(v)
|
||||
{
|
||||
BOOST_TEST(value != -1);
|
||||
++count;
|
||||
}
|
||||
|
||||
counted(counted const& x) : value(x.value) {
|
||||
counted(counted const& x) : value(x.value)
|
||||
{
|
||||
BOOST_TEST(value != -1);
|
||||
++count;
|
||||
}
|
||||
|
||||
~counted() {
|
||||
~counted()
|
||||
{
|
||||
BOOST_TEST(value != -1);
|
||||
destroyed.push_back(value);
|
||||
value = -1;
|
||||
@@ -43,7 +48,8 @@ struct counted {
|
||||
int counted::count = 0;
|
||||
std::vector<int> counted::destroyed;
|
||||
|
||||
int main() {
|
||||
int main()
|
||||
{
|
||||
counted::reset();
|
||||
{
|
||||
quickbook::cleanup c;
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "glob.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "glob.hpp"
|
||||
|
||||
void glob_tests() {
|
||||
void glob_tests()
|
||||
{
|
||||
BOOST_TEST(quickbook::glob("", ""));
|
||||
|
||||
BOOST_TEST(!quickbook::glob("*", ""));
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "path.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/predef.h>
|
||||
#include "path.hpp"
|
||||
|
||||
void file_path_to_url_tests() {
|
||||
void file_path_to_url_tests()
|
||||
{
|
||||
using boost::filesystem::path;
|
||||
using quickbook::file_path_to_url;
|
||||
|
||||
@@ -22,28 +23,37 @@ void file_path_to_url_tests() {
|
||||
BOOST_TEST_EQ(std::string("a/b/"), file_path_to_url(path("a/b/")));
|
||||
BOOST_TEST_EQ(std::string("./a/b"), file_path_to_url(path("./a/./././b")));
|
||||
BOOST_TEST_EQ(std::string("../a/b"), file_path_to_url(path("../a/b")));
|
||||
BOOST_TEST_EQ(std::string("A%20B%2bC%2520"), file_path_to_url(path("A B+C%20")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("A%20B%2bC%2520"), file_path_to_url(path("A B+C%20")));
|
||||
BOOST_TEST_EQ(std::string("file:///"), file_path_to_url(path("/")));
|
||||
BOOST_TEST_EQ(std::string("file:///a/b"), file_path_to_url(path("/a/b")));
|
||||
BOOST_TEST_EQ(std::string("file:///a/b/"), file_path_to_url(path("/a/b/")));
|
||||
BOOST_TEST_EQ(std::string("file://hello/a/b"), file_path_to_url(path("//hello/a/b")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file://hello/a/b"), file_path_to_url(path("//hello/a/b")));
|
||||
|
||||
#if BOOST_OS_WINDOWS || BOOST_OS_CYGWIN
|
||||
// Should this be file:///c:/x ?
|
||||
BOOST_TEST_EQ(std::string("file://?/a:/x"), file_path_to_url(path("\\\\?\\a:\\x")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file://?/a:/x"), file_path_to_url(path("\\\\?\\a:\\x")));
|
||||
BOOST_TEST_EQ(std::string("file:///a"), file_path_to_url(path("\\a")));
|
||||
BOOST_TEST_EQ(std::string("file:///c:/"), file_path_to_url(path("c:\\")));
|
||||
BOOST_TEST_EQ(std::string("file:///c:/foo/bar"), file_path_to_url(path("c:\\foo\\bar")));
|
||||
BOOST_TEST_EQ(std::string("file://localhost/c:/foo/bar"), file_path_to_url(path("\\\\localhost\\c:\\foo\\bar")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file:///c:/foo/bar"),
|
||||
file_path_to_url(path("c:\\foo\\bar")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file://localhost/c:/foo/bar"),
|
||||
file_path_to_url(path("\\\\localhost\\c:\\foo\\bar")));
|
||||
|
||||
// Really not sure what to do with these examples.
|
||||
// Maybe an error?
|
||||
BOOST_TEST_EQ(std::string("file:///c:"), file_path_to_url(path("c:")));
|
||||
BOOST_TEST_EQ(std::string("file:///c:foo/bar"), file_path_to_url(path("c:foo\\bar")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file:///c:foo/bar"), file_path_to_url(path("c:foo\\bar")));
|
||||
#endif
|
||||
}
|
||||
|
||||
void dir_path_to_url_tests() {
|
||||
void dir_path_to_url_tests()
|
||||
{
|
||||
using boost::filesystem::path;
|
||||
using quickbook::dir_path_to_url;
|
||||
|
||||
@@ -54,29 +64,37 @@ void dir_path_to_url_tests() {
|
||||
BOOST_TEST_EQ(std::string("a/b/"), dir_path_to_url(path("a/b/")));
|
||||
BOOST_TEST_EQ(std::string("./a/b/"), dir_path_to_url(path("./a/./././b")));
|
||||
BOOST_TEST_EQ(std::string("../a/b/"), dir_path_to_url(path("../a/b")));
|
||||
BOOST_TEST_EQ(std::string("A%20B%2bC%2520/"), dir_path_to_url(path("A B+C%20")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("A%20B%2bC%2520/"), dir_path_to_url(path("A B+C%20")));
|
||||
BOOST_TEST_EQ(std::string("file:///"), dir_path_to_url(path("/")));
|
||||
BOOST_TEST_EQ(std::string("file:///a/b/"), dir_path_to_url(path("/a/b")));
|
||||
BOOST_TEST_EQ(std::string("file:///a/b/"), dir_path_to_url(path("/a/b/")));
|
||||
BOOST_TEST_EQ(std::string("file://hello/a/b/"), dir_path_to_url(path("//hello/a/b")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file://hello/a/b/"), dir_path_to_url(path("//hello/a/b")));
|
||||
|
||||
#if BOOST_OS_WINDOWS || BOOST_OS_CYGWIN
|
||||
// Should this be file:///c:/x/ ?
|
||||
BOOST_TEST_EQ(std::string("file://?/a:/x/"), dir_path_to_url(path("\\\\?\\a:\\x")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file://?/a:/x/"), dir_path_to_url(path("\\\\?\\a:\\x")));
|
||||
BOOST_TEST_EQ(std::string("file:///a/"), dir_path_to_url(path("\\a")));
|
||||
BOOST_TEST_EQ(std::string("file:///c:/"), dir_path_to_url(path("c:\\")));
|
||||
BOOST_TEST_EQ(std::string("file:///c:/foo/bar/"), dir_path_to_url(path("c:\\foo\\bar")));
|
||||
BOOST_TEST_EQ(std::string("file://localhost/c:/foo/bar/"), dir_path_to_url(path("\\\\localhost\\c:\\foo\\bar")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file:///c:/foo/bar/"),
|
||||
dir_path_to_url(path("c:\\foo\\bar")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file://localhost/c:/foo/bar/"),
|
||||
dir_path_to_url(path("\\\\localhost\\c:\\foo\\bar")));
|
||||
|
||||
// Really not sure what to do with these examples.
|
||||
// Maybe an error?
|
||||
BOOST_TEST_EQ(std::string("file:///c:"), dir_path_to_url(path("c:")));
|
||||
BOOST_TEST_EQ(std::string("file:///c:foo/bar/"), dir_path_to_url(path("c:foo\\bar")));
|
||||
BOOST_TEST_EQ(
|
||||
std::string("file:///c:foo/bar/"), dir_path_to_url(path("c:foo\\bar")));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void path_difference_tests() {
|
||||
void path_difference_tests()
|
||||
{
|
||||
using boost::filesystem::current_path;
|
||||
using boost::filesystem::path;
|
||||
using quickbook::path_difference;
|
||||
@@ -86,19 +104,31 @@ void path_difference_tests() {
|
||||
BOOST_TEST(path(".") == path_difference(path("a/../b"), path("b")));
|
||||
BOOST_TEST(path(".") == path_difference(current_path(), current_path()));
|
||||
BOOST_TEST(path("..") == path_difference(path("a"), path("")));
|
||||
BOOST_TEST(path("..") == path_difference(current_path()/"a", current_path()));
|
||||
BOOST_TEST(
|
||||
path("..") == path_difference(current_path() / "a", current_path()));
|
||||
BOOST_TEST(path("a") == path_difference(path(""), path("a")));
|
||||
BOOST_TEST(path("a") == path_difference(current_path(), current_path()/"a"));
|
||||
BOOST_TEST(
|
||||
path("a") == path_difference(current_path(), current_path() / "a"));
|
||||
BOOST_TEST(path("b") == path_difference(path("a"), path("a/b")));
|
||||
BOOST_TEST(path("b") == path_difference(current_path()/"a", current_path()/"a"/"b"));
|
||||
BOOST_TEST(
|
||||
path("b") ==
|
||||
path_difference(current_path() / "a", current_path() / "a" / "b"));
|
||||
BOOST_TEST(path("../a/b") == path_difference(path("c"), path("a/b")));
|
||||
BOOST_TEST(path("../a/b") == path_difference(current_path()/"c", current_path()/"a"/"b"));
|
||||
BOOST_TEST(
|
||||
path("../a/b") ==
|
||||
path_difference(current_path() / "c", current_path() / "a" / "b"));
|
||||
BOOST_TEST(path("..") == path_difference(path(""), path("..")));
|
||||
BOOST_TEST(path("..") == path_difference(current_path(), current_path().parent_path()));
|
||||
BOOST_TEST(
|
||||
path("..") ==
|
||||
path_difference(current_path(), current_path().parent_path()));
|
||||
BOOST_TEST(path("b") == path_difference(path("a/c/.."), path("a/b")));
|
||||
BOOST_TEST(path("b") == path_difference(path("b/c/../../a"), path("a/b")));
|
||||
BOOST_TEST(path("b") == path_difference(path("b/c/../../a"), path("d/f/../../a/b")));
|
||||
BOOST_TEST(path("../../x/a/b") == path_difference(path("b/c/../../a"), path("d/f/../../../x/a/b")));
|
||||
BOOST_TEST(
|
||||
path("b") ==
|
||||
path_difference(path("b/c/../../a"), path("d/f/../../a/b")));
|
||||
BOOST_TEST(
|
||||
path("../../x/a/b") ==
|
||||
path_difference(path("b/c/../../a"), path("d/f/../../../x/a/b")));
|
||||
|
||||
// path_difference to a file, try to include the filename in the result,
|
||||
// although not always possible. Maybe nonsense calls should be an error?
|
||||
@@ -108,29 +138,50 @@ void path_difference_tests() {
|
||||
// always called with the full path, but it'd be nice to get this right.
|
||||
// Or maybe just add the pre-condition to path_difference?
|
||||
std::cout << path_difference(path(""), path(""), true) << std::endl;
|
||||
//BOOST_TEST(path(".") == path_difference(path(""), path(""), true));
|
||||
// BOOST_TEST(path(".") == path_difference(path(""), path(""), true));
|
||||
BOOST_TEST(path("../a") == path_difference(path("a"), path("a"), true));
|
||||
BOOST_TEST(path("../../a") == path_difference(path("a/b"), path("a"), true));
|
||||
BOOST_TEST(path("../b") == path_difference(path("a/../b"), path("b"), true));
|
||||
BOOST_TEST(".."/current_path().filename() == path_difference(current_path(), current_path(), true));
|
||||
//BOOST_TEST(path("..") == path_difference(path("a"), path(""), true));
|
||||
BOOST_TEST("../.."/current_path().filename() == path_difference(current_path()/"a", current_path(), true));
|
||||
BOOST_TEST(
|
||||
path("../../a") == path_difference(path("a/b"), path("a"), true));
|
||||
BOOST_TEST(
|
||||
path("../b") == path_difference(path("a/../b"), path("b"), true));
|
||||
BOOST_TEST(
|
||||
".." / current_path().filename() ==
|
||||
path_difference(current_path(), current_path(), true));
|
||||
// BOOST_TEST(path("..") == path_difference(path("a"), path(""), true));
|
||||
BOOST_TEST(
|
||||
"../.." / current_path().filename() ==
|
||||
path_difference(current_path() / "a", current_path(), true));
|
||||
BOOST_TEST(path("a") == path_difference(path(""), path("a"), true));
|
||||
BOOST_TEST(path("a") == path_difference(current_path(), current_path()/"a", true));
|
||||
BOOST_TEST(
|
||||
path("a") ==
|
||||
path_difference(current_path(), current_path() / "a", true));
|
||||
BOOST_TEST(path("b") == path_difference(path("a"), path("a/b"), true));
|
||||
BOOST_TEST(path("b") == path_difference(current_path()/"a", current_path()/"a"/"b", true));
|
||||
BOOST_TEST(
|
||||
path("b") ==
|
||||
path_difference(
|
||||
current_path() / "a", current_path() / "a" / "b", true));
|
||||
BOOST_TEST(path("../a/b") == path_difference(path("c"), path("a/b"), true));
|
||||
BOOST_TEST(path("../a/b") == path_difference(current_path()/"c", current_path()/"a"/"b", true));
|
||||
//BOOST_TEST(path("..") == path_difference(path(""), path(".."), true));
|
||||
BOOST_TEST("../.."/current_path().parent_path().filename() ==
|
||||
BOOST_TEST(
|
||||
path("../a/b") ==
|
||||
path_difference(
|
||||
current_path() / "c", current_path() / "a" / "b", true));
|
||||
// BOOST_TEST(path("..") == path_difference(path(""), path(".."), true));
|
||||
BOOST_TEST(
|
||||
"../.." / current_path().parent_path().filename() ==
|
||||
path_difference(current_path(), current_path().parent_path(), true));
|
||||
BOOST_TEST(path("b") == path_difference(path("a/c/.."), path("a/b"), true));
|
||||
BOOST_TEST(path("b") == path_difference(path("b/c/../../a"), path("a/b"), true));
|
||||
BOOST_TEST(path("b") == path_difference(path("b/c/../../a"), path("d/f/../../a/b"), true));
|
||||
BOOST_TEST(path("../../x/a/b") == path_difference(path("b/c/../../a"), path("d/f/../../../x/a/b"), true));
|
||||
BOOST_TEST(
|
||||
path("b") == path_difference(path("b/c/../../a"), path("a/b"), true));
|
||||
BOOST_TEST(
|
||||
path("b") ==
|
||||
path_difference(path("b/c/../../a"), path("d/f/../../a/b"), true));
|
||||
BOOST_TEST(
|
||||
path("../../x/a/b") ==
|
||||
path_difference(path("b/c/../../a"), path("d/f/../../../x/a/b"), true));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main()
|
||||
{
|
||||
file_path_to_url_tests();
|
||||
dir_path_to_url_tests();
|
||||
path_difference_tests();
|
||||
|
||||
@@ -6,25 +6,22 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "post_process.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "post_process.hpp"
|
||||
|
||||
#define EXPECT_EXCEPTION(test, msg) \
|
||||
try { \
|
||||
test; \
|
||||
BOOST_ERROR(msg); \
|
||||
} \
|
||||
catch(quickbook::post_process_failure&) { \
|
||||
#define EXPECT_EXCEPTION(test, msg) \
|
||||
try { \
|
||||
test; \
|
||||
BOOST_ERROR(msg); \
|
||||
} catch (quickbook::post_process_failure&) { \
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
EXPECT_EXCEPTION(
|
||||
quickbook::post_process("</thing>"),
|
||||
"Succeeded with unbalanced tag");
|
||||
quickbook::post_process("</thing>"), "Succeeded with unbalanced tag");
|
||||
EXPECT_EXCEPTION(
|
||||
quickbook::post_process("<"),
|
||||
"Succeeded with badly formed tag");
|
||||
quickbook::post_process("<"), "Succeeded with badly formed tag");
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -6,46 +6,52 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "fwd.hpp"
|
||||
#include "files.hpp"
|
||||
#include "string_view.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/range/algorithm/find.hpp>
|
||||
#include "files.hpp"
|
||||
#include "fwd.hpp"
|
||||
#include "string_view.hpp"
|
||||
|
||||
void simple_map_tests()
|
||||
{
|
||||
quickbook::string_view source("First Line\nSecond Line");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
|
||||
quickbook::string_iterator line1 = fake_file->source().begin();
|
||||
quickbook::string_iterator line1_end = boost::find(fake_file->source(), '\n');
|
||||
quickbook::string_iterator line1_end =
|
||||
boost::find(fake_file->source(), '\n');
|
||||
quickbook::string_iterator line2 = line1_end + 1;
|
||||
quickbook::string_iterator line2_end = fake_file->source().end();
|
||||
|
||||
quickbook::mapped_file_builder builder;
|
||||
|
||||
|
||||
{ // Empty test
|
||||
builder.start(fake_file);
|
||||
BOOST_TEST(builder.empty());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST(f1->source().empty());
|
||||
}
|
||||
|
||||
|
||||
{ // Add full text
|
||||
builder.start(fake_file);
|
||||
builder.add(quickbook::string_view(line1, line2_end - line1));
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(), source);
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(1,3));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line1_end - line1)),
|
||||
quickbook::file_position(1,line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2 - line1)),
|
||||
quickbook::file_position(2,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(1, 3));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line1_end - line1)),
|
||||
quickbook::file_position(1, line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line2 - line1)),
|
||||
quickbook::file_position(2, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
fake_file->position_of(fake_file->source().end()));
|
||||
}
|
||||
|
||||
@@ -53,14 +59,18 @@ void simple_map_tests()
|
||||
builder.start(fake_file);
|
||||
builder.add(quickbook::string_view(line1, line1_end - line1));
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(),
|
||||
quickbook::string_view(source.begin(), line1_end - line1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(1,3));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(1,line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(1, 3));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(1, line1_end - line1 + 1));
|
||||
}
|
||||
|
||||
{ // Add second line
|
||||
@@ -68,12 +78,15 @@ void simple_map_tests()
|
||||
builder.add(quickbook::string_view(line2, line2_end - line2));
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(), quickbook::string_view("Second Line"));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(2,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(2,3));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(2,line2_end - line2 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(2, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(2, 3));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(2, line2_end - line2 + 1));
|
||||
}
|
||||
|
||||
{ // Out of order
|
||||
@@ -82,21 +95,27 @@ void simple_map_tests()
|
||||
builder.add(quickbook::string_view(line1_end, 1));
|
||||
builder.add(quickbook::string_view(line1, line1_end - line1));
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Second Line\nFirst Line"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Second Line\nFirst Line"));
|
||||
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(2,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(2,3));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 - 1)),
|
||||
quickbook::file_position(2,line2_end - line2));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2)),
|
||||
quickbook::file_position(1,(line1_end - line1 + 1)));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 + 1)),
|
||||
quickbook::file_position(1,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(1,line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(2, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(2, 3));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line2_end - line2 - 1)),
|
||||
quickbook::file_position(2, line2_end - line2));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line2_end - line2)),
|
||||
quickbook::file_position(1, (line1_end - line1 + 1)));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line2_end - line2 + 1)),
|
||||
quickbook::file_position(1, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(1, line1_end - line1 + 1));
|
||||
}
|
||||
|
||||
{ // Repeated text
|
||||
@@ -105,84 +124,100 @@ void simple_map_tests()
|
||||
builder.add(quickbook::string_view(line1_end, 1));
|
||||
builder.add(quickbook::string_view(line2, line2_end - line2));
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Second Line\nSecond Line"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Second Line\nSecond Line"));
|
||||
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(2,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(2,3));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 - 1)),
|
||||
quickbook::file_position(2,line2_end - line2));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2)),
|
||||
quickbook::file_position(1,(line1_end - line1 + 1)));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + (line2_end - line2 + 1)),
|
||||
quickbook::file_position(2,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(2,line2_end - line2 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(2, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(2, 3));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line2_end - line2 - 1)),
|
||||
quickbook::file_position(2, line2_end - line2));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line2_end - line2)),
|
||||
quickbook::file_position(1, (line1_end - line1 + 1)));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + (line2_end - line2 + 1)),
|
||||
quickbook::file_position(2, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(2, line2_end - line2 + 1));
|
||||
}
|
||||
|
||||
|
||||
{ // Generated text
|
||||
builder.start(fake_file);
|
||||
builder.add_at_pos("------\n", line1);
|
||||
builder.add(quickbook::string_view(line1, line1_end - line1));
|
||||
builder.add_at_pos("\n------\n", line1_end);
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(),
|
||||
quickbook::string_view("------\nFirst Line\n------\n"));
|
||||
|
||||
|
||||
quickbook::string_iterator newline = boost::find(f1->source(), '\n');
|
||||
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(1,1));
|
||||
BOOST_TEST_EQ(f1->position_of(newline),
|
||||
quickbook::file_position(1,1));
|
||||
BOOST_TEST_EQ(f1->position_of(newline + 1),
|
||||
quickbook::file_position(1,1));
|
||||
BOOST_TEST_EQ(f1->position_of(newline + 2),
|
||||
quickbook::file_position(1,2));
|
||||
BOOST_TEST_EQ(f1->position_of(newline + (line1_end - line1)),
|
||||
quickbook::file_position(1,line1_end - line1));
|
||||
BOOST_TEST_EQ(f1->position_of(newline + (line1_end - line1 + 1)),
|
||||
quickbook::file_position(1,line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(f1->position_of(newline + (line1_end - line1 + 2)),
|
||||
quickbook::file_position(1,line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(1,line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 2),
|
||||
quickbook::file_position(1, 1));
|
||||
BOOST_TEST_EQ(f1->position_of(newline), quickbook::file_position(1, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(newline + 1), quickbook::file_position(1, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(newline + 2), quickbook::file_position(1, 2));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(newline + (line1_end - line1)),
|
||||
quickbook::file_position(1, line1_end - line1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(newline + (line1_end - line1 + 1)),
|
||||
quickbook::file_position(1, line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(newline + (line1_end - line1 + 2)),
|
||||
quickbook::file_position(1, line1_end - line1 + 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(1, line1_end - line1 + 1));
|
||||
}
|
||||
}
|
||||
|
||||
void indented_map_tests()
|
||||
{
|
||||
quickbook::string_view source(
|
||||
" Code line1\n"
|
||||
" Code line2\n");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::string_view source(" Code line1\n"
|
||||
" Code line2\n");
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
|
||||
quickbook::mapped_file_builder builder;
|
||||
|
||||
|
||||
{
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\nCode line2\n"));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1,4));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1,5));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1,9));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1,14));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2,4));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(3,1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Code line1\nCode line2\n"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1, 4));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1, 5));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1, 9));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1, 14));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2, 4));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(3, 1));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -195,20 +230,26 @@ void indented_map_tests()
|
||||
}
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\nCode line2\n"));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1,4));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1,5));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1,9));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1,14));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2,4));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(3,1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Code line1\nCode line2\n"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1, 4));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1, 5));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1, 9));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1, 14));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2, 4));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(3, 1));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -217,52 +258,64 @@ void indented_map_tests()
|
||||
fake_file->source().begin() + 3,
|
||||
fake_file->source().end() - (fake_file->source().begin() + 3)));
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(),
|
||||
quickbook::string_view("Code line1\n Code line2\n"));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1,4));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1,5));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1,9));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1,14));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(3,1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1, 4));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1, 5));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1, 9));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1, 14));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().end()),
|
||||
quickbook::file_position(3, 1));
|
||||
}
|
||||
}
|
||||
|
||||
void indented_map_tests2()
|
||||
{
|
||||
quickbook::string_view source(
|
||||
" Code line1\n"
|
||||
"\n"
|
||||
" Code line2\n");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::string_view source(" Code line1\n"
|
||||
"\n"
|
||||
" Code line2\n");
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
|
||||
quickbook::mapped_file_builder builder;
|
||||
|
||||
|
||||
{
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\n\nCode line2\n"));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1,4));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1,5));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1,9));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1,14));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2,1));
|
||||
BOOST_TEST_EQ(f1->position_of(f1->source().begin() + 12),
|
||||
quickbook::file_position(3,4));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Code line1\n\nCode line2\n"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin()),
|
||||
quickbook::file_position(1, 4));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 1),
|
||||
quickbook::file_position(1, 5));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 5),
|
||||
quickbook::file_position(1, 9));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 10),
|
||||
quickbook::file_position(1, 14));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 11),
|
||||
quickbook::file_position(2, 1));
|
||||
BOOST_TEST_EQ(
|
||||
f1->position_of(f1->source().begin() + 12),
|
||||
quickbook::file_position(3, 4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,35 +325,33 @@ void indented_map_leading_blanks_test()
|
||||
|
||||
{
|
||||
quickbook::string_view source("\n\n Code line1\n");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\n"));
|
||||
BOOST_TEST_EQ(f1->source(), quickbook::string_view("Code line1\n"));
|
||||
}
|
||||
|
||||
{
|
||||
quickbook::string_view source(" \n \n Code line1\n");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\n"));
|
||||
BOOST_TEST_EQ(f1->source(), quickbook::string_view("Code line1\n"));
|
||||
}
|
||||
|
||||
{
|
||||
quickbook::string_view source(" Code line1\n \n Code line2");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\n\nCode line2"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Code line1\n\nCode line2"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,37 +361,34 @@ void indented_map_trailing_blanks_test()
|
||||
|
||||
{
|
||||
quickbook::string_view source("\n\n Code line1\n ");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\n"));
|
||||
BOOST_TEST_EQ(f1->source(), quickbook::string_view("Code line1\n"));
|
||||
}
|
||||
|
||||
{
|
||||
quickbook::string_view source(" \n \n Code line1\n ");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\n "));
|
||||
BOOST_TEST_EQ(f1->source(), quickbook::string_view("Code line1\n "));
|
||||
}
|
||||
|
||||
{
|
||||
quickbook::string_view source(" Code line1\n \n Code line2\n ");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line1\n\nCode line2\n"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Code line1\n\nCode line2\n"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void indented_map_mixed_test()
|
||||
@@ -348,40 +396,42 @@ void indented_map_mixed_test()
|
||||
quickbook::mapped_file_builder builder;
|
||||
|
||||
{
|
||||
quickbook::string_view source("\tCode line 1\n Code line 2\n\t Code line 3\n \tCode line 4");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::string_view source("\tCode line 1\n Code line 2\n\t "
|
||||
"Code line 3\n \tCode line 4");
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line 1\nCode line 2\n Code line 3\n Code line 4"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(),
|
||||
quickbook::string_view(
|
||||
"Code line 1\nCode line 2\n Code line 3\n Code line 4"));
|
||||
}
|
||||
|
||||
{
|
||||
quickbook::string_view source(" Code line 1\n\tCode line 2");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line 1\n Code line 2"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Code line 1\n Code line 2"));
|
||||
}
|
||||
|
||||
{
|
||||
quickbook::string_view source(" Code line 1\n \tCode line 2");
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
builder.start(fake_file);
|
||||
builder.unindent_and_add(fake_file->source());
|
||||
quickbook::file_ptr f1 = builder.release();
|
||||
BOOST_TEST_EQ(f1->source(),
|
||||
quickbook::string_view("Code line 1\n\tCode line 2"));
|
||||
BOOST_TEST_EQ(
|
||||
f1->source(), quickbook::string_view("Code line 1\n\tCode line 2"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
simple_map_tests();
|
||||
|
||||
@@ -12,22 +12,23 @@
|
||||
#include "symbols.hpp"
|
||||
|
||||
typedef char char_type;
|
||||
typedef char const * iterator;
|
||||
typedef char const* iterator;
|
||||
|
||||
char_type data_[] = "whatever";
|
||||
|
||||
iterator begin = data_;
|
||||
iterator end = data_
|
||||
+ sizeof(data_)/sizeof(char_type); // Yes, this is an intentional bug ;)
|
||||
iterator end =
|
||||
data_ +
|
||||
sizeof(data_) / sizeof(char_type); // Yes, this is an intentional bug ;)
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef BOOST_SPIRIT_CLASSIC_NS::scanner<> scanner;
|
||||
typedef quickbook::tst<void *, char_type> symbols;
|
||||
typedef quickbook::tst<void*, char_type> symbols;
|
||||
|
||||
symbols symbols_;
|
||||
|
||||
symbols_.add(begin, end - 1, (void*) boost::addressof(symbols_));
|
||||
symbols_.add(begin, end - 1, (void*)boost::addressof(symbols_));
|
||||
|
||||
// The symbol table parser should not choke on input containing the null
|
||||
// character.
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/spirit/include/classic_core.hpp>
|
||||
#include <boost/spirit/include/classic_symbols.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/swap.hpp>
|
||||
#include "symbols.hpp"
|
||||
|
||||
@@ -22,12 +21,9 @@ using namespace BOOST_SPIRIT_CLASSIC_NS;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename IteratorT>
|
||||
bool
|
||||
equal(IteratorT p, IteratorT q)
|
||||
template <typename IteratorT> bool equal(IteratorT p, IteratorT q)
|
||||
{
|
||||
while (*p && *p == *q)
|
||||
{
|
||||
while (*p && *p == *q) {
|
||||
++p;
|
||||
++q;
|
||||
}
|
||||
@@ -35,85 +31,71 @@ equal(IteratorT p, IteratorT q)
|
||||
}
|
||||
|
||||
template <class SymbolsT, typename CharT>
|
||||
void
|
||||
docheck
|
||||
(
|
||||
SymbolsT const &sym,
|
||||
CharT const *candidate,
|
||||
bool hit,
|
||||
CharT const *result,
|
||||
int length
|
||||
)
|
||||
void docheck(
|
||||
SymbolsT const& sym,
|
||||
CharT const* candidate,
|
||||
bool hit,
|
||||
CharT const* result,
|
||||
int length)
|
||||
{
|
||||
parse_info<CharT const*> info = parse(candidate, sym);
|
||||
|
||||
#define correctly_matched hit == info.hit
|
||||
#define correct_match_length unsigned(length) == info.length
|
||||
#define correct_tail equal(candidate + (hit?1:0)*length, result)
|
||||
#define correct_tail equal(candidate + (hit ? 1 : 0) * length, result)
|
||||
|
||||
BOOST_TEST(correctly_matched);
|
||||
|
||||
if (hit)
|
||||
{
|
||||
if (hit) {
|
||||
BOOST_TEST(correct_match_length);
|
||||
BOOST_TEST(correct_tail);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
BOOST_TEST(correct_tail);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct store_action
|
||||
template <typename T> struct store_action
|
||||
{
|
||||
store_action(T const &v) : value(v) {}
|
||||
void operator()(T &v) const { v = value; }
|
||||
private:
|
||||
store_action(T const& v) : value(v) {}
|
||||
void operator()(T& v) const { v = value; }
|
||||
|
||||
private:
|
||||
T const value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
store_action<T>
|
||||
store(T const &v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
template <typename T> store_action<T> store(T const& v) { return v; }
|
||||
|
||||
template <typename T>
|
||||
struct check_action
|
||||
template <typename T> struct check_action
|
||||
{
|
||||
check_action(T const &v) : value(v) {}
|
||||
check_action(T const& v) : value(v) {}
|
||||
|
||||
#define correct_value_stored (v==value)
|
||||
void operator()(T const &v) const { BOOST_TEST(correct_value_stored); }
|
||||
private:
|
||||
#define correct_value_stored (v == value)
|
||||
void operator()(T const& v) const { BOOST_TEST(correct_value_stored); }
|
||||
|
||||
private:
|
||||
T const value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
check_action<T>
|
||||
docheck(T const &v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
template <typename T> check_action<T> docheck(T const& v) { return v; }
|
||||
|
||||
static void
|
||||
default_constructible()
|
||||
{ // this actually a compile time test
|
||||
static void default_constructible()
|
||||
{ // this actually a compile time test
|
||||
symbols<int, char, quickbook::tst<int, char> > ns1;
|
||||
symbols<int, wchar_t, quickbook::tst<int, wchar_t> > ws1;
|
||||
symbols<std::string, char, quickbook::tst<std::string, char> > ns2;
|
||||
symbols<std::string, wchar_t, quickbook::tst<std::string, wchar_t> > ws2;
|
||||
|
||||
(void)ns1; (void)ws1; (void)ns2; (void)ws2;
|
||||
(void)ns1;
|
||||
(void)ws1;
|
||||
(void)ns2;
|
||||
(void)ws2;
|
||||
}
|
||||
|
||||
typedef symbols<int, char, quickbook::tst<int, char> > nsymbols;
|
||||
typedef symbols<int, wchar_t, quickbook::tst<int, wchar_t> > wsymbols;
|
||||
|
||||
static void
|
||||
narrow_match_tests()
|
||||
static void narrow_match_tests()
|
||||
{
|
||||
nsymbols sym;
|
||||
sym = "pineapple", "orange", "banana", "applepie", "apple";
|
||||
@@ -142,8 +124,7 @@ narrow_match_tests()
|
||||
docheck(sym, "applepix", true, "pix", 5);
|
||||
}
|
||||
|
||||
static void
|
||||
narrow_copy_ctor_tests()
|
||||
static void narrow_copy_ctor_tests()
|
||||
{
|
||||
nsymbols sym;
|
||||
sym = "pineapple", "orange", "banana", "applepie", "apple";
|
||||
@@ -154,8 +135,7 @@ narrow_copy_ctor_tests()
|
||||
docheck(sym2, "bananarama", true, "rama", 6);
|
||||
}
|
||||
|
||||
static void
|
||||
narrow_assigment_operator_tests()
|
||||
static void narrow_assigment_operator_tests()
|
||||
{
|
||||
nsymbols sym;
|
||||
sym = "pineapple", "orange", "banana", "applepie", "apple";
|
||||
@@ -168,8 +148,7 @@ narrow_assigment_operator_tests()
|
||||
docheck(sym2, "bananarama", true, "rama", 6);
|
||||
}
|
||||
|
||||
static void
|
||||
narrow_swap_tests()
|
||||
static void narrow_swap_tests()
|
||||
{
|
||||
nsymbols sym, sym2;
|
||||
sym = "pineapple", "orange", "banana", "applepie", "apple";
|
||||
@@ -184,13 +163,12 @@ narrow_swap_tests()
|
||||
docheck(sym, "cauliflour", false, "cauliflour", -1);
|
||||
}
|
||||
|
||||
static void
|
||||
narrow_value_tests()
|
||||
{ // also tests the add member functions
|
||||
static void narrow_value_tests()
|
||||
{ // also tests the add member functions
|
||||
nsymbols sym;
|
||||
|
||||
sym = "orange", "banana";
|
||||
sym.add("pineapple",1234);
|
||||
sym.add("pineapple", 1234);
|
||||
sym.add("lemon");
|
||||
|
||||
parse("orange", sym[store(12345)]);
|
||||
@@ -200,19 +178,18 @@ narrow_value_tests()
|
||||
parse("lemon", sym[docheck(int())]);
|
||||
}
|
||||
|
||||
static void
|
||||
narrow_free_functions_tests()
|
||||
static void narrow_free_functions_tests()
|
||||
{
|
||||
nsymbols sym;
|
||||
|
||||
#define add_returned_non_null_value (res!=0)
|
||||
#define add_returned_null (res==0)
|
||||
#define find_returned_non_null_value (res!=0)
|
||||
#define find_returned_null (res==0)
|
||||
#define add_returned_non_null_value (res != 0)
|
||||
#define add_returned_null (res == 0)
|
||||
#define find_returned_non_null_value (res != 0)
|
||||
#define find_returned_null (res == 0)
|
||||
|
||||
int *res = add(sym,"pineapple");
|
||||
int* res = add(sym, "pineapple");
|
||||
BOOST_TEST(add_returned_non_null_value);
|
||||
res = add(sym,"pineapple");
|
||||
res = add(sym, "pineapple");
|
||||
BOOST_TEST(add_returned_null);
|
||||
|
||||
res = find(sym, "pineapple");
|
||||
@@ -221,8 +198,7 @@ narrow_free_functions_tests()
|
||||
BOOST_TEST(find_returned_null);
|
||||
}
|
||||
|
||||
static void
|
||||
wide_match_tests()
|
||||
static void wide_match_tests()
|
||||
{
|
||||
wsymbols sym;
|
||||
sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
|
||||
@@ -251,8 +227,7 @@ wide_match_tests()
|
||||
docheck(sym, L"applepix", true, L"pix", 5);
|
||||
}
|
||||
|
||||
static void
|
||||
wide_copy_ctor_tests()
|
||||
static void wide_copy_ctor_tests()
|
||||
{
|
||||
wsymbols sym;
|
||||
sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
|
||||
@@ -263,8 +238,7 @@ wide_copy_ctor_tests()
|
||||
docheck(sym2, L"bananarama", true, L"rama", 6);
|
||||
}
|
||||
|
||||
static void
|
||||
wide_assigment_operator_tests()
|
||||
static void wide_assigment_operator_tests()
|
||||
{
|
||||
wsymbols sym;
|
||||
sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
|
||||
@@ -277,8 +251,7 @@ wide_assigment_operator_tests()
|
||||
docheck(sym2, L"bananarama", true, L"rama", 6);
|
||||
}
|
||||
|
||||
static void
|
||||
wide_swap_tests()
|
||||
static void wide_swap_tests()
|
||||
{
|
||||
wsymbols sym, sym2;
|
||||
sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
|
||||
@@ -293,13 +266,12 @@ wide_swap_tests()
|
||||
docheck(sym, L"cauliflour", false, L"cauliflour", -1);
|
||||
}
|
||||
|
||||
static void
|
||||
wide_value_tests()
|
||||
{ // also tests the add member functions
|
||||
static void wide_value_tests()
|
||||
{ // also tests the add member functions
|
||||
wsymbols sym;
|
||||
|
||||
sym = L"orange", L"banana";
|
||||
sym.add(L"pineapple",1234);
|
||||
sym.add(L"pineapple", 1234);
|
||||
sym.add(L"lemon");
|
||||
|
||||
parse(L"orange", sym[store(12345)]);
|
||||
@@ -309,14 +281,13 @@ wide_value_tests()
|
||||
parse(L"lemon", sym[docheck(int())]);
|
||||
}
|
||||
|
||||
static void
|
||||
wide_free_functions_tests()
|
||||
static void wide_free_functions_tests()
|
||||
{
|
||||
wsymbols sym;
|
||||
|
||||
int *res = add(sym,L"pineapple");
|
||||
int* res = add(sym, L"pineapple");
|
||||
BOOST_TEST(add_returned_non_null_value);
|
||||
res = add(sym,L"pineapple");
|
||||
res = add(sym, L"pineapple");
|
||||
BOOST_TEST(add_returned_null);
|
||||
|
||||
res = find(sym, L"pineapple");
|
||||
@@ -325,8 +296,7 @@ wide_free_functions_tests()
|
||||
BOOST_TEST(find_returned_null);
|
||||
}
|
||||
|
||||
static
|
||||
void free_add_find_functions_tests()
|
||||
static void free_add_find_functions_tests()
|
||||
{
|
||||
nsymbols sym;
|
||||
BOOST_TEST(*add(sym, "a", 0) == 0);
|
||||
@@ -343,18 +313,17 @@ void free_add_find_functions_tests()
|
||||
|
||||
struct check_parse_value
|
||||
{
|
||||
explicit check_parse_value(int value) : value_(value){}
|
||||
|
||||
explicit check_parse_value(int value) : value_(value) {}
|
||||
|
||||
void operator()(int value) const { BOOST_TEST(value == value_); }
|
||||
|
||||
|
||||
int value_;
|
||||
};
|
||||
|
||||
// My version is different to the original, if there's an existing value
|
||||
// it replaces it with the new one.
|
||||
|
||||
static
|
||||
void duplicate_add_tests()
|
||||
static void duplicate_add_tests()
|
||||
{
|
||||
char const* foo1 = "foo";
|
||||
char const* foo2 = foo1 + 3;
|
||||
@@ -364,7 +333,7 @@ void duplicate_add_tests()
|
||||
nsymbols sym2 = sym;
|
||||
sym.add(foo1, foo2, 2);
|
||||
sym2.add(foo1, foo2, 3);
|
||||
|
||||
|
||||
BOOST_TEST(find(sym, "foo") && *find(sym, "foo") == 2);
|
||||
BOOST_TEST(find(sym2, "foo") && *find(sym2, "foo") == 3);
|
||||
|
||||
@@ -383,8 +352,7 @@ void duplicate_add_tests()
|
||||
BOOST_TEST(info.hit && info.length == 3);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
int main()
|
||||
{
|
||||
default_constructible();
|
||||
narrow_match_tests();
|
||||
|
||||
@@ -7,29 +7,35 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
#include "utils.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "utils.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void linkify_test() {
|
||||
void linkify_test()
|
||||
{
|
||||
using quickbook::detail::linkify;
|
||||
|
||||
BOOST_TEST(linkify("abc", "link") == "<link linkend=\"link\">abc</link>");
|
||||
BOOST_TEST(linkify("<link linkend=\"something\">abc</link>", "link") ==
|
||||
BOOST_TEST(
|
||||
linkify("<link linkend=\"something\">abc</link>", "link") ==
|
||||
"<link linkend=\"something\">abc</link>");
|
||||
BOOST_TEST(linkify("abc <link linkend=\"something\">def</link>", "link") ==
|
||||
BOOST_TEST(
|
||||
linkify("abc <link linkend=\"something\">def</link>", "link") ==
|
||||
"abc <link linkend=\"something\">def</link>");
|
||||
BOOST_TEST(linkify("<link linkend=\"something\">abc</link> def", "link") ==
|
||||
BOOST_TEST(
|
||||
linkify("<link linkend=\"something\">abc</link> def", "link") ==
|
||||
"<link linkend=\"something\">abc</link> def");
|
||||
}
|
||||
|
||||
void encode_string_test() {
|
||||
void encode_string_test()
|
||||
{
|
||||
using quickbook::detail::encode_string;
|
||||
BOOST_TEST_EQ(std::string("<A&B>"), encode_string("<A&B>"));
|
||||
}
|
||||
|
||||
void escape_uri_test() {
|
||||
void escape_uri_test()
|
||||
{
|
||||
using quickbook::detail::escape_uri;
|
||||
using quickbook::detail::partially_escape_uri;
|
||||
|
||||
@@ -37,7 +43,8 @@ void escape_uri_test() {
|
||||
BOOST_TEST_EQ(std::string("%20%25%25"), partially_escape_uri("%20%25%"));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main()
|
||||
{
|
||||
linkify_test();
|
||||
encode_string_test();
|
||||
escape_uri_test();
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
// Some very light testing for quickbook::value and friends.
|
||||
// Just for a few issues that came up during development.
|
||||
|
||||
#include <vector>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/range/algorithm/equal.hpp>
|
||||
#include <vector>
|
||||
#include "values.hpp"
|
||||
#include "files.hpp"
|
||||
#include "values.hpp"
|
||||
|
||||
void empty_tests()
|
||||
{
|
||||
@@ -28,12 +28,10 @@ void qbk_tests()
|
||||
std::string source = "Source";
|
||||
quickbook::value q;
|
||||
{
|
||||
quickbook::file_ptr fake_file = new quickbook::file(
|
||||
"(fake file)", source, 105u);
|
||||
quickbook::file_ptr fake_file =
|
||||
new quickbook::file("(fake file)", source, 105u);
|
||||
q = quickbook::qbk_value(
|
||||
fake_file,
|
||||
fake_file->source().begin(),
|
||||
fake_file->source().end());
|
||||
fake_file, fake_file->source().begin(), fake_file->source().end());
|
||||
}
|
||||
BOOST_TEST_EQ(q.get_quickbook(), quickbook::string_view(source));
|
||||
}
|
||||
@@ -46,12 +44,16 @@ void sort_test()
|
||||
b.insert(quickbook::encoded_value("c", 5));
|
||||
b.insert(quickbook::encoded_value("d", 8));
|
||||
b.sort_list();
|
||||
|
||||
|
||||
quickbook::value_consumer c = b.release();
|
||||
BOOST_TEST(c.check(2)); BOOST_TEST_EQ(c.consume(2).get_encoded(), "b");
|
||||
BOOST_TEST(c.check(5)); c.consume(5);
|
||||
BOOST_TEST(c.check(8)); c.consume(8);
|
||||
BOOST_TEST(c.check(10)); c.consume(10);
|
||||
BOOST_TEST(c.check(2));
|
||||
BOOST_TEST_EQ(c.consume(2).get_encoded(), "b");
|
||||
BOOST_TEST(c.check(5));
|
||||
c.consume(5);
|
||||
BOOST_TEST(c.check(8));
|
||||
c.consume(8);
|
||||
BOOST_TEST(c.check(10));
|
||||
c.consume(10);
|
||||
BOOST_TEST(!c.check());
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ void equality_tests()
|
||||
|
||||
quickbook::value_builder builder;
|
||||
quickbook::value nil;
|
||||
|
||||
|
||||
// 0: nil
|
||||
distinct_values.push_back(nil);
|
||||
|
||||
@@ -103,12 +105,12 @@ void equality_tests()
|
||||
builder.insert(nil);
|
||||
distinct_values.push_back(builder.release());
|
||||
|
||||
for(std::size_t i = 0; i < distinct_values.size(); ++i) {
|
||||
for(std::size_t j = 0; j < distinct_values.size(); ++j) {
|
||||
for (std::size_t i = 0; i < distinct_values.size(); ++i) {
|
||||
for (std::size_t j = 0; j < distinct_values.size(); ++j) {
|
||||
if ((i == j) != (distinct_values[i] == distinct_values[j])) {
|
||||
BOOST_ERROR("Value mismatch.");
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM
|
||||
<< "\tat " << i << ", " << j << std::endl;
|
||||
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\tat " << i << ", " << j
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user