$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r53529 - trunk/boost/date_time
From: andrey.semashev_at_[hidden]
Date: 2009-06-01 05:51:35
Author: andysem
Date: 2009-06-01 05:51:34 EDT (Mon, 01 Jun 2009)
New Revision: 53529
URL: http://svn.boost.org/trac/boost/changeset/53529
Log:
Optimized the from_stream_type function. In case if no locales support available the code was modified to fix possible character code truncation. Related to #287.
Text files modified: 
   trunk/boost/date_time/date_parsing.hpp |   142 ++++++++++++++++++++++----------------- 
   1 files changed, 79 insertions(+), 63 deletions(-)
Modified: trunk/boost/date_time/date_parsing.hpp
==============================================================================
--- trunk/boost/date_time/date_parsing.hpp	(original)
+++ trunk/boost/date_time/date_parsing.hpp	2009-06-01 05:51:34 EDT (Mon, 01 Jun 2009)
@@ -2,7 +2,7 @@
 #define _DATE_TIME_DATE_PARSING_HPP___
 
 /* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc.
- * Use, modification and distribution is subject to the 
+ * Use, modification and distribution is subject to the
  * Boost Software License, Version 1.0. (See accompanying
  * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
  * Author: Jeff Garland, Bart Garst
@@ -29,11 +29,11 @@
   //! A function to replace the std::transform( , , ,tolower) construct
   /*! This function simply takes a string, and changes all the characters
    * in that string to lowercase (according to the default system locale).
-   * In the event that a compiler does not support locales, the old 
+   * In the event that a compiler does not support locales, the old
    * C style tolower() is used.
    */
   inline
