Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r65501 - in sandbox/chrono/boost/chrono: . detail
From: vicente.botet_at_[hidden]
Date: 2010-09-21 00:53:52


Author: viboes
Date: 2010-09-21 00:53:48 EDT (Tue, 21 Sep 2010)
New Revision: 65501
URL: http://svn.boost.org/trac/boost/changeset/65501

Log:
Added chrono_io.hpp
Added:
   sandbox/chrono/boost/chrono/chrono_io.hpp (contents, props changed)
   sandbox/chrono/boost/chrono/detail/scan_keyword.hpp (contents, props changed)

Added: sandbox/chrono/boost/chrono/chrono_io.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/boost/chrono/chrono_io.hpp 2010-09-21 00:53:48 EDT (Tue, 21 Sep 2010)
@@ -0,0 +1,670 @@
+
+// chrono_io
+//
+// (C) Copyright Howard Hinnant
+// (C) Copyright 2010 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// This code was adapted by Vicente from Howard Hinnant's experimental work
+// on chrono i/o under lvm/libc++ to Boost
+
+#ifndef BOOST_CHRONO_CHRONO_IO_HPP
+#define BOOST_CHRONO_CHRONO_IO_HPP
+
+/*
+
+ chrono_io synopsis
+
+#include <boost/chrono.hpp>
+#include <boost/ratio/ratio_io.hpp>
+
+namespace boost
+{
+namespace chrono
+{
+
+template <class CharT>
+class duration_punct
+ : public locale::facet
+{
+public:
+ static locale::id id;
+
+ typedef basic_string<CharT> string_type;
+ enum {use_long, use_short};
+
+ explicit duration_punct(int use = use_long);
+
+ duration_punct(int use,
+ const string_type& long_seconds, const string_type& long_minutes,
+ const string_type& long_hours, const string_type& short_seconds,
+ const string_type& short_minutes, const string_type& short_hours);
+
+ duration_punct(int use, const duration_punct& d);
+
+ template <class Period> string_type short_name() const;
+ template <class Period> string_type long_name() const;
+ template <class Period> string_type name() const;
+
+ bool is_short_name() const;
+ bool is_long_name() const;
+};
+
+struct duration_short {};
+struct duration_long {};
+
+template <class CharT, class Traits>
+ basic_ostream<CharT, Traits>&
+ operator<<(basic_ostream<CharT, Traits>& os, duration_short);
+
+template <class CharT, class Traits>
+ basic_ostream<CharT, Traits>&
+ operator<<(basic_ostream<CharT, Traits>& os, duration_long);
+
+template <class CharT, class Traits, class Rep, class Period>
+ basic_ostream<CharT, Traits>&
+ operator<<(basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d);
+
+template <class CharT, class Traits, class Rep, class Period>
+ basic_istream<CharT, Traits>&
+ operator>>(basic_istream<CharT, Traits>& is, duration<Rep, Period>& d);
+
+template <class CharT, class Traits, class Duration>
+ basic_ostream<CharT, Traits>&
+ operator<<(basic_ostream<CharT, Traits>& os,
+ const time_point<monotonic_clock, Duration>& tp);
+
+template <class CharT, class Traits, class Duration>
+ basic_ostream<CharT, Traits>&
+ operator<<(basic_ostream<CharT, Traits>& os,
+ const time_point<high_resolution_clock, Duration>& tp);
+
+template <class CharT, class Traits, class Duration>
+ basic_ostream<CharT, Traits>&
+ operator<<(basic_ostream<CharT, Traits>& os,
+ const time_point<system_clock, Duration>& tp);
+
+template <class CharT, class Traits, class Duration>
+ basic_istream<CharT, Traits>&
+ operator>>(basic_istream<CharT, Traits>& is,
+ time_point<monotonic_clock, Duration>& tp);
+
+template <class CharT, class Traits, class Duration>
+ basic_istream<CharT, Traits>&
+ operator>>(basic_istream<CharT, Traits>& is,
+ time_point<high_resolution_clock, Duration>& tp);
+
+template <class CharT, class Traits, class Duration>
+ basic_istream<CharT, Traits>&
+ operator>>(basic_istream<CharT, Traits>& is,
+ time_point<system_clock, Duration>& tp);
+
+} // chrono
+} // boost
+
+*/
+
+#include <boost/chrono.hpp>
+#include <boost/ratio/ratio_io.hpp>
+#include <locale>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/is_signed.hpp>
+#include <boost/mpl/if.hpp>
+
+#include <boost/chrono/detail/scan_keyword.hpp>
+
+namespace boost
+{
+
+namespace chrono
+{
+
+template <class CharT>
+class duration_punct
+ : public std::locale::facet
+{
+public:
+ typedef std::basic_string<CharT> string_type;
+ enum {use_long, use_short};
+
+private:
+ bool use_short_;
+ string_type long_seconds_;
+ string_type long_minutes_;
+ string_type long_hours_;
+ string_type short_seconds_;
+ string_type short_minutes_;
+ string_type short_hours_;
+
+ template <class Period>
+ string_type short_name(Period) const
+ {return ::boost::ratio_string<Period, CharT>::short_name() + short_seconds_;}
+
+ string_type short_name(ratio<1>) const {return short_seconds_;}
+ string_type short_name(ratio<60>) const {return short_minutes_;}
+ string_type short_name(ratio<3600>) const {return short_hours_;}
+
+ template <class Period>
+ string_type long_name(Period) const
+ {return ::boost::ratio_string<Period, CharT>::long_name() + long_seconds_;}
+
+ string_type long_name(ratio<1>) const {return long_seconds_;}
+ string_type long_name(ratio<60>) const {return long_minutes_;}
+ string_type long_name(ratio<3600>) const {return long_hours_;}
+
+ void init_C();
+public:
+ static std::locale::id id;
+
+ explicit duration_punct(int use = use_long)
+ : use_short_(use) {init_C();}
+
+ duration_punct(int use,
+ const string_type& long_seconds, const string_type& long_minutes,
+ const string_type& long_hours, const string_type& short_seconds,
+ const string_type& short_minutes, const string_type& short_hours);
+
+ duration_punct(int use, const duration_punct& d);
+
+ template <class Period>
+ string_type short_name() const
+ {return short_name(typename Period::type());}
+
+ template <class Period>
+ string_type long_name() const
+ {return long_name(typename Period::type());}
+
+ template <class Period>
+ string_type name() const
+ {return use_short_ ? short_name<Period>() : long_name<Period>();}
+
+ bool is_short_name() const {return use_short_;}
+ bool is_long_name() const {return !use_short_;}
+};
+
+template <class CharT>
+std::locale::id
+duration_punct<CharT>::id;
+
+template <class CharT>
+void
+duration_punct<CharT>::init_C()
+{
+ short_seconds_ = CharT('s');
+ short_minutes_ = CharT('m');
+ short_hours_ = CharT('h');
+ const CharT s[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'};
+ const CharT m[] = {'m', 'i', 'n', 'u', 't', 'e', 's'};
+ const CharT h[] = {'h', 'o', 'u', 'r', 's'};
+ long_seconds_.assign(s, s + sizeof(s)/sizeof(s[0]));
+ long_minutes_.assign(m, m + sizeof(m)/sizeof(m[0]));
+ long_hours_.assign(h, h + sizeof(h)/sizeof(h[0]));
+}
+
+template <class CharT>
+duration_punct<CharT>::duration_punct(int use,
+ const string_type& long_seconds, const string_type& long_minutes,
+ const string_type& long_hours, const string_type& short_seconds,
+ const string_type& short_minutes, const string_type& short_hours)
+ : use_short_(use),
+ long_seconds_(long_seconds),
+ long_minutes_(long_minutes),
+ long_hours_(long_hours),
+ short_seconds_(short_seconds),
+ short_minutes_(short_minutes),
+ short_hours_(short_hours)
+{}
+
+template <class CharT>
+duration_punct<CharT>::duration_punct(int use, const duration_punct& d)
+ : use_short_(use),
+ long_seconds_(d.long_seconds_),
+ long_minutes_(d.long_minutes_),
+ long_hours_(d.long_hours_),
+ short_seconds_(d.short_seconds_),
+ short_minutes_(d.short_minutes_),
+ short_hours_(d.short_hours_)
+{}
+
+template <class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+duration_short(std::basic_ostream<CharT, Traits>& os)
+{
+ typedef duration_punct<CharT> _F;
+ std::locale loc = os.getloc();
+ if (std::has_facet<_F>(loc))
+ {
+ const _F& f = std::use_facet<_F>(loc);
+ if (f.is_long_name())
+ os.imbue(std::locale(loc, new _F(_F::use_short, f)));
+ }
+ else
+ os.imbue(std::locale(loc, new _F(_F::use_short)));
+ return os;
+}
+
+template <class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+duration_long(std::basic_ostream<CharT, Traits>& os)
+{
+ typedef duration_punct<CharT> _F;
+ std::locale loc = os.getloc();
+ if (std::has_facet<_F>(loc))
+ {
+ const _F& f = std::use_facet<_F>(loc);
+ if (f.is_short_name())
+ os.imbue(std::locale(loc, new _F(_F::use_long, f)));
+ }
+ return os;
+}
+
+template <class CharT, class Traits, class Rep, class Period>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d)
+{
+ typedef duration_punct<CharT> _F;
+ std::locale loc = os.getloc();
+ if (!std::has_facet<_F>(loc))
+ os.imbue(std::locale(loc, new _F));
+ const _F& f = std::use_facet<_F>(os.getloc());
+ return os << d.count() << ' ' << f.template name<Period>();
+}
+
+namespace chrono_detail {
+template <class Rep, bool = is_scalar<Rep>::value>
+struct duration_io_intermediate
+{
+ typedef Rep type;
+};
+
+template <class Rep>
+struct duration_io_intermediate<Rep, true>
+{
+ typedef typename mpl::if_c
+ <
+ is_floating_point<Rep>::value,
+ long double,
+ typename mpl::if_c
+ <
+ is_signed<Rep>::value,
+ long long,
+ unsigned long long
+ >::type
+ >::type type;
+};
+
+template <class T>
+T
+gcd(T x, T y)
+{
+ while (y != 0)
+ {
+ T old_x = x;
+ x = y;
+ y = old_x % y;
+ }
+ return x;
+}
+
+template <>
+long double
+inline
+gcd(long double , long double )
+{
+ return 1;
+}
+}
+
+template <class CharT, class Traits, class Rep, class Period>
+std::basic_istream<CharT, Traits>&
+operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d)
+{
+ typedef duration_punct<CharT> _F;
+ std::locale loc = is.getloc();
+ if (!std::has_facet<_F>(loc))
+ is.imbue(std::locale(loc, new _F));
+ loc = is.getloc();
+ const _F& f = std::use_facet<_F>(loc);
+ typedef typename chrono_detail::duration_io_intermediate<Rep>::type _IR;
+ _IR r;
+ // read value into r
+ is >> r;
+ if (is.good())
+ {
+ // now determine unit
+ typedef std::istreambuf_iterator<CharT, Traits> _I;
+ _I i(is);
+ _I e;
+ if (i != e && *i == ' ') // mandatory ' ' after value
+ {
+ ++i;
+ if (i != e)
+ {
+ // unit is num / den (yet to be determined)
+ unsigned long long num = 0;
+ unsigned long long den = 0;
+ if (*i == '[')
+ {
+ // parse [N/D]s or [N/D]seconds format
+ ++i;
+ CharT x;
+ is >> num >> x >> den;
+ if (!is.good() || x != '/')
+ {
+ is.setstate(is.failbit);
+ return is;
+ }
+ i = _I(is);
+ if (*i != ']')
+ {
+ is.setstate(is.failbit);
+ return is;
+ }
+ ++i;
+ const std::basic_string<CharT> units[] =
+ {
+ f.template long_name<ratio<1> >(),
+ f.template short_name<ratio<1> >()
+ };
+ std::ios_base::iostate err = std::ios_base::goodbit;
+ const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
+ units, units + sizeof(units)/sizeof(units[0]),
+ std::use_facet<std::ctype<CharT> >(loc),
+ err);
+ switch ((k - units) / 2)
+ {
+ case 0:
+ break;
+ default:
+ is.setstate(err);
+ return is;
+ }
+ }
+ else
+ {
+ // parse SI name, short or long
+ const std::basic_string<CharT> units[] =
+ {
+ f.template long_name<atto>(),
+ f.template short_name<atto>(),
+ f.template long_name<femto>(),
+ f.template short_name<femto>(),
+ f.template long_name<pico>(),
+ f.template short_name<pico>(),
+ f.template long_name<nano>(),
+ f.template short_name<nano>(),
+ f.template long_name<micro>(),
+ f.template short_name<micro>(),
+ f.template long_name<milli>(),
+ f.template short_name<milli>(),
+ f.template long_name<centi>(),
+ f.template short_name<centi>(),
+ f.template long_name<deci>(),
+ f.template short_name<deci>(),
+ f.template long_name<deca>(),
+ f.template short_name<deca>(),
+ f.template long_name<hecto>(),
+ f.template short_name<hecto>(),
+ f.template long_name<kilo>(),
+ f.template short_name<kilo>(),
+ f.template long_name<mega>(),
+ f.template short_name<mega>(),
+ f.template long_name<giga>(),
+ f.template short_name<giga>(),
+ f.template long_name<tera>(),
+ f.template short_name<tera>(),
+ f.template long_name<peta>(),
+ f.template short_name<peta>(),
+ f.template long_name<exa>(),
+ f.template short_name<exa>(),
+ f.template long_name<ratio<1> >(),
+ f.template short_name<ratio<1> >(),
+ f.template long_name<ratio<60> >(),
+ f.template short_name<ratio<60> >(),
+ f.template long_name<ratio<3600> >(),
+ f.template short_name<ratio<3600> >()
+ };
+ std::ios_base::iostate err = std::ios_base::goodbit;
+ const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e,
+ units, units + sizeof(units)/sizeof(units[0]),
+ std::use_facet<std::ctype<CharT> >(loc),
+ err);
+ switch ((k - units) / 2)
+ {
+ case 0:
+ num = 1ULL;
+ den = 1000000000000000000ULL;
+ break;
+ case 1:
+ num = 1ULL;
+ den = 1000000000000000ULL;
+ break;
+ case 2:
+ num = 1ULL;
+ den = 1000000000000ULL;
+ break;
+ case 3:
+ num = 1ULL;
+ den = 1000000000ULL;
+ break;
+ case 4:
+ num = 1ULL;
+ den = 1000000ULL;
+ break;
+ case 5:
+ num = 1ULL;
+ den = 1000ULL;
+ break;
+ case 6:
+ num = 1ULL;
+ den = 100ULL;
+ break;
+ case 7:
+ num = 1ULL;
+ den = 10ULL;
+ break;
+ case 8:
+ num = 10ULL;
+ den = 1ULL;
+ break;
+ case 9:
+ num = 100ULL;
+ den = 1ULL;
+ break;
+ case 10:
+ num = 1000ULL;
+ den = 1ULL;
+ break;
+ case 11:
+ num = 1000000ULL;
+ den = 1ULL;
+ break;
+ case 12:
+ num = 1000000000ULL;
+ den = 1ULL;
+ break;
+ case 13:
+ num = 1000000000000ULL;
+ den = 1ULL;
+ break;
+ case 14:
+ num = 1000000000000000ULL;
+ den = 1ULL;
+ break;
+ case 15:
+ num = 1000000000000000000ULL;
+ den = 1ULL;
+ break;
+ case 16:
+ num = 1;
+ den = 1;
+ break;
+ case 17:
+ num = 60;
+ den = 1;
+ break;
+ case 18:
+ num = 3600;
+ den = 1;
+ break;
+ default:
+ is.setstate(err);
+ return is;
+ }
+ }
+ // unit is num/den
+ // r should be multiplied by (num/den) / Period
+ // Reduce (num/den) / Period to lowest terms
+ unsigned long long gcd_n1_n2 = chrono_detail::gcd<unsigned long long>(num, Period::num);
+ unsigned long long gcd_d1_d2 = chrono_detail::gcd<unsigned long long>(den, Period::den);
+ num /= gcd_n1_n2;
+ den /= gcd_d1_d2;
+ unsigned long long n2 = Period::num / gcd_n1_n2;
+ unsigned long long d2 = Period::den / gcd_d1_d2;
+ if (num > std::numeric_limits<unsigned long long>::max() / d2 ||
+ den > std::numeric_limits<unsigned long long>::max() / n2)
+ {
+ // (num/den) / Period overflows
+ is.setstate(is.failbit);
+ return is;
+ }
+ num *= d2;
+ den *= n2;
+ // num / den is now factor to multiply by r
+ typedef typename common_type<_IR, unsigned long long>::type _CT;
+ if (is_integral<_IR>::value)
+ {
+ // Reduce r * num / den
+ _CT t = chrono_detail::gcd<_CT>(r, den);
+ r /= t;
+ den /= t;
+ if (den != 1)
+ {
+ // Conversion to Period is integral and not exact
+ is.setstate(is.failbit);
+ return is;
+ }
+ }
+ if (r > duration_values<_CT>::max() / num)
+ {
+ // Conversion to Period overflowed
+ is.setstate(is.failbit);
+ return is;
+ }
+ _CT t = r * num;
+ t /= den;
+ if (duration_values<Rep>::max() < t)
+ {
+ // Conversion to Period overflowed
+ is.setstate(is.failbit);
+ return is;
+ }
+ // Success! Store it.
+ r = Rep(t);
+ d = duration<Rep, Period>(r);
+ }
+ else
+ is.setstate(is.failbit | is.eofbit);
+ }
+ else
+ {
+ if (i == e)
+ is.setstate(is.eofbit);
+ is.setstate(is.failbit);
+ }
+ }
+ else
+ is.setstate(is.failbit);
+ return is;
+}
+
+#ifdef BOOST_CHRONO_HAS_CLOCK_MONOTONIC
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os,
+ const time_point<monotonic_clock, Duration>& tp)
+{
+ return os << tp.time_since_epoch() << " since boot";
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_istream<CharT, Traits>&
+operator>>(std::basic_istream<CharT, Traits>& is,
+ time_point<monotonic_clock, Duration>& tp)
+{
+ Duration d;
+ is >> d;
+ if (is.good())
+ {
+ const CharT u[] = {' ', 's', 'i', 'n', 'c', 'e', ' ', 'b', 'o', 'o', 't'};
+ const std::basic_string<CharT> units(u, u + sizeof(u)/sizeof(u[0]));
+ std::ios_base::iostate err = std::ios_base::goodbit;
+ typedef std::istreambuf_iterator<CharT, Traits> _I;
+ _I i(is);
+ _I e;
+ std::ptrdiff_t k = chrono_detail::scan_keyword(i, e,
+ &units, &units + 1,
+ std::use_facet<std::ctype<CharT> >(is.getloc()),
+ err) - &units;
+ if (k == 1)
+ {
+ // failed to read epoch string
+ is.setstate(err);
+ return is;
+ }
+ tp = time_point<monotonic_clock, Duration>(d);
+ }
+ else
+ is.setstate(is.failbit);
+ return is;
+}
+#endif
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os,
+ const time_point<system_clock, Duration>& tp)
+{
+ return os << tp.time_since_epoch() << " since Jan 1, 1970";
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_istream<CharT, Traits>&
+operator>>(std::basic_istream<CharT, Traits>& is,
+ time_point<system_clock, Duration>& tp)
+{
+ Duration d;
+ is >> d;
+ if (is.good())
+ {
+ const CharT u[] = {' ', 's', 'i', 'n', 'c', 'e', ' ', 'J', 'a',
+ 'n', ' ', '1', ',', ' ', '1', '9', '7', '0'};
+ const std::basic_string<CharT> units(u, u + sizeof(u)/sizeof(u[0]));
+ std::ios_base::iostate err = std::ios_base::goodbit;
+ typedef std::istreambuf_iterator<CharT, Traits> _I;
+ _I i(is);
+ _I e;
+ std::ptrdiff_t k = chrono_detail::scan_keyword(i, e,
+ &units, &units + 1,
+ std::use_facet<std::ctype<CharT> >(is.getloc()),
+ err) - &units;
+ if (k == 1)
+ {
+ // failed to read epoch string
+ is.setstate(err);
+ return is;
+ }
+ tp = time_point<system_clock, Duration>(d);
+ }
+ else
+ is.setstate(is.failbit);
+ return is;
+}
+
+} // chrono
+
+}
+
+#endif // BOOST_CHRONO_CHRONO_IO_HPP

