]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/quickbook/src/document_state.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / tools / quickbook / src / document_state.cpp
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 #include "document_state_impl.hpp"
10 #include "utils.hpp"
11 #include <boost/make_shared.hpp>
12 #include <boost/lexical_cast.hpp>
13 #include <boost/range/algorithm.hpp>
14 #include <cctype>
15
16 namespace quickbook
17 {
18 struct file_info
19 {
20 boost::shared_ptr<file_info> const parent;
21 boost::shared_ptr<doc_info> const document;
22
23 unsigned const compatibility_version;
24 unsigned const depth;
25 unsigned const override_depth;
26 id_placeholder const* const override_id;
27
28 // The 1.1-1.5 document id would actually change per file due to
29 // explicit ids in includes and a bug which would sometimes use the
30 // document title instead of the id.
31 std::string const doc_id_1_1;
32
33 // Constructor for files that aren't the root of a document.
34 explicit file_info(boost::shared_ptr<file_info> const& parent_,
35 unsigned compatibility_version_,
36 quickbook::string_view doc_id_1_1_,
37 id_placeholder const* override_id_) :
38 parent(parent_), document(parent->document),
39 compatibility_version(compatibility_version_),
40 depth(parent->depth + 1),
41 override_depth(override_id_ ? depth : parent->override_depth),
42 override_id(override_id_ ? override_id_ : parent->override_id),
43 doc_id_1_1(doc_id_1_1_.to_s())
44 {}
45
46 // Constructor for files that are the root of a document.
47 explicit file_info(boost::shared_ptr<file_info> const& parent_,
48 boost::shared_ptr<doc_info> const& document_,
49 unsigned compatibility_version_,
50 quickbook::string_view doc_id_1_1_) :
51 parent(parent_), document(document_),
52 compatibility_version(compatibility_version_),
53 depth(0), override_depth(0), override_id(0),
54 doc_id_1_1(doc_id_1_1_.to_s())
55 {}
56 };
57
58 struct doc_info
59 {
60 boost::shared_ptr<section_info> current_section;
61
62 // Note: these are mutable to remain bug compatible with old versions
63 // of quickbook. They would set these values at the start of new files
64 // and sections and then not restore them at the end.
65 std::string last_title_1_1;
66 std::string section_id_1_1;
67 };
68
69 struct section_info
70 {
71 boost::shared_ptr<section_info> const parent;
72 unsigned const compatibility_version;
73 unsigned const file_depth;
74 unsigned const level;
75
76 value const explicit_id;
77 std::string const id_1_1;
78 id_placeholder const* const placeholder_1_6;
79 source_mode_info const source_mode;
80
81 explicit section_info(boost::shared_ptr<section_info> const& parent_,
82 file_info const* current_file_,
83 value const& explicit_id_,
84 quickbook::string_view id_1_1_,
85 id_placeholder const* placeholder_1_6_,
86 source_mode_info const& source_mode_) :
87 parent(parent_),
88 compatibility_version(current_file_->compatibility_version),
89 file_depth(current_file_->depth),
90 level(parent ? parent->level + 1 : 1),
91 explicit_id(explicit_id_),
92 id_1_1(id_1_1_.to_s()),
93 placeholder_1_6(placeholder_1_6_),
94 source_mode(source_mode_) {}
95 };
96
97 //
98 // document_state
99 //
100
101 document_state::document_state()
102 : state(new document_state_impl)
103 {
104 }
105
106 document_state::~document_state() {}
107
108 void document_state::start_file(
109 unsigned compatibility_version_,
110 quickbook::string_view include_doc_id,
111 quickbook::string_view id,
112 value const& title_)
113 {
114 state->start_file(compatibility_version_, false, include_doc_id, id, title_);
115 }
116
117 std::string document_state::start_file_with_docinfo(
118 unsigned compatibility_version_,
119 quickbook::string_view include_doc_id,
120 quickbook::string_view id,
121 value const& title_)
122 {
123 return state->start_file(compatibility_version_, true, include_doc_id,
124 id, title_)->to_string();
125 }
126
127 void document_state::end_file()
128 {
129 state->end_file();
130 }
131
132 std::string document_state::begin_section(
133 value const& explicit_id_, quickbook::string_view id,
134 id_category category, source_mode_info const& source_mode)
135 {
136 return state->begin_section(explicit_id_, id, category, source_mode)
137 ->to_string();
138 }
139
140 void document_state::end_section()
141 {
142 return state->end_section();
143 }
144
145 int document_state::section_level() const
146 {
147 return state->current_file->document->current_section->level;
148 }
149
150 value const& document_state::explicit_id() const
151 {
152 return state->current_file->document->current_section->explicit_id;
153 }
154
155 source_mode_info document_state::section_source_mode() const
156 {
157 return state->current_file ?
158 state->current_file->document->current_section->source_mode :
159 source_mode_info();
160 }
161
162 std::string document_state::old_style_id(quickbook::string_view id, id_category category)
163 {
164 return state->old_style_id(id, category)->to_string();
165 }
166
167 std::string document_state::add_id(quickbook::string_view id, id_category category)
168 {
169 return state->add_id(id, category)->to_string();
170 }
171
172 std::string document_state::add_anchor(quickbook::string_view id, id_category category)
173 {
174 return state->add_placeholder(id, category)->to_string();
175 }
176
177 std::string document_state::replace_placeholders_with_unresolved_ids(
178 quickbook::string_view xml) const
179 {
180 return replace_ids(*state, xml);
181 }
182
183 std::string document_state::replace_placeholders(quickbook::string_view xml) const
184 {
185 assert(!state->current_file);
186 std::vector<std::string> ids = generate_ids(*state, xml);
187 return replace_ids(*state, xml, &ids);
188 }
189
190 unsigned document_state::compatibility_version() const
191 {
192 return state->current_file->compatibility_version;
193 }
194
195 //
196 // id_placeholder
197 //
198
199 id_placeholder::id_placeholder(
200 std::size_t index_,
201 quickbook::string_view id_,
202 id_category category_,
203 id_placeholder const* parent_)
204 : index(index_),
205 id(id_.begin(), id_.end()),
206 unresolved_id(parent_ ? parent_->unresolved_id + '.' + id : id),
207 parent(parent_),
208 category(category_),
209 num_dots(boost::range::count(id, '.') +
210 (parent_ ? parent_->num_dots + 1 : 0))
211 {
212 }
213
214 std::string id_placeholder::to_string() const
215 {
216 return '$' + boost::lexical_cast<std::string>(index);
217 }
218
219 //
220 // document_state_impl
221 //
222
223 id_placeholder const* document_state_impl::add_placeholder(
224 quickbook::string_view id, id_category category,
225 id_placeholder const* parent)
226 {
227 placeholders.push_back(id_placeholder(
228 placeholders.size(), id, category, parent));
229 return &placeholders.back();
230 }
231
232 id_placeholder const* document_state_impl::get_placeholder(quickbook::string_view value) const
233 {
234 // If this isn't a placeholder id.
235 if (value.size() <= 1 || *value.begin() != '$')
236 return 0;
237
238 unsigned index = boost::lexical_cast<unsigned>(std::string(
239 value.begin() + 1, value.end()));
240
241 return &placeholders.at(index);
242 }
243
244 id_placeholder const* document_state_impl::get_id_placeholder(
245 boost::shared_ptr<section_info> const& section) const
246 {
247 return !section ? 0 :
248 section->file_depth < current_file->override_depth ?
249 current_file->override_id : section->placeholder_1_6;
250 }
251
252 id_placeholder const* document_state_impl::start_file(
253 unsigned compatibility_version,
254 bool document_root,
255 quickbook::string_view include_doc_id,
256 quickbook::string_view id,
257 value const& title)
258 {
259 boost::shared_ptr<file_info> parent = current_file;
260 assert(parent || document_root);
261
262 boost::shared_ptr<doc_info> document =
263 document_root ? boost::make_shared<doc_info>() : parent->document;
264
265 // Choose specified id to use. Prefer 'include_doc_id' (the id
266 // specified in an 'include' element) unless backwards compatibility
267 // is required.
268
269 quickbook::string_view initial_doc_id;
270
271 if (document_root ||
272 compatibility_version >= 106u ||
273 parent->compatibility_version >= 106u)
274 {
275 initial_doc_id = !include_doc_id.empty() ? include_doc_id : id;
276 }
277 else {
278 initial_doc_id = !id.empty() ? id : include_doc_id;
279 }
280
281 // Work out this file's doc_id for older versions of quickbook.
282 // A bug meant that this need to be done per file, not per
283 // document.
284
285 std::string doc_id_1_1;
286
287 if (document_root || compatibility_version < 106u) {
288 if (title.check())
289 document->last_title_1_1 = title.get_quickbook().to_s();
290
291 doc_id_1_1 = !initial_doc_id.empty() ? initial_doc_id.to_s() :
292 detail::make_identifier(document->last_title_1_1);
293 }
294 else if (parent) {
295 doc_id_1_1 = parent->doc_id_1_1;
296 }
297
298 if (document_root) {
299 // Create new file
300
301 current_file = boost::make_shared<file_info>(parent,
302 document, compatibility_version, doc_id_1_1);
303
304 // Create a section for the new document.
305
306 source_mode_info default_source_mode;
307
308 if (!initial_doc_id.empty()) {
309 return create_new_section(empty_value(), id,
310 id_category::explicit_section_id, default_source_mode);
311 }
312 else if (!title.empty()) {
313 return create_new_section(empty_value(),
314 detail::make_identifier(title.get_quickbook()),
315 id_category::generated_doc, default_source_mode);
316 }
317 else if (compatibility_version >= 106u) {
318 return create_new_section(empty_value(), "doc",
319 id_category::numbered, default_source_mode);
320 }
321 else {
322 return create_new_section(empty_value(), "",
323 id_category::generated_doc, default_source_mode);
324 }
325 }
326 else {
327 // If an id was set for the file, then the file overrides the
328 // current section's id with this id.
329 //
330 // Don't do this for document_root as it will create a section
331 // for the document.
332 //
333 // Don't do this for older versions, as they use a different
334 // backwards compatible mechanism to handle file ids.
335
336 id_placeholder const* override_id = 0;
337
338 if (!initial_doc_id.empty() && compatibility_version >= 106u)
339 {
340 boost::shared_ptr<section_info> null_section;
341
342 override_id = add_id_to_section(initial_doc_id,
343 id_category::explicit_section_id, null_section);
344 }
345
346 // Create new file
347
348 current_file =
349 boost::make_shared<file_info>(parent, compatibility_version,
350 doc_id_1_1, override_id);
351
352 return 0;
353 }
354 }
355
356 void document_state_impl::end_file()
357 {
358 current_file = current_file->parent;
359 }
360
361 id_placeholder const* document_state_impl::add_id(
362 quickbook::string_view id,
363 id_category category)
364 {
365 return add_id_to_section(id, category,
366 current_file->document->current_section);
367 }
368
369 id_placeholder const* document_state_impl::add_id_to_section(
370 quickbook::string_view id,
371 id_category category,
372 boost::shared_ptr<section_info> const& section)
373 {
374 std::string id_part(id.begin(), id.end());
375
376 // Note: Normalizing id according to file compatibility version, but
377 // adding to section according to section compatibility version.
378
379 if (current_file->compatibility_version >= 106u &&
380 category.c < id_category::explicit_id) {
381 id_part = normalize_id(id);
382 }
383
384 id_placeholder const* placeholder_1_6 = get_id_placeholder(section);
385
386 if(!section || section->compatibility_version >= 106u) {
387 return add_placeholder(id_part, category, placeholder_1_6);
388 }
389 else {
390 std::string const& qualified_id = section->id_1_1;
391
392 std::string new_id;
393 if (!placeholder_1_6)
394 new_id = current_file->doc_id_1_1;
395 if (!new_id.empty() && !qualified_id.empty()) new_id += '.';
396 new_id += qualified_id;
397 if (!new_id.empty() && !id_part.empty()) new_id += '.';
398 new_id += id_part;
399
400 return add_placeholder(new_id, category, placeholder_1_6);
401 }
402 }
403
404 id_placeholder const* document_state_impl::old_style_id(
405 quickbook::string_view id,
406 id_category category)
407 {
408 return current_file->compatibility_version < 103u ?
409 add_placeholder(
410 current_file->document->section_id_1_1 + "." + id.to_s(), category) :
411 add_id(id, category);
412 }
413
414 id_placeholder const* document_state_impl::begin_section(
415 value const& explicit_id,
416 quickbook::string_view id,
417 id_category category,
418 source_mode_info const& source_mode)
419 {
420 current_file->document->section_id_1_1 = id.to_s();
421 return create_new_section(explicit_id, id, category, source_mode);
422 }
423
424 id_placeholder const* document_state_impl::create_new_section(
425 value const& explicit_id,
426 quickbook::string_view id,
427 id_category category,
428 source_mode_info const& source_mode)
429 {
430 boost::shared_ptr<section_info> parent =
431 current_file->document->current_section;
432
433 id_placeholder const* p = 0;
434 id_placeholder const* placeholder_1_6 = 0;
435
436 std::string id_1_1;
437
438 if (parent && current_file->compatibility_version < 106u) {
439 id_1_1 = parent->id_1_1;
440 if (!id_1_1.empty() && !id.empty())
441 id_1_1 += ".";
442 id_1_1.append(id.begin(), id.end());
443 }
444
445 if (current_file->compatibility_version >= 106u) {
446 p = placeholder_1_6 = add_id_to_section(id, category, parent);
447 }
448 else if (current_file->compatibility_version >= 103u) {
449 placeholder_1_6 = get_id_placeholder(parent);
450
451 std::string new_id;
452 if (!placeholder_1_6) {
453 new_id = current_file->doc_id_1_1;
454 if (!id_1_1.empty()) new_id += '.';
455 }
456 new_id += id_1_1;
457
458 p = add_placeholder(new_id, category, placeholder_1_6);
459 }
460 else {
461 placeholder_1_6 = get_id_placeholder(parent);
462
463 std::string new_id;
464 if (parent && !placeholder_1_6)
465 new_id = current_file->doc_id_1_1 + '.';
466
467 new_id += id.to_s();
468
469 p = add_placeholder(new_id, category, placeholder_1_6);
470 }
471
472 current_file->document->current_section =
473 boost::make_shared<section_info>(parent,
474 current_file.get(), explicit_id, id_1_1, placeholder_1_6,
475 source_mode);
476
477 return p;
478 }
479
480 void document_state_impl::end_section()
481 {
482 current_file->document->current_section =
483 current_file->document->current_section->parent;
484 }
485 }