]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/support/utree/operators.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / spirit / home / support / utree / operators.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2011 Bryce Lelbach
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_SPIRIT_UTREE_OPERATORS)
10 #define BOOST_SPIRIT_UTREE_OPERATORS
11
12 #if defined(BOOST_MSVC)
13 # pragma warning(push)
14 # pragma warning(disable: 4804)
15 # pragma warning(disable: 4805)
16 #endif
17
18 #include <exception>
19 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
20 #include <ios>
21 #include <boost/io/ios_state.hpp>
22 #endif
23 #include <boost/spirit/home/support/utree/utree.hpp>
24 #include <boost/preprocessor/cat.hpp>
25 #include <boost/throw_exception.hpp>
26 #include <boost/type_traits/is_arithmetic.hpp>
27 #include <boost/type_traits/is_integral.hpp>
28
29 namespace boost { namespace spirit
30 {
31 // Relational operators
32 bool operator==(utree const& a, utree const& b);
33 bool operator<(utree const& a, utree const& b);
34 bool operator!=(utree const& a, utree const& b);
35 bool operator>(utree const& a, utree const& b);
36 bool operator<=(utree const& a, utree const& b);
37 bool operator>=(utree const& a, utree const& b);
38
39 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
40 // output
41 std::ostream& operator<<(std::ostream& out, utree const& x);
42 std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x);
43 std::ostream& operator<<(std::ostream& out, utree::nil_type const& x);
44 #endif
45
46 // Logical operators
47 utree operator&&(utree const& a, utree const& b);
48 utree operator||(utree const& a, utree const& b);
49 utree operator!(utree const& a);
50
51 // Arithmetic operators
52 utree operator+(utree const& a, utree const& b);
53 utree operator-(utree const& a, utree const& b);
54 utree operator*(utree const& a, utree const& b);
55 utree operator/(utree const& a, utree const& b);
56 utree operator%(utree const& a, utree const& b);
57 utree operator-(utree const& a);
58
59 // Bitwise operators
60 utree operator&(utree const& a, utree const& b);
61 utree operator|(utree const& a, utree const& b);
62 utree operator^(utree const& a, utree const& b);
63 utree operator<<(utree const& a, utree const& b);
64 utree operator>>(utree const& a, utree const& b);
65 utree operator~(utree const& a);
66
67 // Implementation
68 struct utree_is_equal
69 {
70 typedef bool result_type;
71
72 template <typename A, typename B>
73 bool dispatch(const A&, const B&, boost::mpl::false_) const
74 {
75 return false; // cannot compare different types by default
76 }
77
78 template <typename A, typename B>
79 bool dispatch(const A& a, const B& b, boost::mpl::true_) const
80 {
81 return a == b; // for arithmetic types
82 }
83
84 template <typename A, typename B>
85 bool operator()(const A& a, const B& b) const
86 {
87 return dispatch(a, b,
88 boost::mpl::and_<
89 boost::is_arithmetic<A>,
90 boost::is_arithmetic<B> >());
91 }
92
93 template <typename T>
94 bool operator()(const T& a, const T& b) const
95 {
96 // This code works for lists
97 return a == b;
98 }
99
100 template <typename Base, utree_type::info type_>
101 bool operator()(
102 basic_string<Base, type_> const& a,
103 basic_string<Base, type_> const& b) const
104 {
105 return static_cast<Base const&>(a) == static_cast<Base const&>(b);
106 }
107
108 bool operator()(utree::invalid_type, utree::invalid_type) const
109 {
110 return true;
111 }
112
113 bool operator()(utree::nil_type, utree::nil_type) const
114 {
115 return true;
116 }
117
118 bool operator()(function_base const&, function_base const&) const
119 {
120 return false; // just don't allow comparison of functions
121 }
122 };
123
124 struct utree_is_less_than
125 {
126 typedef bool result_type;
127
128 template <typename A, typename B>
129 bool dispatch(const A&, const B&, boost::mpl::false_) const
130 {
131 return false; // cannot compare different types by default
132 }
133
134 template <typename A, typename B>
135 bool dispatch(const A& a, const B& b, boost::mpl::true_) const
136 {
137 return a < b; // for arithmetic types
138 }
139
140 template <typename A, typename B>
141 bool operator()(const A& a, const B& b) const
142 {
143 return dispatch(a, b,
144 boost::mpl::and_<
145 boost::is_arithmetic<A>,
146 boost::is_arithmetic<B> >());
147 }
148
149 template <typename T>
150 bool operator()(const T& a, const T& b) const
151 {
152 // This code works for lists
153 return a < b;
154 }
155
156 template <typename Base, utree_type::info type_>
157 bool operator()(
158 basic_string<Base, type_> const& a,
159 basic_string<Base, type_> const& b) const
160 {
161 return static_cast<Base const&>(a) < static_cast<Base const&>(b);
162 }
163
164 bool operator()(utree::invalid_type, utree::invalid_type) const
165 {
166 BOOST_THROW_EXCEPTION(bad_type_exception
167 ("no less-than comparison for this utree type",
168 utree_type::invalid_type));
169 return false; // no less than comparison for nil
170 }
171
172 bool operator()(utree::nil_type, utree::nil_type) const
173 {
174 BOOST_THROW_EXCEPTION(bad_type_exception
175 ("no less-than comparison for this utree type",
176 utree_type::nil_type));
177 return false; // no less than comparison for nil
178 }
179
180 bool operator()(any_ptr const&, any_ptr const&) const
181 {
182 BOOST_THROW_EXCEPTION(bad_type_exception
183 ("no less-than comparison for this utree type",
184 utree_type::any_type));
185 return false; // no less than comparison for any_ptr
186 }
187
188 bool operator()(function_base const&, function_base const&) const
189 {
190 BOOST_THROW_EXCEPTION(bad_type_exception
191 ("no less-than comparison for this utree type",
192 utree_type::function_type));
193 return false; // no less than comparison of functions
194 }
195 };
196
197 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
198 struct utree_print
199 {
200 typedef void result_type;
201
202 std::ostream& out;
203 utree_print(std::ostream& out) : out(out) {}
204
205 void operator()(utree::invalid_type) const
206 {
207 out << "<invalid> ";
208 }
209
210 void operator()(utree::nil_type) const
211 {
212 out << "<nil> ";
213 }
214
215 template <typename T>
216 void operator()(T val) const
217 {
218 out << val << ' ';
219 }
220
221 void operator()(bool b) const
222 {
223 out << (b ? "true" : "false") << ' ';
224 }
225
226 void operator()(binary_range_type const& b) const
227 {
228 boost::io::ios_all_saver saver(out);
229 out << "#";
230 out.width(2);
231 out.fill('0');
232
233 typedef binary_range_type::const_iterator iterator;
234 for (iterator i = b.begin(); i != b.end(); ++i)
235 out << std::hex << int((unsigned char)*i);
236 out << "# ";
237 }
238
239 void operator()(utf8_string_range_type const& str) const
240 {
241 typedef utf8_string_range_type::const_iterator iterator;
242 iterator i = str.begin();
243 out << '"';
244 for (; i != str.end(); ++i)
245 out << *i;
246 out << "\" ";
247 }
248
249 void operator()(utf8_symbol_range_type const& str) const
250 {
251 typedef utf8_symbol_range_type::const_iterator iterator;
252 iterator i = str.begin();
253 for (; i != str.end(); ++i)
254 out << *i;
255 out << ' ';
256 }
257
258 template <typename Iterator>
259 void operator()(boost::iterator_range<Iterator> const& range) const
260 {
261 typedef typename boost::iterator_range<Iterator>::const_iterator iterator;
262 (*this)('(');
263 for (iterator i = range.begin(); i != range.end(); ++i)
264 {
265 boost::spirit::utree::visit(*i, *this);
266 }
267 (*this)(')');
268 }
269
270 void operator()(any_ptr const&) const
271 {
272 return (*this)("<pointer>");
273 }
274
275 void operator()(function_base const&) const
276 {
277 return (*this)("<function>");
278 }
279 };
280 #endif
281
282 template <typename Base>
283 struct logical_function
284 {
285 typedef utree result_type;
286
287 // We assume anything except false is true
288
289 // binary
290 template <typename A, typename B>
291 utree operator()(A const& a, B const& b) const
292 {
293 return dispatch(a, b
294 , boost::is_arithmetic<A>()
295 , boost::is_arithmetic<B>());
296 }
297
298 // binary
299 template <typename A, typename B>
300 utree dispatch(A const& a, B const& b, mpl::true_, mpl::true_) const
301 {
302 return Base::eval(a, b); // for arithmetic types
303 }
304
305 // binary
306 template <typename A, typename B>
307 utree dispatch(A const&, B const& b, mpl::false_, mpl::true_) const
308 {
309 return Base::eval(true, b);
310 }
311
312 // binary
313 template <typename A, typename B>
314 utree dispatch(A const& a, B const&, mpl::true_, mpl::false_) const
315 {
316 return Base::eval(a, true);
317 }
318
319 // binary
320 template <typename A, typename B>
321 utree dispatch(A const&, B const&, mpl::false_, mpl::false_) const
322 {
323 return Base::eval(true, true);
324 }
325
326 // unary
327 template <typename A>
328 utree operator()(A const& a) const
329 {
330 return dispatch(a, boost::is_arithmetic<A>());
331 }
332
333 // unary
334 template <typename A>
335 utree dispatch(A const& a, mpl::true_) const
336 {
337 return Base::eval(a);
338 }
339
340 // unary
341 template <typename A>
342 utree dispatch(A const&, mpl::false_) const
343 {
344 return Base::eval(true);
345 }
346 };
347
348 template <typename Base>
349 struct arithmetic_function
350 {
351 typedef utree result_type;
352
353 template <typename A, typename B>
354 utree dispatch(A const&, B const&, boost::mpl::false_) const
355 {
356 return utree(); // cannot apply to non-arithmetic types
357 }
358
359 template <typename A, typename B>
360 utree dispatch(A const& a, B const& b, boost::mpl::true_) const
361 {
362 return Base::eval(a, b); // for arithmetic types
363 }
364
365 // binary
366 template <typename A, typename B>
367 utree operator()(A const& a, B const& b) const
368 {
369 return dispatch(a, b,
370 boost::mpl::and_<
371 boost::is_arithmetic<A>,
372 boost::is_arithmetic<B> >());
373 }
374
375 template <typename A>
376 utree dispatch(A const&, boost::mpl::false_) const
377 {
378 return utree(); // cannot apply to non-arithmetic types
379 }
380
381 template <typename A>
382 utree dispatch(A const& a, boost::mpl::true_) const
383 {
384 return Base::eval(a); // for arithmetic types
385 }
386
387 // unary
388 template <typename A>
389 utree operator()(A const& a) const
390 {
391 return dispatch(a, boost::is_arithmetic<A>());
392 }
393 };
394
395 template <typename Base>
396 struct integral_function
397 {
398 typedef utree result_type;
399
400 template <typename A, typename B>
401 utree dispatch(A const&, B const&, boost::mpl::false_) const
402 {
403 return utree(); // cannot apply to non-integral types
404 }
405
406 template <typename A, typename B>
407 utree dispatch(A const& a, B const& b, boost::mpl::true_) const
408 {
409 return Base::eval(a, b); // for integral types
410 }
411
412 // binary
413 template <typename A, typename B>
414 utree operator()(A const& a, B const& b) const
415 {
416 return dispatch(a, b,
417 boost::mpl::and_<
418 boost::is_integral<A>,
419 boost::is_integral<B> >());
420 }
421
422 template <typename A>
423 utree dispatch(A const&, boost::mpl::false_) const
424 {
425 return utree(); // cannot apply to non-integral types
426 }
427
428 template <typename A>
429 utree dispatch(A const& a, boost::mpl::true_) const
430 {
431 return Base::eval(a); // for integral types
432 }
433
434 // unary
435 template <typename A>
436 utree operator()(A const& a) const
437 {
438 return dispatch(a, boost::is_integral<A>());
439 }
440 };
441
442 #define BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, base) \
443 struct BOOST_PP_CAT(function_impl_, name) \
444 { \
445 template <typename A, typename B> \
446 static utree eval(A const& a, B const& b) \
447 { \
448 return utree(expr); \
449 } \
450 template <typename A> \
451 static utree eval(A const& a) \
452 { \
453 static int b; \
454 (void) b; \
455 return utree(expr); \
456 } \
457 }; \
458 base<BOOST_PP_CAT(function_impl_, name)> const \
459 BOOST_PP_CAT(base, BOOST_PP_CAT(_, name)) = {}; \
460 /***/
461
462 #define BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(name, expr) \
463 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, arithmetic_function) \
464 /***/
465
466 #define BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(name, expr) \
467 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, integral_function) \
468 /***/
469
470 #define BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(name, expr) \
471 BOOST_SPIRIT_UTREE_CREATE_FUNCTION(name, expr, logical_function) \
472 /***/
473
474 inline bool operator==(utree const& a, utree const& b)
475 {
476 return utree::visit(a, b, utree_is_equal());
477 }
478
479 inline bool operator<(utree const& a, utree const& b)
480 {
481 return utree::visit(a, b, utree_is_less_than());
482 }
483
484 inline bool operator!=(utree const& a, utree const& b)
485 {
486 return !(a == b);
487 }
488
489 inline bool operator>(utree const& a, utree const& b)
490 {
491 return b < a;
492 }
493
494 inline bool operator<=(utree const& a, utree const& b)
495 {
496 return !(b < a);
497 }
498
499 inline bool operator>=(utree const& a, utree const& b)
500 {
501 return !(a < b);
502 }
503
504 #if !defined(BOOST_SPIRIT_DISABLE_UTREE_IO)
505 inline std::ostream& operator<<(std::ostream& out, utree const& x)
506 {
507 utree::visit(x, utree_print(out));
508 return out;
509 }
510
511 inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const&)
512 {
513 return out;
514 }
515
516 inline std::ostream& operator<<(std::ostream& out, utree::nil_type const&)
517 {
518 return out;
519 }
520 #endif
521
522 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(and_, a&&b)
523 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(or_, a||b)
524 BOOST_SPIRIT_UTREE_CREATE_LOGICAL_FUNCTION(not_, !a)
525
526 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(plus, a+b)
527 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(minus, a-b)
528 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(times, a*b)
529 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(divides, a/b)
530 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(modulus, a%b)
531 BOOST_SPIRIT_UTREE_CREATE_ARITHMETIC_FUNCTION(negate, -a)
532
533 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitand_, a&b)
534 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitor_, a|b)
535 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(bitxor_, a^b)
536 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_left, a<<b)
537 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(shift_right, a>>b)
538 #if defined(__GNUC__) && (__GNUC__ >= 7)
539 # pragma GCC diagnostic push
540 # pragma GCC diagnostic ignored "-Wbool-operation" // '~' on an expression of type bool
541 #endif
542 BOOST_SPIRIT_UTREE_CREATE_INTEGRAL_FUNCTION(invert, ~a)
543 #if defined(__GNUC__) && (__GNUC__ >= 7)
544 # pragma GCC diagnostic pop
545 #endif
546
547 inline utree operator&&(utree const& a, utree const& b)
548 {
549 return utree::visit(a, b, logical_function_and_);
550 }
551
552 inline utree operator||(utree const& a, utree const& b)
553 {
554 return utree::visit(a, b, logical_function_or_);
555 }
556
557 inline utree operator!(utree const& a)
558 {
559 return utree::visit(a, logical_function_not_);
560 }
561
562 inline utree operator+(utree const& a, utree const& b)
563 {
564 utree r = utree::visit(a, b, arithmetic_function_plus);
565 if (r.which() == utree_type::invalid_type)
566 {
567 BOOST_THROW_EXCEPTION(bad_type_exception
568 ("addition performed on non-arithmetic utree types",
569 a.which(), b.which()));
570 }
571 return r;
572 }
573
574 inline utree operator-(utree const& a, utree const& b)
575 {
576 utree r = utree::visit(a, b, arithmetic_function_minus);
577 if (r.which() == utree_type::invalid_type)
578 {
579 BOOST_THROW_EXCEPTION(bad_type_exception
580 ("subtraction performed on non-arithmetic utree types",
581 a.which(), b.which()));
582 }
583 return r;
584 }
585
586 inline utree operator*(utree const& a, utree const& b)
587 {
588 utree r = utree::visit(a, b, arithmetic_function_times);
589 if (r.which() == utree_type::invalid_type)
590 {
591 BOOST_THROW_EXCEPTION(bad_type_exception
592 ("multiplication performed on non-arithmetic utree types",
593 a.which(), b.which()));
594 }
595 return r;
596 }
597
598 inline utree operator/(utree const& a, utree const& b)
599 {
600 utree r = utree::visit(a, b, arithmetic_function_divides);
601 if (r.which() == utree_type::invalid_type)
602 {
603 BOOST_THROW_EXCEPTION(bad_type_exception
604 ("division performed on non-arithmetic utree types",
605 a.which(), b.which()));
606 }
607 return r;
608 }
609
610 inline utree operator%(utree const& a, utree const& b)
611 {
612 utree r = utree::visit(a, b, integral_function_modulus);
613 if (r.which() == utree_type::invalid_type)
614 {
615 BOOST_THROW_EXCEPTION(bad_type_exception
616 ("modulos performed on non-integral utree types",
617 a.which(), b.which()));
618 }
619 return r;
620 }
621
622 inline utree operator-(utree const& a)
623 {
624 utree r = utree::visit(a, arithmetic_function_negate);
625 if (r.which() == utree_type::invalid_type)
626 {
627 BOOST_THROW_EXCEPTION(bad_type_exception
628 ("negation performed on non-arithmetic utree type",
629 a.which()));
630 }
631 return r;
632 }
633
634 inline utree operator&(utree const& a, utree const& b)
635 {
636 utree r = utree::visit(a, b, integral_function_bitand_);
637 if (r.which() == utree_type::invalid_type)
638 {
639 BOOST_THROW_EXCEPTION(bad_type_exception
640 ("bitwise and performed on non-integral utree types",
641 a.which(), b.which()));
642 }
643 return r;
644 }
645
646 inline utree operator|(utree const& a, utree const& b)
647 {
648 utree r = utree::visit(a, b, integral_function_bitor_);
649 if (r.which() == utree_type::invalid_type)
650 {
651 BOOST_THROW_EXCEPTION(bad_type_exception
652 ("bitwise or performed on non-integral utree types",
653 a.which(), b.which()));
654 }
655 return r;
656 }
657
658 inline utree operator^(utree const& a, utree const& b)
659 {
660 utree r = utree::visit(a, b, integral_function_bitxor_);
661 if (r.which() == utree_type::invalid_type)
662 {
663 BOOST_THROW_EXCEPTION(bad_type_exception
664 ("bitwise xor performed on non-integral utree types",
665 a.which(), b.which()));
666 }
667 return r;
668 }
669
670 inline utree operator<<(utree const& a, utree const& b)
671 {
672 utree r = utree::visit(a, b, integral_function_shift_left);
673 if (r.which() == utree_type::invalid_type)
674 {
675 BOOST_THROW_EXCEPTION(bad_type_exception
676 ("left shift performed on non-integral utree types",
677 a.which(), b.which()));
678 }
679 return r;
680 }
681
682 inline utree operator>>(utree const& a, utree const& b)
683 {
684 utree r = utree::visit(a, b, integral_function_shift_right);
685 if (r.which() == utree_type::invalid_type)
686 {
687 BOOST_THROW_EXCEPTION(bad_type_exception
688 ("right shift performed on non-integral utree types",
689 a.which(), b.which()));
690 }
691 return r;
692 }
693
694 inline utree operator~(utree const& a)
695 {
696 utree r = utree::visit(a, integral_function_invert);
697 if (r.which() == utree_type::invalid_type)
698 {
699 BOOST_THROW_EXCEPTION(bad_type_exception
700 ("inversion performed on non-integral utree type",
701 a.which()));
702 }
703 return r;
704 }
705 }}
706
707 #if defined(BOOST_MSVC)
708 # pragma warning(pop)
709 #endif
710
711 #endif