• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Copyright (c) 2001-2011 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #if !defined(BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM)
7 #define BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM
8 
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12 
13 #include <boost/config.hpp>
14 #include <boost/config/no_tr1/cmath.hpp>
15 #include <boost/limits.hpp>
16 
17 #include <boost/math/special_functions/fpclassify.hpp>
18 #include <boost/type_traits/is_integral.hpp>
19 #include <boost/spirit/home/support/char_class.hpp>
20 #include <boost/spirit/home/support/unused.hpp>
21 #include <boost/spirit/home/support/numeric_traits.hpp>
22 #include <boost/spirit/home/support/detail/pow10.hpp>
23 #include <boost/spirit/home/support/detail/sign.hpp>
24 #include <boost/spirit/home/karma/detail/generate_to.hpp>
25 #include <boost/spirit/home/karma/detail/string_generate.hpp>
26 
27 ///////////////////////////////////////////////////////////////////////////////
28 //
29 //  The value BOOST_KARMA_NUMERICS_LOOP_UNROLL specifies, how to unroll the
30 //  integer string generation loop (see below).
31 //
32 //      Set the value to some integer in between 0 (no unrolling) and the
33 //      largest expected generated integer string length (complete unrolling).
34 //      If not specified, this value defaults to 6.
35 //
36 ///////////////////////////////////////////////////////////////////////////////
37 #if !defined(BOOST_KARMA_NUMERICS_LOOP_UNROLL)
38 #define BOOST_KARMA_NUMERICS_LOOP_UNROLL 6
39 #endif
40 
41 #if BOOST_KARMA_NUMERICS_LOOP_UNROLL < 0
42 #error "Please set the BOOST_KARMA_NUMERICS_LOOP_UNROLL to a non-negative value!"
43 #endif
44 
45 namespace boost { namespace spirit { namespace traits
46 {
47     ///////////////////////////////////////////////////////////////////////
48     //
49     //  return the absolute value from a given number, avoiding over- and
50     //  underflow
51     //
52     ///////////////////////////////////////////////////////////////////////
53     template <typename T, typename Enable/* = void*/>
54     struct absolute_value
55     {
56         typedef T type;
callboost::spirit::traits::absolute_value57         static T call (T n)
58         {
59             // allow for ADL to find the correct overloads for fabs
60             using namespace std;
61             return fabs(n);
62         }
63     };
64 
65 #define BOOST_SPIRIT_ABSOLUTE_VALUE(signedtype, unsignedtype)                 \
66         template <>                                                           \
67         struct absolute_value<signedtype>                                     \
68         {                                                                     \
69             typedef unsignedtype type;                                        \
70             static type call(signedtype n)                                    \
71             {                                                                 \
72                 /* implementation is well-defined for one's complement, */    \
73                 /* two's complement, and signed magnitude architectures */    \
74                 /* by the C++ Standard. [conv.integral] [expr.unary.op] */    \
75                 return (n >= 0) ?  static_cast<type>(n)                       \
76                                 : -static_cast<type>(n);                      \
77             }                                                                 \
78         }                                                                     \
79     /**/
80 #define BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsignedtype)                    \
81         template <>                                                           \
82         struct absolute_value<unsignedtype>                                   \
83         {                                                                     \
84             typedef unsignedtype type;                                        \
85             static type call(unsignedtype n)                                  \
86             {                                                                 \
87                 return n;                                                     \
88             }                                                                 \
89         }                                                                     \
90     /**/
91 
92 #if defined(BOOST_MSVC)
93 # pragma warning(push)
94 // unary minus operator applied to unsigned type, result still unsigned
95 # pragma warning(disable: 4146)
96 #endif
97     BOOST_SPIRIT_ABSOLUTE_VALUE(signed char, unsigned char);
98     BOOST_SPIRIT_ABSOLUTE_VALUE(char, unsigned char);
99     BOOST_SPIRIT_ABSOLUTE_VALUE(short, unsigned short);
100     BOOST_SPIRIT_ABSOLUTE_VALUE(int, unsigned int);
101     BOOST_SPIRIT_ABSOLUTE_VALUE(long, unsigned long);
102     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned char);
103     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned short);
104     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned int);
105     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned long);
106 #ifdef BOOST_HAS_LONG_LONG
107     BOOST_SPIRIT_ABSOLUTE_VALUE(boost::long_long_type, boost::ulong_long_type);
108     BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(boost::ulong_long_type);
109 #endif
110 #if defined(BOOST_MSVC)
111 # pragma warning(pop)
112 #endif
113 
114 #undef BOOST_SPIRIT_ABSOLUTE_VALUE
115 #undef BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED
116 
117     template <>
118     struct absolute_value<float>
119     {
120         typedef float type;
callboost::spirit::traits::absolute_value121         static type call(float n)
122         {
123             return (spirit::detail::signbit)(n) ? -n : n;
124         }
125     };
126 
127     template <>
128     struct absolute_value<double>
129     {
130         typedef double type;
callboost::spirit::traits::absolute_value131         static type call(double n)
132         {
133             return (spirit::detail::signbit)(n) ? -n : n;
134         }
135     };
136 
137     template <>
138     struct absolute_value<long double>
139     {
140         typedef long double type;
callboost::spirit::traits::absolute_value141         static type call(long double n)
142         {
143             return (spirit::detail::signbit)(n) ? -n : n;
144         }
145     };
146 
147     // specialization for pointers
148     template <typename T>
149     struct absolute_value<T*>
150     {
151         typedef std::size_t type;
callboost::spirit::traits::absolute_value152         static type call (T* p)
153         {
154             return std::size_t(p);
155         }
156     };
157 
158     template <typename T>
159     inline typename absolute_value<T>::type
get_absolute_value(T n)160     get_absolute_value(T n)
161     {
162         return absolute_value<T>::call(n);
163     }
164 
165     ///////////////////////////////////////////////////////////////////////
166     template <typename T, typename Enable/* = void*/>
167     struct is_negative
168     {
callboost::spirit::traits::is_negative169         static bool call(T n)
170         {
171             return (n < 0) ? true : false;
172         }
173     };
174 
175     template <>
176     struct is_negative<float>
177     {
callboost::spirit::traits::is_negative178         static bool call(float n)
179         {
180             return (spirit::detail::signbit)(n) ? true : false;
181         }
182     };
183 
184     template <>
185     struct is_negative<double>
186     {
callboost::spirit::traits::is_negative187         static bool call(double n)
188         {
189             return (spirit::detail::signbit)(n) ? true : false;
190         }
191     };
192 
193     template <>
194     struct is_negative<long double>
195     {
callboost::spirit::traits::is_negative196         static bool call(long double n)
197         {
198             return (spirit::detail::signbit)(n) ? true : false;
199         }
200     };
201 
202     template <typename T>
test_negative(T n)203     inline bool test_negative(T n)
204     {
205         return is_negative<T>::call(n);
206     }
207 
208     ///////////////////////////////////////////////////////////////////////
209     template <typename T, typename Enable/* = void*/>
210     struct is_zero
211     {
callboost::spirit::traits::is_zero212         static bool call(T n)
213         {
214             return (n == 0) ? true : false;
215         }
216     };
217 
218     template <>
219     struct is_zero<float>
220     {
callboost::spirit::traits::is_zero221         static bool call(float n)
222         {
223             return (math::fpclassify)(n) == FP_ZERO;
224         }
225     };
226 
227     template <>
228     struct is_zero<double>
229     {
callboost::spirit::traits::is_zero230         static bool call(double n)
231         {
232             return (math::fpclassify)(n) == FP_ZERO;
233         }
234     };
235 
236     template <>
237     struct is_zero<long double>
238     {
callboost::spirit::traits::is_zero239         static bool call(long double n)
240         {
241             return (math::fpclassify)(n) == FP_ZERO;
242         }
243     };
244 
245     template <typename T>
test_zero(T n)246     inline bool test_zero(T n)
247     {
248         return is_zero<T>::call(n);
249     }
250 
251     ///////////////////////////////////////////////////////////////////////
252     template <typename T, typename Enable/* = void*/>
253     struct is_nan
254     {
callboost::spirit::traits::is_nan255         static bool call(T n)
256         {
257             // NaN numbers are not equal to anything
258             return (n != n) ? true : false;
259         }
260     };
261 
262     template <>
263     struct is_nan<float>
264     {
callboost::spirit::traits::is_nan265         static bool call(float n)
266         {
267             return (math::fpclassify)(n) == FP_NAN;
268         }
269     };
270 
271     template <>
272     struct is_nan<double>
273     {
callboost::spirit::traits::is_nan274         static bool call(double n)
275         {
276             return (math::fpclassify)(n) == FP_NAN;
277         }
278     };
279 
280     template <>
281     struct is_nan<long double>
282     {
callboost::spirit::traits::is_nan283         static bool call(long double n)
284         {
285             return (math::fpclassify)(n) == FP_NAN;
286         }
287     };
288 
289     template <typename T>
test_nan(T n)290     inline bool test_nan(T n)
291     {
292         return is_nan<T>::call(n);
293     }
294 
295     ///////////////////////////////////////////////////////////////////////
296     template <typename T, typename Enable/* = void*/>
297     struct is_infinite
298     {
callboost::spirit::traits::is_infinite299         static bool call(T n)
300         {
301             return std::numeric_limits<T>::has_infinity
302                 && n == std::numeric_limits<T>::infinity();
303         }
304     };
305 
306     template <>
307     struct is_infinite<float>
308     {
callboost::spirit::traits::is_infinite309         static bool call(float n)
310         {
311             return (math::fpclassify)(n) == FP_INFINITE;
312         }
313     };
314 
315     template <>
316     struct is_infinite<double>
317     {
callboost::spirit::traits::is_infinite318         static bool call(double n)
319         {
320             return (math::fpclassify)(n) == FP_INFINITE;
321         }
322     };
323 
324     template <>
325     struct is_infinite<long double>
326     {
callboost::spirit::traits::is_infinite327         static bool call(long double n)
328         {
329             return (math::fpclassify)(n) == FP_INFINITE;
330         }
331     };
332 
333     template <typename T>
test_infinite(T n)334     inline bool test_infinite(T n)
335     {
336         return is_infinite<T>::call(n);
337     }
338 
339     ///////////////////////////////////////////////////////////////////////
340     struct cast_to_long
341     {
callboost::spirit::traits::cast_to_long342         static long call(float n, mpl::false_)
343         {
344             return static_cast<long>(std::floor(n));
345         }
346 
callboost::spirit::traits::cast_to_long347         static long call(double n, mpl::false_)
348         {
349             return static_cast<long>(std::floor(n));
350         }
351 
callboost::spirit::traits::cast_to_long352         static long call(long double n, mpl::false_)
353         {
354             return static_cast<long>(std::floor(n));
355         }
356 
357         template <typename T>
callboost::spirit::traits::cast_to_long358         static long call(T n, mpl::false_)
359         {
360             // allow for ADL to find the correct overload for floor and
361             // lround
362             using namespace std;
363             return lround(floor(n));
364         }
365 
366         template <typename T>
callboost::spirit::traits::cast_to_long367         static long call(T n, mpl::true_)
368         {
369             return static_cast<long>(n);
370         }
371 
372         template <typename T>
callboost::spirit::traits::cast_to_long373         static long call(T n)
374         {
375             return call(n, mpl::bool_<is_integral<T>::value>());
376         }
377     };
378 
379     ///////////////////////////////////////////////////////////////////////
380     struct truncate_to_long
381     {
callboost::spirit::traits::truncate_to_long382         static long call(float n, mpl::false_)
383         {
384             return test_negative(n) ? static_cast<long>(std::ceil(n)) :
385                 static_cast<long>(std::floor(n));
386         }
387 
callboost::spirit::traits::truncate_to_long388         static long call(double n, mpl::false_)
389         {
390             return test_negative(n) ? static_cast<long>(std::ceil(n)) :
391                 static_cast<long>(std::floor(n));
392         }
393 
callboost::spirit::traits::truncate_to_long394         static long call(long double n, mpl::false_)
395         {
396             return test_negative(n) ? static_cast<long>(std::ceil(n)) :
397                 static_cast<long>(std::floor(n));
398         }
399 
400         template <typename T>
callboost::spirit::traits::truncate_to_long401         static long call(T n, mpl::false_)
402         {
403             // allow for ADL to find the correct overloads for ltrunc
404             using namespace std;
405             return ltrunc(n);
406         }
407 
408         template <typename T>
callboost::spirit::traits::truncate_to_long409         static long call(T n, mpl::true_)
410         {
411             return static_cast<long>(n);
412         }
413 
414         template <typename T>
callboost::spirit::traits::truncate_to_long415         static long call(T n)
416         {
417             return call(n, mpl::bool_<is_integral<T>::value>());
418         }
419     };
420 
421     ///////////////////////////////////////////////////////////////////////
422     //
423     //  Traits class for radix specific number conversion
424     //
425     //      Convert a digit from binary representation to character
426     //      representation:
427     //
428     //          static int call(unsigned n);
429     //
430     ///////////////////////////////////////////////////////////////////////
431     namespace detail
432     {
433         template <typename CharEncoding, typename Tag, bool radix_less_than_10>
434         struct convert_digit
435         {
callboost::spirit::traits::detail::convert_digit436             static int call(unsigned n)
437             {
438                 if (n <= 9)
439                     return n + '0';
440 
441                 using spirit::char_class::convert;
442                 return convert<CharEncoding>::to(Tag(), n - 10 + 'a');
443             }
444         };
445 
446         template <>
447         struct convert_digit<unused_type, unused_type, false>
448         {
callboost::spirit::traits::detail::convert_digit449             static int call(unsigned n)
450             {
451                 if (n <= 9)
452                     return n + '0';
453                 return n - 10 + 'a';
454             }
455         };
456 
457         template <typename CharEncoding, typename Tag>
458         struct convert_digit<CharEncoding, Tag, true>
459         {
callboost::spirit::traits::detail::convert_digit460             static int call(unsigned n)
461             {
462                 return n + '0';
463             }
464         };
465     }
466 
467     template <unsigned Radix, typename CharEncoding, typename Tag>
468     struct convert_digit
469       : detail::convert_digit<CharEncoding, Tag, (Radix <= 10) ? true : false>
470     {};
471 
472     ///////////////////////////////////////////////////////////////////////
473     template <unsigned Radix>
474     struct divide
475     {
476         template <typename T>
callboost::spirit::traits::divide477         static T call(T& n, mpl::true_)
478         {
479             return n / Radix;
480         }
481 
482         template <typename T>
callboost::spirit::traits::divide483         static T call(T& n, mpl::false_)
484         {
485             // Allow ADL to find the correct overload for floor
486             using namespace std;
487             return floor(n / Radix);
488         }
489 
490         template <typename T>
callboost::spirit::traits::divide491         static T call(T& n, T const&, int)
492         {
493             return call(n, mpl::bool_<is_integral<T>::value>());
494         }
495 
496         template <typename T>
callboost::spirit::traits::divide497         static T call(T& n)
498         {
499             return call(n, mpl::bool_<is_integral<T>::value>());
500         }
501     };
502 
503     // specialization for division by 10
504     template <>
505     struct divide<10>
506     {
507         template <typename T>
callboost::spirit::traits::divide508         static T call(T& n, T, int, mpl::true_)
509         {
510             return n / 10;
511         }
512 
513         template <typename T>
callboost::spirit::traits::divide514         static T call(T, T& num, int exp, mpl::false_)
515         {
516             // Allow ADL to find the correct overload for floor
517             using namespace std;
518             return floor(num / spirit::traits::pow10<T>(exp));
519         }
520 
521         template <typename T>
callboost::spirit::traits::divide522         static T call(T& n, T& num, int exp)
523         {
524             return call(n, num, exp, mpl::bool_<is_integral<T>::value>());
525         }
526 
527         template <typename T>
callboost::spirit::traits::divide528         static T call(T& n)
529         {
530             return call(n, n, 1, mpl::bool_<is_integral<T>::value>());
531         }
532     };
533 
534     ///////////////////////////////////////////////////////////////////////
535     template <unsigned Radix>
536     struct remainder
537     {
538         template <typename T>
callboost::spirit::traits::remainder539         static long call(T n, mpl::true_)
540         {
541             // this cast is safe since we know the result is not larger
542             // than Radix
543             return static_cast<long>(n % Radix);
544         }
545 
546         template <typename T>
callboost::spirit::traits::remainder547         static long call(T n, mpl::false_)
548         {
549             // Allow ADL to find the correct overload for fmod
550             using namespace std;
551             return cast_to_long::call(fmod(n, T(Radix)));
552         }
553 
554         template <typename T>
callboost::spirit::traits::remainder555         static long call(T n)
556         {
557             return call(n, mpl::bool_<is_integral<T>::value>());
558         }
559     };
560 }}}
561 
562 namespace boost { namespace spirit { namespace karma
563 {
564     ///////////////////////////////////////////////////////////////////////////
565     //
566     //  The int_inserter template takes care of the integer to string
567     //  conversion. If specified, the loop is unrolled for better performance.
568     //
569     //      Set the value BOOST_KARMA_NUMERICS_LOOP_UNROLL to some integer in
570     //      between 0 (no unrolling) and the largest expected generated integer
571     //      string length (complete unrolling).
572     //      If not specified, this value defaults to 6.
573     //
574     ///////////////////////////////////////////////////////////////////////////
575 #define BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX(z, x, data)                    \
576         if (!traits::test_zero(n)) {                                          \
577             int ch = radix_type::call(remainder_type::call(n));               \
578             n = divide_type::call(n, num, ++exp);                             \
579     /**/
580 
581 #define BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX(z, x, data)                    \
582             *sink = char(ch);                                                 \
583             ++sink;                                                           \
584         }                                                                     \
585     /**/
586 
587     template <
588         unsigned Radix, typename CharEncoding = unused_type
589       , typename Tag = unused_type>
590     struct int_inserter
591     {
592         typedef traits::convert_digit<Radix, CharEncoding, Tag> radix_type;
593         typedef traits::divide<Radix> divide_type;
594         typedef traits::remainder<Radix> remainder_type;
595 
596         template <typename OutputIterator, typename T>
597         static bool
callboost::spirit::karma::int_inserter598         call(OutputIterator& sink, T n, T& num, int exp)
599         {
600             // remainder_type::call returns n % Radix
601             int ch = radix_type::call(remainder_type::call(n));
602             n = divide_type::call(n, num, ++exp);
603 
604             BOOST_PP_REPEAT(
605                 BOOST_KARMA_NUMERICS_LOOP_UNROLL,
606                 BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX, _);
607 
608             if (!traits::test_zero(n))
609                 call(sink, n, num, exp);
610 
611             BOOST_PP_REPEAT(
612                 BOOST_KARMA_NUMERICS_LOOP_UNROLL,
613                 BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX, _);
614 
615             *sink = char(ch);
616             ++sink;
617             return true;
618         }
619 
620         //  Common code for integer string representations
621         template <typename OutputIterator, typename T>
622         static bool
callboost::spirit::karma::int_inserter623         call(OutputIterator& sink, T n)
624         {
625             return call(sink, n, n, 0);
626         }
627 
628     private:
629         // helper function returning the biggest number representable either in
630         // a boost::long_long_type (if this does exist) or in a plain long
631         // otherwise
632 #if defined(BOOST_HAS_LONG_LONG)
633         typedef boost::long_long_type biggest_long_type;
634 #else
635         typedef long biggest_long_type;
636 #endif
637 
max_longboost::spirit::karma::int_inserter638         static biggest_long_type max_long()
639         {
640             return (std::numeric_limits<biggest_long_type>::max)();
641         }
642 
643     public:
644         // Specialization for doubles and floats, falling back to long integers
645         // for representable values. These specializations speed up formatting
646         // of floating point numbers considerably as all the required
647         // arithmetics will be executed using integral data types.
648         template <typename OutputIterator>
649         static bool
callboost::spirit::karma::int_inserter650         call(OutputIterator& sink, long double n)
651         {
652             if (std::fabs(n) < max_long())
653             {
654                 biggest_long_type l((biggest_long_type)n);
655                 return call(sink, l, l, 0);
656             }
657             return call(sink, n, n, 0);
658         }
659         template <typename OutputIterator>
660         static bool
callboost::spirit::karma::int_inserter661         call(OutputIterator& sink, double n)
662         {
663             if (std::fabs(n) < max_long())
664             {
665                 biggest_long_type l((biggest_long_type)n);
666                 return call(sink, l, l, 0);
667             }
668             return call(sink, n, n, 0);
669         }
670         template <typename OutputIterator>
671         static bool
callboost::spirit::karma::int_inserter672         call(OutputIterator& sink, float n)
673         {
674             if (std::fabs(n) < max_long())
675             {
676                 biggest_long_type l((biggest_long_type)n);
677                 return call(sink, l, l, 0);
678             }
679             return call(sink, n, n, 0);
680         }
681     };
682 
683 #undef BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX
684 #undef BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX
685 
686     ///////////////////////////////////////////////////////////////////////////
687     //
688     //  The uint_inserter template takes care of the conversion of any integer
689     //  to a string, while interpreting the number as an unsigned type.
690     //
691     ///////////////////////////////////////////////////////////////////////////
692     template <
693         unsigned Radix, typename CharEncoding = unused_type
694       , typename Tag = unused_type>
695     struct uint_inserter : int_inserter<Radix, CharEncoding, Tag>
696     {
697         typedef int_inserter<Radix, CharEncoding, Tag> base_type;
698 
699         //  Common code for integer string representations
700         template <typename OutputIterator, typename T>
701         static bool
callboost::spirit::karma::uint_inserter702         call(OutputIterator& sink, T const& n)
703         {
704             typedef typename traits::absolute_value<T>::type type;
705             type un = type(n);
706             return base_type::call(sink, un, un, 0);
707         }
708     };
709 
710     ///////////////////////////////////////////////////////////////////////////
711     //
712     //  The sign_inserter template generates a sign for a given numeric value.
713     //
714     //    The parameter forcesign allows to generate a sign even for positive
715     //    numbers.
716     //
717     ///////////////////////////////////////////////////////////////////////////
718     struct sign_inserter
719     {
720         template <typename OutputIterator>
721         static bool
call_noforceboost::spirit::karma::sign_inserter722         call_noforce(OutputIterator& sink, bool is_zero, bool is_negative,
723             bool sign_if_zero)
724         {
725             // generate a sign for negative numbers only
726             if (is_negative || (is_zero && sign_if_zero)) {
727                 *sink = '-';
728                 ++sink;
729             }
730             return true;
731         }
732 
733         template <typename OutputIterator>
734         static bool
call_forceboost::spirit::karma::sign_inserter735         call_force(OutputIterator& sink, bool is_zero, bool is_negative,
736             bool sign_if_zero)
737         {
738             // generate a sign for all numbers except zero
739             if (!is_zero || sign_if_zero)
740                 *sink = is_negative ? '-' : '+';
741             else
742                 *sink = ' ';
743 
744             ++sink;
745             return true;
746         }
747 
748         template <typename OutputIterator>
749         static bool
callboost::spirit::karma::sign_inserter750         call(OutputIterator& sink, bool is_zero, bool is_negative
751           , bool forcesign, bool sign_if_zero = false)
752         {
753             return forcesign ?
754                 call_force(sink, is_zero, is_negative, sign_if_zero) :
755                 call_noforce(sink, is_zero, is_negative, sign_if_zero);
756         }
757     };
758 
759     ///////////////////////////////////////////////////////////////////////////
760     //  These are helper functions for the real policies allowing to generate
761     //  a single character and a string
762     ///////////////////////////////////////////////////////////////////////////
763     template <typename CharEncoding = unused_type, typename Tag = unused_type>
764     struct char_inserter
765     {
766         template <typename OutputIterator, typename Char>
callboost::spirit::karma::char_inserter767         static bool call(OutputIterator& sink, Char c)
768         {
769             return detail::generate_to(sink, c, CharEncoding(), Tag());
770         }
771     };
772 
773     template <typename CharEncoding = unused_type, typename Tag = unused_type>
774     struct string_inserter
775     {
776         template <typename OutputIterator, typename String>
callboost::spirit::karma::string_inserter777         static bool call(OutputIterator& sink, String str)
778         {
779             return detail::string_generate(sink, str, CharEncoding(), Tag());
780         }
781     };
782 
783 }}}
784 
785 #endif
786