]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/tools/quickbook/src/values.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / tools / quickbook / src / values.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2010-2011 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// An easy way to store data parsed for quickbook.
10
11#if !defined(BOOST_SPIRIT_QUICKBOOK_VALUES_HPP)
12#define BOOST_SPIRIT_QUICKBOOK_VALUES_HPP
13
14#include <utility>
15#include <string>
16#include <cassert>
b32b8144 17#include <stdexcept>
7c673cae 18#include <boost/scoped_ptr.hpp>
b32b8144 19#include <boost/operators.hpp>
7c673cae 20#include <boost/iterator/iterator_traits.hpp>
b32b8144 21#include "string_view.hpp"
7c673cae
FG
22#include "fwd.hpp"
23#include "files.hpp"
24
25namespace quickbook
26{
27 struct value;
28 struct value_builder;
29 struct value_error;
30
31 namespace detail
32 {
33 ////////////////////////////////////////////////////////////////////////
34 // Node
35
36 struct value_node
37 {
38 private:
39 value_node(value_node const&);
40 value_node& operator=(value_node const&);
41
42 public:
43 typedef int tag_type;
44
45 protected:
46 explicit value_node(tag_type);
47 virtual ~value_node();
48
49 public:
50 virtual char const* type_name() const = 0;
51 virtual value_node* clone() const = 0;
52
53 virtual file_ptr get_file() const;
54 virtual string_iterator get_position() const;
b32b8144 55 virtual quickbook::string_view get_quickbook() const;
7c673cae
FG
56 virtual std::string get_encoded() const;
57 virtual int get_int() const;
58
59 virtual bool check() const;
60 virtual bool empty() const;
61 virtual bool is_encoded() const;
62 virtual bool is_list() const;
63 virtual bool equals(value_node*) const;
64
65 virtual value_node* get_list() const;
66
67 int ref_count_;
68 const tag_type tag_;
69 value_node* next_;
70
71 friend void intrusive_ptr_add_ref(value_node* ptr)
72 { ++ptr->ref_count_; }
73 friend void intrusive_ptr_release(value_node* ptr)
74 { if(--ptr->ref_count_ == 0) delete ptr; }
75 };
76
77 ////////////////////////////////////////////////////////////////////////
78 // Value base
79 //
80 // This defines most of the public methods for value.
81 // 'begin' and 'end' are defined with the iterators later.
82
83 struct value_base
84 {
85 public:
86 struct iterator;
87
88 typedef iterator const_iterator;
89 typedef value_node::tag_type tag_type;
90 enum { default_tag = 0 };
91
92 protected:
93 explicit value_base(value_node* base)
94 : value_(base)
95 {
96 assert(value_);
97 }
98
99 ~value_base() {}
100
101 void swap(value_base& x) { std::swap(value_, x.value_); }
102 public:
103 bool check() const { return value_->check(); }
104 bool empty() const { return value_->empty(); }
105 bool is_encoded() const { return value_->is_encoded(); }
106 bool is_list() const { return value_->is_list(); }
107
108 iterator begin() const;
109 iterator end() const;
110
111 // Item accessors
b32b8144 112 tag_type get_tag() const { return value_->tag_; }
7c673cae
FG
113 file_ptr get_file() const
114 { return value_->get_file(); }
115 string_iterator get_position() const
116 { return value_->get_position(); }
b32b8144 117 quickbook::string_view get_quickbook() const
7c673cae
FG
118 { return value_->get_quickbook(); }
119 std::string get_encoded() const
120 { return value_->get_encoded(); }
121 int get_int() const
122 { return value_->get_int(); }
123
124 // Equality is pretty inefficient. Not really designed for anything
125 // more than testing purposes.
126 friend bool operator==(value_base const& x, value_base const& y)
127 { return x.value_->equals(y.value_); }
128
129 protected:
130 value_node* value_;
131
132 // value_builder needs to access 'value_' to get the node
133 // from a value.
134 friend struct quickbook::value_builder;
135 };
136
137 ////////////////////////////////////////////////////////////////////////
138 // Reference and proxy values for use in iterators
139
140 struct value_ref : public value_base
141 {
142 public:
143 explicit value_ref(value_node* base) : value_base(base) {}
144 };
145
146 struct value_proxy : public value_base
147 {
148 public:
149 explicit value_proxy(value_node* base) : value_base(base) {}
150 value_proxy* operator->() { return this; }
151 value_ref operator*() const { return value_ref(value_); }
152 };
153
154 ////////////////////////////////////////////////////////////////////////
155 // Iterators
156
157 struct value_base::iterator
158 : public boost::forward_iterator_helper<
159 iterator, value, int, value_proxy, value_ref>
160 {
161 public:
162 iterator();
163 explicit iterator(value_node* p) : ptr_(p) {}
164 friend bool operator==(iterator x, iterator y)
165 { return x.ptr_ == y.ptr_; }
166 iterator& operator++() { ptr_ = ptr_->next_; return *this; }
167 value_ref operator*() const { return value_ref(ptr_); }
168 value_proxy operator->() const { return value_proxy(ptr_); }
169 private:
170 value_node* ptr_;
171 };
172
173 inline value_base::iterator value_base::begin() const
174 {
175 return iterator(value_->get_list());
176 }
177
178 inline value_base::iterator value_base::end() const
179 {
180 return iterator();
181 }
182
183 ////////////////////////////////////////////////////////////////////////
184 // Reference counting for values
185
186 struct value_counted : public value_base
187 {
188 value_counted& operator=(value_counted const&);
189 protected:
190 value_counted();
191 value_counted(value_counted const&);
192 value_counted(value_base const&);
193 value_counted(value_node*);
194 ~value_counted();
195 };
196
197 ////////////////////////////////////////////////////////////////////////
198 // List builder
199 //
200 // Values are immutable, so this class is used to build a list of
201 // value nodes before constructing the value.
202
203 struct value_list_builder {
204 value_list_builder(value_list_builder const&);
205 value_list_builder& operator=(value_list_builder const&);
206 public:
207 value_list_builder();
208 value_list_builder(value_node*);
209 ~value_list_builder();
210 void swap(value_list_builder& b);
211 value_node* release();
212
213 void append(value_node*);
214 void sort();
215
216 bool empty() const;
217 private:
218 value_node* head_;
219 value_node** back_;
220 };
221 }
222
223 ////////////////////////////////////////////////////////////////////////////
224 // Value
225 //
226 // Most of the methods are in value_base.
227
228 struct value : public detail::value_counted
229 {
230 public:
231 value();
232 value(value const&);
233 value(detail::value_base const&);
234 explicit value(detail::value_node*);
235 value& operator=(value);
236 void swap(value& x) { detail::value_counted::swap(x); }
237 };
238
239 // Empty
240 value empty_value(value::tag_type = value::default_tag);
241
242 // Integers
243 value int_value(int, value::tag_type = value::default_tag);
244
245 // String types
246
247 // Quickbook strings contain a reference to the original quickbook source.
248 value qbk_value(file_ptr const&, string_iterator, string_iterator,
249 value::tag_type = value::default_tag);
250
251 // Encoded strings are either plain text or boostbook.
252 value encoded_value(std::string const&,
253 value::tag_type = value::default_tag);
254
255 // An encoded quickbook string is an encoded string that contains a
256 // reference to the quickbook source it was generated from.
257 value encoded_qbk_value(file_ptr const&, string_iterator, string_iterator,
258 std::string const&, value::tag_type = value::default_tag);
259
260 ////////////////////////////////////////////////////////////////////////////
261 // Value Builder
262 //
263 // Used to incrementally build a valueeter tree.
264
265 struct value_builder {
266 public:
267 value_builder();
268 void swap(value_builder& b);
269
270 void save();
271 void restore();
272
273 value release();
274
275 void insert(value const&);
276 void extend(value const&);
277
278 void start_list(value::tag_type = value::default_tag);
279 void finish_list();
280 void clear_list();
281 void sort_list();
282
283 bool empty() const;
284
285 private:
286 detail::value_list_builder current;
287 value::tag_type list_tag;
288 boost::scoped_ptr<value_builder> saved;
289 };
290
291 ////////////////////////////////////////////////////////////////////////////
292 // Value Error
293 //
294
295 struct value_error : public std::logic_error
296 {
297 public:
298 explicit value_error(std::string const&);
299 };
300
301 ////////////////////////////////////////////////////////////////////////////
302 // Value Consumer
303 //
304 // Convenience class for unpacking value values.
305
306 struct value_consumer {
307 public:
308 struct iterator
309 : public boost::input_iterator_helper<iterator,
310 boost::iterator_value<value::iterator>::type,
311 boost::iterator_difference<value::iterator>::type,
312 boost::iterator_pointer<value::iterator>::type,
313 boost::iterator_reference<value::iterator>::type>
314 {
315 public:
316 iterator();
317 explicit iterator(value::iterator* p) : ptr_(p) {}
318 friend bool operator==(iterator x, iterator y)
319 { return *x.ptr_ == *y.ptr_; }
320 iterator& operator++() { ++*ptr_; return *this; }
321 reference operator*() const { return **ptr_; }
322 pointer operator->() const { return ptr_->operator->(); }
323 private:
324 value::iterator* ptr_;
325 };
326
327 typedef iterator const_iterator;
328 typedef iterator::reference reference;
329
330 value_consumer(value const& x)
331 : list_(x)
332 , pos_(x.begin())
333 , end_(x.end())
334 {}
335
336 value_consumer(reference x)
337 : list_(x)
338 , pos_(x.begin())
339 , end_(x.end())
340 {}
341
342 reference consume()
343 {
344 assert_check();
345 return *pos_++;
346 }
347
348 reference consume(value::tag_type t)
349 {
350 assert_check(t);
351 return *pos_++;
352 }
353
354 value optional_consume()
355 {
356 if(check()) {
357 return *pos_++;
358 }
359 else {
360 return value();
361 }
362 }
363
364 value optional_consume(value::tag_type t)
365 {
366 if(check(t)) {
367 return *pos_++;
368 }
369 else {
370 return value();
371 }
372 }
373
374 bool check() const
375 {
376 return pos_ != end_;
377 }
378
379 bool check(value::tag_type t) const
380 {
381 return pos_ != end_ && t == pos_->get_tag();
382 }
383
384 void finish() const
385 {
386 if (pos_ != end_)
387 throw value_error("Not all values handled.");
388 }
389
390 iterator begin() { return iterator(&pos_); }
391 iterator end() { return iterator(&end_); }
392 private:
393
394 void assert_check() const
395 {
396 if (pos_ == end_)
397 throw value_error("Attempt to read past end of value list.");
398 }
399
400 void assert_check(value::tag_type t) const
401 {
402 assert_check();
403 if (t != pos_->get_tag())
404 throw value_error("Incorrect value tag.");
405 }
406
407 value list_;
408 value::iterator pos_, end_;
409 };
410}
411
412#endif