|
Boost-Commit : |
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
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