summaryrefslogtreecommitdiff
path: root/tools/quickbook/src/document_state_impl.hpp
blob: e9258e3b11bd10f5d3f9bc1b195ba5a44cb0132e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*=============================================================================
    Copyright (c) 2011-2013 Daniel James

    Use, modification and distribution is subject to the Boost Software
    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

#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 <boost/utility/string_ref.hpp>
#include <boost/shared_ptr.hpp>
#include <deque>
#include <string>
#include <vector>

namespace quickbook
{
    //
    // id_placeholder
    //
    // When generating the xml, quickbook can't allocate the identifiers until
    // the end, so it stores in the intermedia xml a placeholder string,
    // e.g. id="$1". This represents one of these placeholders.
    //

    struct id_placeholder
    {
        unsigned index;         // The index in document_state_impl::placeholders.
                                // Use for the dollar identifiers in
                                // intermediate xml.
        std::string unresolved_id;
                                // The id that would be generated
                                // without any duplicate handling.
                                // Used for generating old style header anchors.
        std::string id;         // The node id.
        id_placeholder const* parent;
                                // Placeholder of the parent id.
        id_category category;
        unsigned num_dots;      // Number of dots in the id.
                                // Normally equal to the section level
                                // but not when an explicit id contains
                                // dots.

        id_placeholder(unsigned index, boost::string_ref id,
                id_category category, id_placeholder const* parent_);

        std::string to_string() const;
    };

    //
    // document_state_impl
    //
    // Contains all the data tracked by document_state.
    //

    struct file_info;
    struct doc_info;
    struct section_info;

    struct document_state_impl
    {
        boost::shared_ptr<file_info> current_file;
        std::deque<id_placeholder> placeholders;

        // Placeholder methods

        id_placeholder const* add_placeholder(boost::string_ref, id_category,
            id_placeholder const* parent = 0);

        id_placeholder const* get_placeholder(boost::string_ref) const;

        id_placeholder const* get_id_placeholder(
                boost::shared_ptr<section_info> const& section) const;

        // Events

        id_placeholder const* start_file(
                unsigned compatibility_version,
                bool document_root,
                boost::string_ref include_doc_id,
                boost::string_ref id,
                value const& title);

        void end_file();

        id_placeholder const* add_id(
                boost::string_ref id,
                id_category category);
        id_placeholder const* old_style_id(
            boost::string_ref id,
            id_category category);
        id_placeholder const* begin_section(
                boost::string_ref id,
                id_category category,
                source_mode_info const&);
        void end_section();

    private:
        id_placeholder const* add_id_to_section(
                boost::string_ref id,
                id_category category,
                boost::shared_ptr<section_info> const& section);
        id_placeholder const* create_new_section(
                boost::string_ref id,
                id_category category,
                source_mode_info const&);
    };

    std::string replace_ids(document_state_impl const& state, boost::string_ref xml,
            std::vector<std::string> const* = 0);
    std::vector<std::string> generate_ids(document_state_impl const&, boost::string_ref);

    std::string normalize_id(boost::string_ref src_id);
    std::string normalize_id(boost::string_ref src_id, std::size_t);

    //
    // Xml subset parser used for finding id values.
    //
    // I originally tried to integrate this into the post processor
    // but that proved tricky. Alternatively it could use a proper
    // xml parser, but I want this to be able to survive badly
    // marked up escapes.
    //

    struct xml_processor
    {
        xml_processor();

        std::vector<std::string> id_attributes;

        struct callback {
            virtual void start(boost::string_ref) {}
            virtual void id_value(boost::string_ref) {}
            virtual void finish(boost::string_ref) {}
            virtual ~callback() {}
        };

        void parse(boost::string_ref, callback&);
    };
}

#endif