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