|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r55585 - in trunk/boost/spirit/home/karma: detail directive numeric numeric/detail
From: hartmut.kaiser_at_[hidden]
Date: 2009-08-14 16:25:03
Author: hkaiser
Date: 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
New Revision: 55585
URL: http://svn.boost.org/trac/boost/changeset/55585
Log:
Spirit: adjustments to real_policies to accommodate more use cases
Text files modified:
trunk/boost/spirit/home/karma/detail/output_iterator.hpp | 5 +
trunk/boost/spirit/home/karma/directive/right_alignment.hpp | 2
trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp | 75 +++++++++++++++++-----------
trunk/boost/spirit/home/karma/numeric/int.hpp | 12 ++--
trunk/boost/spirit/home/karma/numeric/real.hpp | 4 +
trunk/boost/spirit/home/karma/numeric/real_policies.hpp | 105 ++++++++++++++++++++++++++++-----------
6 files changed, 135 insertions(+), 68 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/output_iterator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/output_iterator.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/output_iterator.hpp 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -248,7 +248,7 @@
void enable(std::size_t width_)
{
tidy(); // release existing buffer
- width = width_;
+ width = (width_ == std::size_t(-1)) ? 0 : width_;
}
void tidy()
@@ -529,7 +529,8 @@
template <typename OutputIterator>
struct enable_buffering
{
- enable_buffering(OutputIterator& sink_, std::size_t width = 0)
+ enable_buffering(OutputIterator& sink_
+ , std::size_t width = std::size_t(-1))
: sink(sink_), prev_buffer(NULL), enabled(false)
{
buffer_data.enable(width);
Modified: trunk/boost/spirit/home/karma/directive/right_alignment.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/right_alignment.hpp (original)
+++ trunk/boost/spirit/home/karma/directive/right_alignment.hpp 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -98,7 +98,7 @@
} // re-enable counting
buffering.disable(); // do not perform buffering any more
-
+
// generate the left padding
detail::enable_counting<OutputIterator> counting(sink, buffering.buffer_size());
while(r && counting.count() < width)
Modified: trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -547,16 +547,15 @@
//
// The sign_inserter template generates a sign for a given numeric value.
//
- // The parameter ForceSign allows to generate a sign even for positive
+ // The parameter forcesign allows to generate a sign even for positive
// numbers.
//
///////////////////////////////////////////////////////////////////////////
- template <bool ForceSign>
struct sign_inserter
{
template <typename OutputIterator>
static bool
- call(OutputIterator& sink, bool /*is_zero*/, bool is_negative)
+ call_noforce(OutputIterator& sink, bool /*is_zero*/, bool is_negative)
{
// generate a sign for negative numbers only
if (is_negative) {
@@ -565,14 +564,10 @@
}
return true;
}
- };
- template <>
- struct sign_inserter<true>
- {
template <typename OutputIterator>
static bool
- call(OutputIterator& sink, bool is_zero, bool is_negative)
+ call_force(OutputIterator& sink, bool is_zero, bool is_negative)
{
// generate a sign for all numbers except zero
if (!is_zero)
@@ -583,6 +578,16 @@
++sink;
return true;
}
+
+ template <typename OutputIterator>
+ static bool
+ call(OutputIterator& sink, bool is_zero, bool is_negative
+ , bool forcesign)
+ {
+ return forcesign ?
+ call_force(sink, is_zero, is_negative) :
+ call_noforce(sink, is_zero, is_negative);
+ }
};
///////////////////////////////////////////////////////////////////////////
@@ -625,18 +630,20 @@
, typename Tag = unused_type>
struct real_inserter
{
- enum { force_sign = Policies::force_sign };
-
template <typename OutputIterator>
static bool
call (OutputIterator& sink, float n, Policies const& p = Policies())
{
int fpclass = (math::fpclassify)(n);
- if ((int)FP_NAN == fpclass)
- return Policies::template nan<force_sign, CharEncoding, Tag>(sink, n);
- else if ((int)FP_INFINITE == fpclass)
- return Policies::template inf<force_sign, CharEncoding, Tag>(sink, n);
- return call_n(sink, n, p);
+ if ((int)FP_NAN == fpclass) {
+ return Policies::template nan<CharEncoding, Tag>(
+ sink, n, p.force_sign(n));
+ }
+ else if ((int)FP_INFINITE == fpclass) {
+ return Policies::template inf<CharEncoding, Tag>(
+ sink, n, p.force_sign(n));
+ }
+ return p.template call<real_inserter>(sink, n, p);
}
template <typename OutputIterator>
@@ -644,11 +651,15 @@
call (OutputIterator& sink, double n, Policies const& p = Policies())
{
int fpclass = (math::fpclassify)(n);
- if ((int)FP_NAN == fpclass)
- return Policies::template nan<force_sign, CharEncoding, Tag>(sink, n);
- else if ((int)FP_INFINITE == fpclass)
- return Policies::template inf<force_sign, CharEncoding, Tag>(sink, n);
- return call_n(sink, n, p);
+ if ((int)FP_NAN == fpclass) {
+ return Policies::template nan<CharEncoding, Tag>(
+ sink, n, p.force_sign(n));
+ }
+ else if ((int)FP_INFINITE == fpclass) {
+ return Policies::template inf<CharEncoding, Tag>(
+ sink, n, p.force_sign(n));
+ }
+ return p.template call<real_inserter>(sink, n, p);
}
template <typename OutputIterator>
@@ -656,11 +667,15 @@
call (OutputIterator& sink, long double n, Policies const& p = Policies())
{
int fpclass = (math::fpclassify)(n);
- if ((int)FP_NAN == fpclass)
- return Policies::template nan<force_sign, CharEncoding, Tag>(sink, n);
- else if ((int)FP_INFINITE == fpclass)
- return Policies::template inf<force_sign, CharEncoding, Tag>(sink, n);
- return call_n(sink, n, p);
+ if ((int)FP_NAN == fpclass) {
+ return Policies::template nan<CharEncoding, Tag>(
+ sink, n, p.force_sign(n));
+ }
+ else if ((int)FP_INFINITE == fpclass) {
+ return Policies::template inf<CharEncoding, Tag>(
+ sink, n, p.force_sign(n));
+ }
+ return p.template call<real_inserter>(sink, n, p);
}
template <typename OutputIterator, typename U>
@@ -669,7 +684,7 @@
{
// we have no means of testing whether the number is normalized if
// the type is not float, double or long double
- return call_n(sink, T(n), p);
+ return p.template call<real_inserter>(sink, T(n), p);
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
@@ -686,6 +701,7 @@
call_n (OutputIterator& sink, U n, Policies const& p)
{
// prepare sign and get output format
+ bool force_sign = p.force_sign(n);
bool sign_val = false;
int flags = p.floatfield(n);
if (detail::is_negative(n))
@@ -769,14 +785,13 @@
}
// generate integer part
- bool r = p.template integer_part<force_sign>(
- sink, long_int_part, sign_val);
+ bool r = p.integer_part(sink, long_int_part, sign_val, force_sign);
// generate decimal point
- r = r && p.dot(sink, long_frac_part);
+ r = r && p.dot(sink, long_frac_part, precision);
// generate fractional part with the desired precision
- r = r && p.fraction_part(sink, long_frac_part, prec);
+ r = r && p.fraction_part(sink, long_frac_part, prec, precision);
if (r && 0 == (Policies::fmtflags::fixed & flags)) {
return p.template exponent<CharEncoding, Tag>(sink,
Modified: trunk/boost/spirit/home/karma/numeric/int.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/int.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/int.hpp 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -200,8 +200,8 @@
generate(OutputIterator& sink, Context&, Delimiter const& d
, Attribute const& attr)
{
- return sign_inserter<force_sign>::call(sink
- , detail::is_zero(attr), detail::is_negative(attr)) &&
+ return sign_inserter::call(sink, detail::is_zero(attr)
+ , detail::is_negative(attr), force_sign) &&
int_inserter<Radix, CharEncoding, Tag>::call(sink
, detail::absolute_value(attr)) &&
karma::delimit_out(sink, d); // always do post-delimiting
@@ -262,8 +262,8 @@
if (n_ != attr)
return false;
- return sign_inserter<force_sign>::call(sink
- , detail::is_zero(n_), detail::is_negative(n_)) &&
+ return sign_inserter::call(sink, detail::is_zero(n_)
+ , detail::is_negative(n_), force_sign) &&
int_inserter<Radix, CharEncoding, Tag>::call(sink
, detail::absolute_value(n_)) &&
karma::delimit_out(sink, d); // always do post-delimiting
@@ -275,8 +275,8 @@
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
- return sign_inserter<force_sign>::call(sink
- , detail::is_zero(n_), detail::is_negative(n_)) &&
+ return sign_inserter::call(sink, detail::is_zero(n_)
+ , detail::is_negative(n_), force_sign) &&
int_inserter<Radix, CharEncoding, Tag>::call(sink
, detail::absolute_value(n_)) &&
karma::delimit_out(sink, d); // always do post-delimiting
Modified: trunk/boost/spirit/home/karma/numeric/real.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/real.hpp 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -156,6 +156,8 @@
struct any_real_generator
: primitive_generator<any_real_generator<T, Policies, CharEncoding, Tag> >
{
+ typedef typename Policies::properties properties;
+
template <typename Context, typename Unused>
struct attribute
{
@@ -206,6 +208,8 @@
: primitive_generator<literal_real_generator<T, Policies, CharEncoding
, Tag, no_attribute> >
{
+ typedef typename Policies::properties properties;
+
template <typename Context, typename Unused>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
Modified: trunk/boost/spirit/home/karma/numeric/real_policies.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real_policies.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/real_policies.hpp 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -19,6 +19,8 @@
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/numeric/int.hpp>
+#include <boost/mpl/bool.hpp>
+
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
@@ -50,6 +52,14 @@
typedef T value_type;
///////////////////////////////////////////////////////////////////////
+ // By default the policy doesn't require any special iterator
+ // functionality. The floating point generator exposes its properties
+ // from here, so this needs to be updated in case other properties
+ // need to be implemented.
+ ///////////////////////////////////////////////////////////////////////
+ typedef mpl::int_<generator_properties::no_properties> properties;
+
+ ///////////////////////////////////////////////////////////////////////
// Specifies, which representation type to use during output
// generation.
///////////////////////////////////////////////////////////////////////
@@ -63,11 +73,38 @@
BOOST_SCOPED_ENUM_END
///////////////////////////////////////////////////////////////////////
+ // This is the main function used to generate the output for a
+ // floating point number. It is called by the real generator in order
+ // to perform the conversion. In theory all of the work can be
+ // implemented here, but it is the easiest to use existing
+ // functionality provided by the type specified by the template
+ // parameter `Inserter`.
+ //
+ // sink: the output iterator to use for generation
+ // n: the floating point number to convert
+ // p: the instance of the policy type used to instantiate this
+ // floating point generator.
+ ///////////////////////////////////////////////////////////////////////
+ template <typename Inserter, typename OutputIterator, typename Policies>
+ static bool
+ call (OutputIterator& sink, T n, Policies const& p)
+ {
+ return Inserter::call_n(sink, n, p);
+ }
+
+ ///////////////////////////////////////////////////////////////////////
// The default behavior is to not to require generating a sign. If
- // 'force_sign' is specified as true, then all generated numbers will
+ // 'force_sign()' returns true, then all generated numbers will
// have a sign ('+' or '-', zeros will have a space instead of a sign)
+ //
+ // n The floating point number to output. This can be used to
+ // adjust the required behavior depending on the value of
+ // this number.
///////////////////////////////////////////////////////////////////////
- static bool const force_sign = false;
+ static bool const force_sign(T)
+ {
+ return false;
+ }
///////////////////////////////////////////////////////////////////////
// Return whether trailing zero digits have to be emitted in the
@@ -135,16 +172,20 @@
///////////////////////////////////////////////////////////////////////
// Generate the integer part of the number.
//
- // sink The output iterator to use for generation
- // n The absolute value of the integer part of the floating
- // point number to convert (always non-negative).
- // sign The sign of the overall floating point number to convert.
+ // sink The output iterator to use for generation
+ // n The absolute value of the integer part of the floating
+ // point number to convert (always non-negative).
+ // sign The sign of the overall floating point number to
+ // convert.
+ // force_sign Whether a sign has to be generated even for
+ // non-negative numbers
///////////////////////////////////////////////////////////////////////
- template <bool ForceSign, typename OutputIterator>
- static bool integer_part (OutputIterator& sink, T n, bool sign)
+ template <typename OutputIterator>
+ static bool integer_part (OutputIterator& sink, T n, bool sign
+ , bool force_sign)
{
- return sign_inserter<ForceSign>::call(
- sink, detail::is_zero(n), sign) &&
+ return sign_inserter::call(
+ sink, detail::is_zero(n), sign, force_sign) &&
int_inserter<10>::call(sink, n);
}
@@ -158,6 +199,8 @@
// to the value returned from the precision() function
// earlier. I.e. a fractional part of 0.01234 is
// represented as 1234 when the 'Precision' is 5.
+ // precision The number of digits to emit as returned by the
+ // function 'precision()' above
//
// This is given to allow to decide, whether a decimal point
// has to be generated at all.
@@ -167,7 +210,7 @@
// function below.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
- static bool dot (OutputIterator& sink, T)
+ static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/)
{
return char_inserter<>::call(sink, '.'); // generate the dot by default
}
@@ -181,6 +224,10 @@
// the number of units which correspond to the 'Precision'.
// I.e. a fractional part of 0.01234 is represented as 1234
// when the 'precision_' parameter is 5.
+ // precision_ The corrected number of digits to emit (see note
+ // below)
+ // precision The number of digits to emit as returned by the
+ // function 'precision()' above
//
// Note: If trailing_zeros() does not return true the 'precision_'
// parameter will have been corrected from the value the
@@ -200,7 +247,7 @@
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
static bool fraction_part (OutputIterator& sink, T n
- , unsigned precision_)
+ , unsigned precision_, unsigned precision)
{
// allow for ADL to find the correct overload for floor and log10
using namespace std;
@@ -213,7 +260,9 @@
bool r = true;
for (/**/; r && digits < precision_; digits = digits + 1)
r = char_inserter<>::call(sink, '0');
- return r && int_inserter<10>::call(sink, n);
+ if (precision && r)
+ r = int_inserter<10>::call(sink, n);
+ return r;
}
///////////////////////////////////////////////////////////////////////
@@ -234,8 +283,8 @@
{
long abs_n = detail::absolute_value(n);
bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
- sign_inserter<false>::call(
- sink, detail::is_zero(n), detail::is_negative(n));
+ sign_inserter::call(sink, detail::is_zero(n)
+ , detail::is_negative(n), false);
// the C99 Standard requires at least two digits in the exponent
if (r && abs_n < 10)
@@ -247,8 +296,10 @@
// Print the textual representations for non-normal floats (NaN and
// Inf)
//
- // sink The output iterator to use for generation
- // n The (signed) floating point number to convert.
+ // sink The output iterator to use for generation
+ // n The (signed) floating point number to convert.
+ // force_sign Whether a sign has to be generated even for
+ // non-negative numbers
//
// The Tag template parameter is either of the type unused_type or
// describes the character class and conversion to be applied to any
@@ -258,23 +309,19 @@
// Note: These functions get called only if fpclassify() returned
// FP_INFINITY or FP_NAN.
///////////////////////////////////////////////////////////////////////
- template <
- bool ForceSign, typename CharEncoding, typename Tag
- , typename OutputIterator>
- static bool nan (OutputIterator& sink, T n)
+ template <typename CharEncoding, typename Tag, typename OutputIterator>
+ static bool nan (OutputIterator& sink, T n, bool force_sign)
{
- return sign_inserter<ForceSign>::call(
- sink, false, detail::is_negative(n)) &&
+ return sign_inserter::call(
+ sink, false, detail::is_negative(n), force_sign) &&
string_inserter<CharEncoding, Tag>::call(sink, "nan");
}
- template <
- bool ForceSign, typename CharEncoding, typename Tag
- , typename OutputIterator>
- static bool inf (OutputIterator& sink, T n)
+ template <typename CharEncoding, typename Tag, typename OutputIterator>
+ static bool inf (OutputIterator& sink, T n, bool force_sign)
{
- return sign_inserter<ForceSign>::call(
- sink, false, detail::is_negative(n)) &&
+ return sign_inserter::call(
+ sink, false, detail::is_negative(n), force_sign) &&
string_inserter<CharEncoding, Tag>::call(sink, "inf");
}
};
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk