$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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