Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:47

0001 //  (C) Copyright Howard Hinnant
0002 //  (C) Copyright 2011 Vicente J. Botet Escriba
0003 //  Use, modification and distribution are subject to the Boost Software License,
0004 //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0005 //  http://www.boost.org/LICENSE_1_0.txt).
0006 //
0007 
0008 #ifndef BOOST_CHRONO_IO_TIME_POINT_GET_HPP
0009 #define BOOST_CHRONO_IO_TIME_POINT_GET_HPP
0010 
0011 #include <boost/chrono/config.hpp>
0012 #include <boost/chrono/detail/scan_keyword.hpp>
0013 #include <boost/chrono/io/time_point_units.hpp>
0014 #include <boost/chrono/io/duration_get.hpp>
0015 #include <boost/assert.hpp>
0016 #include <locale>
0017 #include <string>
0018 
0019 /**
0020  * Duration formatting facet for input.
0021  */
0022 namespace boost
0023 {
0024   namespace chrono
0025   {
0026 
0027     template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> >
0028     class time_point_get: public std::locale::facet
0029     {
0030     public:
0031       /**
0032        * Type of character the facet is instantiated on.
0033        */
0034       typedef CharT char_type;
0035       /**
0036        * Type of iterator used to scan the character buffer.
0037        */
0038       typedef InputIterator iter_type;
0039 
0040       /**
0041        * Construct a @c time_point_get facet.
0042        * @param refs
0043        * @Effects Construct a @c time_point_get facet.
0044        * If the @c refs argument is @c 0 then destruction of the object is
0045        * delegated to the @c locale, or locales, containing it. This allows
0046        * the user to ignore lifetime management issues. On the other had,
0047        * if @c refs is @c 1 then the object must be explicitly deleted;
0048        * the @c locale will not do so. In this case, the object can be
0049        * maintained across the lifetime of multiple locales.
0050        */
0051 
0052       explicit time_point_get(size_t refs = 0) :
0053         std::locale::facet(refs)
0054       {
0055       }
0056 
0057       /**
0058        * @param s start input stream iterator
0059        * @param end end input stream iterator
0060        * @param ios a reference to a ios_base
0061        * @param err the ios_base state
0062        * @param d the duration
0063        * @param pattern begin of the formatting pattern
0064        * @param pat_end end of the formatting pattern
0065        *
0066        * Requires: [pattern,pat_end) shall be a valid range.
0067        *
0068        * Effects: The function starts by evaluating err = std::ios_base::goodbit.
0069        * It then enters a loop, reading zero or more characters from s at
0070        * each iteration. Unless otherwise specified below, the loop
0071        * terminates when the first of the following conditions holds:
0072        * - The expression pattern == pat_end evaluates to true.
0073        * - The expression err == std::ios_base::goodbit evaluates to false.
0074        * - The expression s == end evaluates to true, in which case the
0075        * function evaluates err = std::ios_base::eofbit | std::ios_base::failbit.
0076        * - The next element of pattern is equal to '%', followed by a conversion
0077        * specifier character, the functions @c get_duration or @c get_epoch are called depending on
0078        * whether the format is @c 'd' or @c 'e'.
0079        * If the number of elements in the range [pattern,pat_end) is not
0080        * sufficient to unambiguously determine whether the conversion
0081        * specification is complete and valid, the function evaluates
0082        * err = std::ios_base::failbit. Otherwise, the function evaluates
0083        * s = do_get(s, end, ios, err, d). If err == std::ios_base::goodbit holds after
0084        * the evaluation of the expression, the function increments pattern to
0085        * point just past the end of the conversion specification and continues
0086        * looping.
0087        * - The expression isspace(*pattern, ios.getloc()) evaluates to true, in
0088        * which case the function first increments pattern until
0089        * pattern == pat_end || !isspace(*pattern, ios.getloc()) evaluates to true,
0090        * then advances s until s == end || !isspace(*s, ios.getloc()) is true,
0091        * and finally resumes looping.
0092        * - The next character read from s matches the element pointed to by
0093        * pattern in a case-insensitive comparison, in which case the function
0094        * evaluates ++pattern, ++s and continues looping. Otherwise, the function
0095        * evaluates err = std::ios_base::failbit.
0096        *
0097        * Returns: s
0098        */
0099 
0100       template <class Clock, class Duration>
0101       iter_type get(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err,
0102           time_point<Clock, Duration> &tp, const char_type *pattern, const char_type *pat_end) const
0103       {
0104         if (std::has_facet<time_point_units<CharT> >(is.getloc()))
0105         {
0106           time_point_units<CharT> const &facet = std::use_facet<time_point_units<CharT> >(is.getloc());
0107           return get(facet, i, e, is, err, tp, pattern, pat_end);
0108         }
0109         else
0110         {
0111           time_point_units_default<CharT> facet;
0112           return get(facet, i, e, is, err, tp, pattern, pat_end);
0113         }
0114       }
0115 
0116       template <class Clock, class Duration>
0117       iter_type get(time_point_units<CharT> const &facet, iter_type s, iter_type end, std::ios_base& ios,
0118           std::ios_base::iostate& err, time_point<Clock, Duration> &tp, const char_type *pattern,
0119           const char_type *pat_end) const
0120       {
0121 
0122         Duration d;
0123         bool duration_found = false, epoch_found = false;
0124 
0125         const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc());
0126         err = std::ios_base::goodbit;
0127         while (pattern != pat_end && err == std::ios_base::goodbit)
0128         {
0129           if (s == end)
0130           {
0131             err |= std::ios_base::eofbit;
0132             break;
0133           }
0134           if (ct.narrow(*pattern, 0) == '%')
0135           {
0136             if (++pattern == pat_end)
0137             {
0138               err |= std::ios_base::failbit;
0139               return s;
0140             }
0141             char cmd = ct.narrow(*pattern, 0);
0142             switch (cmd)
0143             {
0144             case 'd':
0145             {
0146               if (duration_found)
0147               {
0148                 err |= std::ios_base::failbit;
0149                 return s;
0150               }
0151               duration_found = true;
0152               s = get_duration(s, end, ios, err, d);
0153               if (err & (std::ios_base::badbit | std::ios_base::failbit))
0154               {
0155                 return s;
0156               }
0157               break;
0158             }
0159             case 'e':
0160             {
0161               if (epoch_found)
0162               {
0163                 err |= std::ios_base::failbit;
0164                 return s;
0165               }
0166               epoch_found = true;
0167               s = get_epoch<Clock> (facet, s, end, ios, err);
0168               if (err & (std::ios_base::badbit | std::ios_base::failbit))
0169               {
0170                 return s;
0171               }
0172               break;
0173             }
0174             default:
0175               BOOST_ASSERT(false && "Boost::Chrono internal error.");
0176               break;
0177             }
0178 
0179             ++pattern;
0180           }
0181           else if (ct.is(std::ctype_base::space, *pattern))
0182           {
0183             for (++pattern; pattern != pat_end && ct.is(std::ctype_base::space, *pattern); ++pattern)
0184               ;
0185             for (; s != end && ct.is(std::ctype_base::space, *s); ++s)
0186               ;
0187           }
0188           else if (ct.toupper(*s) == ct.toupper(*pattern))
0189           {
0190             ++s;
0191             ++pattern;
0192           }
0193           else
0194           {
0195             err |= std::ios_base::failbit;
0196           }
0197         }
0198 
0199         // Success!  Store it.
0200         tp = time_point<Clock, Duration> (d);
0201         return s;
0202       }
0203 
0204       /**
0205        *
0206        * @param s an input stream iterator
0207        * @param ios a reference to a ios_base
0208        * @param d the duration
0209        * Stores the duration pattern from the @c duration_unit facet in let say @c str. Last as if
0210        * @code
0211        *   return get(s, end, ios, err, ios, d, str.data(), str.data() + str.size());
0212        * @codeend
0213        * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name
0214        */
0215       template <class Clock, class Duration>
0216       iter_type get(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err,
0217           time_point<Clock, Duration> &tp) const
0218       {
0219         if (std::has_facet<time_point_units<CharT> >(is.getloc()))
0220         {
0221           time_point_units<CharT> const &facet = std::use_facet<time_point_units<CharT> >(is.getloc());
0222           std::basic_string<CharT> str = facet.get_pattern();
0223           return get(facet, i, e, is, err, tp, str.data(), str.data() + str.size());
0224         }
0225         else
0226         {
0227           time_point_units_default<CharT> facet;
0228           std::basic_string<CharT> str = facet.get_pattern();
0229           return get(facet, i, e, is, err, tp, str.data(), str.data() + str.size());
0230         }
0231       }
0232 
0233       /**
0234        * As if
0235        * @code
0236        * return facet.get(s, end, ios, err, d);
0237        * @endcode
0238        * where @c facet is either the @c duration_get facet associated to the @c ios or an instance of the default @c duration_get facet.
0239        *
0240        * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid duration.
0241        */
0242       template <typename Rep, typename Period>
0243       iter_type get_duration(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err,
0244           duration<Rep, Period>& d) const
0245       {
0246         if (std::has_facet<duration_get<CharT> >(is.getloc()))
0247         {
0248           duration_get<CharT> const &facet = std::use_facet<duration_get<CharT> >(is.getloc());
0249           return get_duration(facet, i, e, is, err, d);
0250         }
0251         else
0252         {
0253           duration_get<CharT> facet;
0254           return get_duration(facet, i, e, is, err, d);
0255         }
0256       }
0257 
0258       template <typename Rep, typename Period>
0259       iter_type get_duration(duration_get<CharT> const& facet, iter_type s, iter_type end, std::ios_base& ios,
0260           std::ios_base::iostate& err, duration<Rep, Period>& d) const
0261       {
0262         return facet.get(s, end, ios, err, d);
0263       }
0264 
0265       /**
0266        *
0267        * @Effects Let @c facet be the @c time_point_units facet associated to @c is or a new instance of the default @c time_point_units_default facet.
0268        * Let @c epoch be the epoch string associated to the Clock using this facet.
0269        * Scans @c i to match @c epoch or @c e is reached.
0270        *
0271        * If not match before the @c e is reached @c std::ios_base::failbit is set in @c err.
0272        * If @c e is reached @c std::ios_base::failbit is set in @c err.
0273        *
0274        * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid epoch.
0275        */
0276       template <class Clock>
0277       iter_type get_epoch(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err) const
0278       {
0279         if (std::has_facet<time_point_units<CharT> >(is.getloc()))
0280         {
0281           time_point_units<CharT> const &facet = std::use_facet<time_point_units<CharT> >(is.getloc());
0282           return get_epoch<Clock>(facet, i, e, is, err);
0283         }
0284         else
0285         {
0286           time_point_units_default<CharT> facet;
0287           return get_epoch<Clock>(facet, i, e, is, err);
0288         }
0289       }
0290 
0291       template <class Clock>
0292       iter_type get_epoch(time_point_units<CharT> const &facet, iter_type i, iter_type e, std::ios_base&,
0293           std::ios_base::iostate& err) const
0294       {
0295         const std::basic_string<CharT> epoch = facet.template get_epoch<Clock> ();
0296         std::ptrdiff_t k = chrono_detail::scan_keyword(i, e, &epoch, &epoch + 1,
0297         //~ std::use_facet<std::ctype<CharT> >(ios.getloc()),
0298             err) - &epoch;
0299         if (k == 1)
0300         {
0301           err |= std::ios_base::failbit;
0302           return i;
0303         }
0304         return i;
0305       }
0306 
0307       /**
0308        * Unique identifier for this type of facet.
0309        */
0310       static std::locale::id id;
0311 
0312       /**
0313        * @Effects Destroy the facet
0314        */
0315       ~time_point_get()
0316       {
0317       }
0318     };
0319 
0320     /**
0321      * Unique identifier for this type of facet.
0322      */
0323     template <class CharT, class InputIterator>
0324     std::locale::id time_point_get<CharT, InputIterator>::id;
0325 
0326   } // chrono
0327 }
0328 // boost
0329 
0330 #endif  // header