-  std::string 
+  std::string
   convert_to_lower(std::string inp)
   {
 #if !defined(BOOST_DATE_TIME_NO_LOCALE)
@@ -57,11 +57,11 @@
     /* Used by-value parameter because we change the string and may
      * want to preserve the original argument */
     template<class month_type>
-    inline unsigned short 
+    inline unsigned short
     month_str_to_ushort(std::string const& s) {
       if((s.at(0) >= '0') && (s.at(0) <= '9')) {
         return boost::lexical_cast<unsigned short>(s);
-      } 
+      }
       else {
         std::string str = convert_to_lower(s);
         typename month_type::month_map_ptr_type ptr = month_type::get_month_map_ptr();
@@ -81,8 +81,8 @@
      * 'size' can be sent in with: (greg_month::max)() (which 12),
      * (greg_weekday::max)() + 1 (which is 7) or date_time::NumSpecialValues */
     template<class charT>
-    short find_match(const charT* const* short_names, 
-                     const charT* const* long_names, 
+    short find_match(const charT* const* short_names,
+                     const charT* const* long_names,
                      short size,
                      const std::basic_string<charT>& s) {
       for(short i = 0; i < size; ++i){
@@ -92,12 +92,12 @@
       }
       return size; // not-found, return a value out of range
     }
-    
+
     //! Generic function to parse a delimited date (eg: 2002-02-10)
     /*! Accepted formats are: "2003-02-10" or " 2003-Feb-10" or
-     * "2003-Feburary-10" 
-     * The order in which the Month, Day, & Year appear in the argument 
-     * string can be accomodated by passing in the appropriate ymd_order_spec 
+     * "2003-Feburary-10"
+     * The order in which the Month, Day, & Year appear in the argument
+     * string can be accomodated by passing in the appropriate ymd_order_spec
      */
     template<class date_type>
     date_type
@@ -105,14 +105,14 @@
       std::string spec_str;
       if(order_spec == ymd_order_iso) {
         spec_str = "ymd";
-      } 
+      }
       else if(order_spec == ymd_order_dmy) {
         spec_str = "dmy";
-      } 
+      }
       else { // (order_spec == ymd_order_us)
         spec_str = "mdy";
       }
-      
+
       typedef typename date_type::year_type year_type;
       typedef typename date_type::month_type month_type;
       unsigned pos = 0;
@@ -129,21 +129,21 @@
       const char sep_char[] = {',','-','.',' ','/','\0'};
       char_separator_type sep(sep_char);
       tokenizer tok(s,sep);
-      for(tokenizer_iterator beg=tok.begin(); 
-          beg!=tok.end() && pos < spec_str.size(); 
+      for(tokenizer_iterator beg=tok.begin();
+          beg!=tok.end() && pos < spec_str.size();
           ++beg, ++pos) {
         switch(spec_str.at(pos)) {
-          case 'y': 
+          case 'y':
           {
             year = boost::lexical_cast<unsigned short>(*beg);
             break;
           }
-          case 'm': 
+          case 'm':
           {
             month = month_str_to_ushort<month_type>(*beg);
             break;
           }
-          case 'd': 
+          case 'd':
           {
             day = boost::lexical_cast<unsigned short>(*beg);
             break;
@@ -152,7 +152,7 @@
       }
       return date_type(year, month, day);
     }
-    
+
     //! Generic function to parse undelimited date (eg: 20020201)
     template<class date_type>
     date_type
@@ -162,16 +162,16 @@
       typedef typename date_type::year_type year_type;
       //typename date_type::ymd_type ymd((year_type::min)(),1,1);
       unsigned short y = 0, m = 0, d = 0;
-      
-      /* The two bool arguments state that parsing will not wrap 
-       * (only the first 8 characters will be parsed) and partial 
-       * strings will not be parsed. 
+
+      /* The two bool arguments state that parsing will not wrap
+       * (only the first 8 characters will be parsed) and partial
+       * strings will not be parsed.
        * Ex:
        * "2005121" will parse 2005 & 12, but not the "1" */
       boost::offset_separator osf(offsets, offsets+3, false, false);
-      
-      typedef typename boost::tokenizer<boost::offset_separator, 
-                                        std::basic_string<char>::const_iterator, 
+
+      typedef typename boost::tokenizer<boost::offset_separator,
+                                        std::basic_string<char>::const_iterator,
                                         std::basic_string<char> > tokenizer_type;
       tokenizer_type tok(s, osf);
       for(typename tokenizer_type::iterator ti=tok.begin(); ti!=tok.end();++ti) {
@@ -185,17 +185,17 @@
       }
       return date_type(y,m,d);
     }
-    
+
     //! Helper function for 'date gregorian::from_stream()'
     /*! Creates a string from the iterators that reference the
-     * begining & end of a char[] or string. All elements are 
+     * begining & end of a char[] or string. All elements are
      * used in output string */
     template<class date_type, class iterator_type>
-    inline 
+    inline
     date_type
-    from_stream_type(iterator_type& beg, 
-                     iterator_type& end,
-                     char) 
+    from_stream_type(iterator_type& beg,
+                     iterator_type const& end,
+                     char)
     {
       std::ostringstream ss;
       while(beg != end) {
@@ -203,16 +203,16 @@
       }
       return parse_date<date_type>(ss.str());
     }
- 
+
     //! Helper function for 'date gregorian::from_stream()'
     /*! Returns the first string found in the stream referenced by the
      * begining & end iterators */
     template<class date_type, class iterator_type>
-    inline 
+    inline
     date_type
-    from_stream_type(iterator_type& beg, 
-                     iterator_type& /* end */,
-                     std::string) 
+    from_stream_type(iterator_type& beg,
+                     iterator_type const& /* end */,
+                     std::string const&)
     {
       return parse_date<date_type>(*beg);
     }
@@ -221,22 +221,30 @@
      * parse_date<>()? In the mean time this gets us started... */
     //! Helper function for 'date gregorian::from_stream()'
     /*! Creates a string from the iterators that reference the
-     * begining & end of a wstring. All elements are 
+     * begining & end of a wstring. All elements are
      * used in output string */
     template<class date_type, class iterator_type>
-    inline 
-    date_type from_stream_type(iterator_type& beg, 
-                               iterator_type& end,
-                               wchar_t) 
+    inline
+    date_type from_stream_type(iterator_type& beg,
+                               iterator_type const& end,
+                               wchar_t)
     {
       std::ostringstream ss;
-      while(beg != end) {
 #if !defined(BOOST_DATE_TIME_NO_LOCALE)
-        ss << std::use_facet<std::ctype<wchar_t> >(std::locale()).narrow(*beg++, 'X'); // 'X' will cause exception to be thrown
+      std::locale loc;
+      std::ctype<wchar_t> const& fac = std::use_facet<std::ctype<wchar_t> >(loc);
+      while(beg != end) {
+        ss << fac.narrow(*beg++, 'X'); // 'X' will cause exception to be thrown
+      }
 #else
-        ss << ss.narrow(*beg++, 'X');
-#endif
+      while(beg != end) {
+        char c = 'X'; // 'X' will cause exception to be thrown
+        const wchar_t wc = *beg++;
+        if (wc >= 0 && wc <= 127)
+          c = static_cast< char >(wc);
+        ss << c;
       }
+#endif
       return parse_date<date_type>(ss.str());
     }
 #ifndef BOOST_NO_STD_WSTRING
@@ -244,21 +252,29 @@
     /*! Creates a string from the first wstring found in the stream
      * referenced by the begining & end iterators */
     template<class date_type, class iterator_type>
-    inline 
+    inline
     date_type
-    from_stream_type(iterator_type& beg, 
-                     iterator_type& /* end */,
-                     std::wstring) {
+    from_stream_type(iterator_type& beg,
+                     iterator_type const& /* end */,
+                     std::wstring const&) {
       std::wstring ws = *beg;
       std::ostringstream ss;
       std::wstring::iterator wsb = ws.begin(), wse = ws.end();
-      while(wsb != wse) {
 #if !defined(BOOST_DATE_TIME_NO_LOCALE)
-        ss << std::use_facet<std::ctype<wchar_t> >(std::locale()).narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown
+      std::locale loc;
+      std::ctype<wchar_t> const& fac = std::use_facet<std::ctype<wchar_t> >(loc);
+      while(wsb != wse) {
+        ss << fac.narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown
+      }
 #else
-        ss << ss.narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown
-#endif
+      while(wsb != wse) {
+        char c = 'X'; // 'X' will cause exception to be thrown
+        const wchar_t wc = *wsb++;
+        if (wc >= 0 && wc <= 127)
+          c = static_cast< char >(wc);
+        ss << c;
       }
+#endif
       return parse_date<date_type>(ss.str());
     }
 #endif // BOOST_NO_STD_WSTRING
@@ -267,27 +283,27 @@
 #else
     //! function called by wrapper functions: date_period_from_(w)string()
     template<class date_type, class charT>
-    period<date_type, typename date_type::duration_type> 
+    period<date_type, typename date_type::duration_type>
     from_simple_string_type(const std::basic_string<charT>& s){
       typedef typename std::basic_string<charT>::traits_type traits_type;
       typedef typename boost::char_separator<charT, traits_type> char_separator;
-      typedef typename boost::tokenizer<char_separator, 
-                                        typename std::basic_string<charT>::const_iterator, 
+      typedef typename boost::tokenizer<char_separator,
+                                        typename std::basic_string<charT>::const_iterator,
                                         std::basic_string<charT> > tokenizer;
       const charT sep_list[4] = {'[','/',']','\0'};
       char_separator sep(sep_list);
       tokenizer tokens(s, sep);
-      typename tokenizer::iterator tok_it = tokens.begin(); 
+      typename tokenizer::iterator tok_it = tokens.begin();
       std::basic_string<charT> date_string = *tok_it;
       // get 2 string iterators and generate a date from them
-      typename std::basic_string<charT>::iterator date_string_start = date_string.begin(), 
-                                                  date_string_end = date_string.end(); 
+      typename std::basic_string<charT>::iterator date_string_start = date_string.begin(),
+                                                  date_string_end = date_string.end();
       typedef typename std::iterator_traits<typename std::basic_string<charT>::iterator>::value_type value_type;
       date_type d1 = from_stream_type<date_type>(date_string_start, date_string_end, value_type());
       date_string = *(++tok_it); // next token
-      date_string_start = date_string.begin(), date_string_end = date_string.end(); 
+      date_string_start = date_string.begin(), date_string_end = date_string.end();
       date_type d2 = from_stream_type<date_type>(date_string_start, date_string_end, value_type());
-      return period<date_type, typename date_type::duration_type>(d1, d2); 
+      return period<date_type, typename date_type::duration_type>(d1, d2);
     }
 #endif