Added: sandbox/chrono/boost/chrono/detail/scan_keyword.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/boost/chrono/detail/scan_keyword.hpp 2010-09-21 00:53:48 EDT (Tue, 21 Sep 2010)
@@ -0,0 +1,163 @@
+// scan_keyword.hpp --------------------------------------------------------------//
+
+// Copyright 2009-2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+//===-------------------------- locale ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This code was adapted to Boost by Vicente from locale file on llvm/libc++
+
+#ifndef _LIBCPP_LOCALE
+
+#ifndef BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP
+#define BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP
+
+#include <boost/chrono/config.hpp>
+#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
+#include <ios>
+#include <exception>
+
+namespace boost {
+ using interprocess::unique_ptr;
+
+namespace chrono {
+namespace chrono_detail {
+
+// scan_keyword
+// Scans [b, e) until a match is found in the basic_strings range
+// [kb, ke) or until it can be shown that there is no match in [kb, ke).
+// b will be incremented (visibly), consuming CharT until a match is found
+// or proved to not exist. A keyword may be "", in which will match anything.
+// If one keyword is a prefix of another, and the next CharT in the input
+// might match another keyword, the algorithm will attempt to find the longest
+// matching keyword. If the longer matching keyword ends up not matching, then
+// no keyword match is found. If no keyword match is found, ke is returned
+// and failbit is set in err.
+// Else an iterator pointing to the matching keyword is found. If more than
+// one keyword matches, an iterator to the first matching keyword is returned.
+// If on exit b == e, eofbit is set in err. If case_senstive is false,
+// ct is used to force to lower case before comparing characters.
+// Examples:
+// Keywords: "a", "abb"
+// If the input is "a", the first keyword matches and eofbit is set.
+// If the input is "abc", no match is found and "ab" are consumed.
+
+template <class InputIterator, class ForwardIterator, class Ctype>
+ForwardIterator
+scan_keyword(InputIterator& b, InputIterator e,
+ ForwardIterator kb, ForwardIterator ke,
+ const Ctype& ct, std::ios_base::iostate& err,
+ bool case_sensitive = true)
+{
+ typedef typename std::iterator_traits<InputIterator>::value_type CharT;
+ size_t nkw = std::distance(kb, ke);
+ const unsigned char doesnt_match = '\0';
+ const unsigned char might_match = '\1';
+ const unsigned char does_match = '\2';
+ unsigned char statbuf[100];
+ unsigned char* status = statbuf;
+ unique_ptr<unsigned char, void(*)(void*)> stat_hold(0, free);
+ if (nkw > sizeof(statbuf))
+ {
+ status = (unsigned char*)malloc(nkw);
+ if (status == 0)
+ throw std::bad_alloc();
+ stat_hold.reset(status);
+ }
+ size_t n_might_match = nkw; // At this point, any keyword might match
+ size_t n_does_match = 0; // but none of them definitely do
+ // Initialize all statuses to might_match, except for "" keywords are does_match
+ unsigned char* st = status;
+ for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
+ {
+ if (!ky->empty())
+ *st = might_match;
+ else
+ {
+ *st = does_match;
+ --n_might_match;
+ ++n_does_match;
+ }
+ }
+ // While there might be a match, test keywords against the next CharT
+ for (size_t indx = 0; b != e && n_might_match > 0; ++indx)
+ {
+ // Peek at the next CharT but don't consume it
+ CharT c = *b;
+ if (!case_sensitive)
+ c = ct.toupper(c);
+ bool consume = false;
+ // For each keyword which might match, see if the indx character is c
+ // If a match if found, consume c
+ // If a match is found, and that is the last character in the keyword,
+ // then that keyword matches.
+ // If the keyword doesn't match this character, then change the keyword
+ // to doesn't match
+ st = status;
+ for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
+ {
+ if (*st == might_match)
+ {
+ CharT kc = (*ky)[indx];
+ if (!case_sensitive)
+ kc = ct.toupper(kc);
+ if (c == kc)
+ {
+ consume = true;
+ if (ky->size() == indx+1)
+ {
+ *st = does_match;
+ --n_might_match;
+ ++n_does_match;
+ }
+ }
+ else
+ {
+ *st = doesnt_match;
+ --n_might_match;
+ }
+ }
+ }
+ // consume if we matched a character
+ if (consume)
+ {
+ ++b;
+ // If we consumed a character and there might be a matched keyword that
+ // was marked matched on a previous iteration, then such keywords
+ // which are now marked as not matching.
+ if (n_might_match + n_does_match > 1)
+ {
+ st = status;
+ for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
+ {
+ if (*st == does_match && ky->size() != indx+1)
+ {
+ *st = doesnt_match;
+ --n_does_match;
+ }
+ }
+ }
+ }
+ }
+ // We've exited the loop because we hit eof and/or we have no more "might matches".
+ if (b == e)
+ err |= std::ios_base::eofbit;
+ // Return the first matching result
+ for (st = status; kb != ke; ++kb, ++st)
+ if (*st == does_match)
+ break;
+ if (kb == ke)
+ err |= std::ios_base::failbit;
+ return kb;
+}
+}
+}
+}
+#endif // BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP


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