1 /*=============================================================================
2     Copyright (c) 2011-2013 Daniel James
3 
4     Use, modification and distribution is subject to the Boost Software
5     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6     http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 
9 #if !defined(BOOST_QUICKBOOK_DOCUMENT_STATE_IMPL_HPP)
10 #define BOOST_QUICKBOOK_DOCUMENT_STATE_IMPL_HPP
11 
12 #include "document_state.hpp"
13 #include "phrase_tags.hpp"
14 #include "utils.hpp"
15 #include <boost/utility/string_ref.hpp>
16 #include <boost/shared_ptr.hpp>
17 #include <deque>
18 #include <string>
19 #include <vector>
20 
21 namespace quickbook
22 {
23     //
24     // id_placeholder
25     //
26     // When generating the xml, quickbook can't allocate the identifiers until
27     // the end, so it stores in the intermedia xml a placeholder string,
28     // e.g. id="$1". This represents one of these placeholders.
29     //
30 
31     struct id_placeholder
32     {
33         unsigned index;         // The index in document_state_impl::placeholders.
34                                 // Use for the dollar identifiers in
35                                 // intermediate xml.
36         std::string unresolved_id;
37                                 // The id that would be generated
38                                 // without any duplicate handling.
39                                 // Used for generating old style header anchors.
40         std::string id;         // The node id.
41         id_placeholder const* parent;
42                                 // Placeholder of the parent id.
43         id_category category;
44         unsigned num_dots;      // Number of dots in the id.
45                                 // Normally equal to the section level
46                                 // but not when an explicit id contains
47                                 // dots.
48 
49         id_placeholder(unsigned index, boost::string_ref id,
50                 id_category category, id_placeholder const* parent_);
51 
52         std::string to_string() const;
53     };
54 
55     //
56     // document_state_impl
57     //
58     // Contains all the data tracked by document_state.
59     //
60 
61     struct file_info;
62     struct doc_info;
63     struct section_info;
64 
65     struct document_state_impl
66     {
67         boost::shared_ptr<file_info> current_file;
68         std::deque<id_placeholder> placeholders;
69 
70         // Placeholder methods
71 
72         id_placeholder const* add_placeholder(boost::string_ref, id_category,
73             id_placeholder const* parent = 0);
74 
75         id_placeholder const* get_placeholder(boost::string_ref) const;
76 
77         id_placeholder const* get_id_placeholder(
78                 boost::shared_ptr<section_info> const& section) const;
79 
80         // Events
81 
82         id_placeholder const* start_file(
83                 unsigned compatibility_version,
84                 bool document_root,
85                 boost::string_ref include_doc_id,
86                 boost::string_ref id,
87                 value const& title);
88 
89         void end_file();
90 
91         id_placeholder const* add_id(
92                 boost::string_ref id,
93                 id_category category);
94         id_placeholder const* old_style_id(
95             boost::string_ref id,
96             id_category category);
97         id_placeholder const* begin_section(
98                 boost::string_ref id,
99                 id_category category,
100                 source_mode_info const&);
101         void end_section();
102 
103     private:
104         id_placeholder const* add_id_to_section(
105                 boost::string_ref id,
106                 id_category category,
107                 boost::shared_ptr<section_info> const& section);
108         id_placeholder const* create_new_section(
109                 boost::string_ref id,
110                 id_category category,
111                 source_mode_info const&);
112     };
113 
114     std::string replace_ids(document_state_impl const& state, boost::string_ref xml,
115             std::vector<std::string> const* = 0);
116     std::vector<std::string> generate_ids(document_state_impl const&, boost::string_ref);
117 
118     std::string normalize_id(boost::string_ref src_id);
119     std::string normalize_id(boost::string_ref src_id, std::size_t);
120 
121     //
122     // Xml subset parser used for finding id values.
123     //
124     // I originally tried to integrate this into the post processor
125     // but that proved tricky. Alternatively it could use a proper
126     // xml parser, but I want this to be able to survive badly
127     // marked up escapes.
128     //
129 
130     struct xml_processor
131     {
132         xml_processor();
133 
134         std::vector<std::string> id_attributes;
135 
136         struct callback {
startquickbook::xml_processor::callback137             virtual void start(boost::string_ref) {}
id_valuequickbook::xml_processor::callback138             virtual void id_value(boost::string_ref) {}
finishquickbook::xml_processor::callback139             virtual void finish(boost::string_ref) {}
~callbackquickbook::xml_processor::callback140             virtual ~callback() {}
141         };
142 
143         void parse(boost::string_ref, callback&);
144     };
145 }
146 
147 #endif
148