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