Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/date_time/date_parsing.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 #ifndef _DATE_TIME_DATE_PARSING_HPP___ | |
2 #define _DATE_TIME_DATE_PARSING_HPP___ | |
3 | |
4 /* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. | |
5 * Use, modification and distribution is subject to the | |
6 * Boost Software License, Version 1.0. (See accompanying | |
7 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
8 * Author: Jeff Garland, Bart Garst | |
9 * $Date: 2012-09-30 16:25:22 -0700 (Sun, 30 Sep 2012) $ | |
10 */ | |
11 | |
12 #include <string> | |
13 #include <iterator> | |
14 #include <algorithm> | |
15 #include <boost/tokenizer.hpp> | |
16 #include <boost/lexical_cast.hpp> | |
17 #include <boost/date_time/compiler_config.hpp> | |
18 #include <boost/date_time/parse_format_base.hpp> | |
19 | |
20 #if defined(BOOST_DATE_TIME_NO_LOCALE) | |
21 #include <cctype> // ::tolower(int) | |
22 #else | |
23 #include <locale> // std::tolower(char, locale) | |
24 #endif | |
25 | |
26 namespace boost { | |
27 namespace date_time { | |
28 | |
29 //! A function to replace the std::transform( , , ,tolower) construct | |
30 /*! This function simply takes a string, and changes all the characters | |
31 * in that string to lowercase (according to the default system locale). | |
32 * In the event that a compiler does not support locales, the old | |
33 * C style tolower() is used. | |
34 */ | |
35 inline | |
36 std::string | |
37 convert_to_lower(std::string inp) | |
38 { | |
39 #if !defined(BOOST_DATE_TIME_NO_LOCALE) | |
40 const std::locale loc(std::locale::classic()); | |
41 #endif | |
42 std::string::size_type i = 0, n = inp.length(); | |
43 for (; i < n; ++i) { | |
44 inp[i] = | |
45 #if defined(BOOST_DATE_TIME_NO_LOCALE) | |
46 static_cast<char>(std::tolower(inp[i])); | |
47 #else | |
48 // tolower and others were brought in to std for borland >= v564 | |
49 // in compiler_config.hpp | |
50 std::tolower(inp[i], loc); | |
51 #endif | |
52 } | |
53 return inp; | |
54 } | |
55 | |
56 //! Helper function for parse_date. | |
57 /* Used by-value parameter because we change the string and may | |
58 * want to preserve the original argument */ | |
59 template<class month_type> | |
60 inline unsigned short | |
61 month_str_to_ushort(std::string const& s) { | |
62 if((s.at(0) >= '0') && (s.at(0) <= '9')) { | |
63 return boost::lexical_cast<unsigned short>(s); | |
64 } | |
65 else { | |
66 std::string str = convert_to_lower(s); | |
67 typename month_type::month_map_ptr_type ptr = month_type::get_month_map_ptr(); | |
68 typename month_type::month_map_type::iterator iter = ptr->find(str); | |
69 if(iter != ptr->end()) { // required for STLport | |
70 return iter->second; | |
71 } | |
72 } | |
73 return 13; // intentionally out of range - name not found | |
74 } | |
75 | |
76 //! Find index of a string in either of 2 arrays | |
77 /*! find_match searches both arrays for a match to 's'. Both arrays | |
78 * must contain 'size' elements. The index of the match is returned. | |
79 * If no match is found, 'size' is returned. | |
80 * Ex. "Jan" returns 0, "Dec" returns 11, "Tue" returns 2. | |
81 * 'size' can be sent in with: (greg_month::max)() (which 12), | |
82 * (greg_weekday::max)() + 1 (which is 7) or date_time::NumSpecialValues */ | |
83 template<class charT> | |
84 short find_match(const charT* const* short_names, | |
85 const charT* const* long_names, | |
86 short size, | |
87 const std::basic_string<charT>& s) { | |
88 for(short i = 0; i < size; ++i){ | |
89 if(short_names[i] == s || long_names[i] == s){ | |
90 return i; | |
91 } | |
92 } | |
93 return size; // not-found, return a value out of range | |
94 } | |
95 | |
96 //! Generic function to parse a delimited date (eg: 2002-02-10) | |
97 /*! Accepted formats are: "2003-02-10" or " 2003-Feb-10" or | |
98 * "2003-Feburary-10" | |
99 * The order in which the Month, Day, & Year appear in the argument | |
100 * string can be accomodated by passing in the appropriate ymd_order_spec | |
101 */ | |
102 template<class date_type> | |
103 date_type | |
104 parse_date(const std::string& s, int order_spec = ymd_order_iso) { | |
105 std::string spec_str; | |
106 if(order_spec == ymd_order_iso) { | |
107 spec_str = "ymd"; | |
108 } | |
109 else if(order_spec == ymd_order_dmy) { | |
110 spec_str = "dmy"; | |
111 } | |
112 else { // (order_spec == ymd_order_us) | |
113 spec_str = "mdy"; | |
114 } | |
115 | |
116 typedef typename date_type::year_type year_type; | |
117 typedef typename date_type::month_type month_type; | |
118 unsigned pos = 0; | |
119 unsigned short year(0), month(0), day(0); | |
120 typedef typename std::basic_string<char>::traits_type traits_type; | |
121 typedef boost::char_separator<char, traits_type> char_separator_type; | |
122 typedef boost::tokenizer<char_separator_type, | |
123 std::basic_string<char>::const_iterator, | |
124 std::basic_string<char> > tokenizer; | |
125 typedef boost::tokenizer<char_separator_type, | |
126 std::basic_string<char>::const_iterator, | |
127 std::basic_string<char> >::iterator tokenizer_iterator; | |
128 // may need more delimiters, these work for the regression tests | |
129 const char sep_char[] = {',','-','.',' ','/','\0'}; | |
130 char_separator_type sep(sep_char); | |
131 tokenizer tok(s,sep); | |
132 for(tokenizer_iterator beg=tok.begin(); | |
133 beg!=tok.end() && pos < spec_str.size(); | |
134 ++beg, ++pos) { | |
135 switch(spec_str.at(pos)) { | |
136 case 'y': | |
137 { | |
138 year = boost::lexical_cast<unsigned short>(*beg); | |
139 break; | |
140 } | |
141 case 'm': | |
142 { | |
143 month = month_str_to_ushort<month_type>(*beg); | |
144 break; | |
145 } | |
146 case 'd': | |
147 { | |
148 day = boost::lexical_cast<unsigned short>(*beg); | |
149 break; | |
150 } | |
151 default: break; | |
152 } //switch | |
153 } | |
154 return date_type(year, month, day); | |
155 } | |
156 | |
157 //! Generic function to parse undelimited date (eg: 20020201) | |
158 template<class date_type> | |
159 date_type | |
160 parse_undelimited_date(const std::string& s) { | |
161 int offsets[] = {4,2,2}; | |
162 int pos = 0; | |
163 typedef typename date_type::year_type year_type; | |
164 //typename date_type::ymd_type ymd((year_type::min)(),1,1); | |
165 unsigned short y = 0, m = 0, d = 0; | |
166 | |
167 /* The two bool arguments state that parsing will not wrap | |
168 * (only the first 8 characters will be parsed) and partial | |
169 * strings will not be parsed. | |
170 * Ex: | |
171 * "2005121" will parse 2005 & 12, but not the "1" */ | |
172 boost::offset_separator osf(offsets, offsets+3, false, false); | |
173 | |
174 typedef typename boost::tokenizer<boost::offset_separator, | |
175 std::basic_string<char>::const_iterator, | |
176 std::basic_string<char> > tokenizer_type; | |
177 tokenizer_type tok(s, osf); | |
178 for(typename tokenizer_type::iterator ti=tok.begin(); ti!=tok.end();++ti) { | |
179 unsigned short i = boost::lexical_cast<unsigned short>(*ti); | |
180 switch(pos) { | |
181 case 0: y = i; break; | |
182 case 1: m = i; break; | |
183 case 2: d = i; break; | |
184 default: break; | |
185 } | |
186 pos++; | |
187 } | |
188 return date_type(y,m,d); | |
189 } | |
190 | |
191 //! Helper function for 'date gregorian::from_stream()' | |
192 /*! Creates a string from the iterators that reference the | |
193 * begining & end of a char[] or string. All elements are | |
194 * used in output string */ | |
195 template<class date_type, class iterator_type> | |
196 inline | |
197 date_type | |
198 from_stream_type(iterator_type& beg, | |
199 iterator_type const& end, | |
200 char) | |
201 { | |
202 std::ostringstream ss; | |
203 while(beg != end) { | |
204 ss << *beg++; | |
205 } | |
206 return parse_date<date_type>(ss.str()); | |
207 } | |
208 | |
209 //! Helper function for 'date gregorian::from_stream()' | |
210 /*! Returns the first string found in the stream referenced by the | |
211 * begining & end iterators */ | |
212 template<class date_type, class iterator_type> | |
213 inline | |
214 date_type | |
215 from_stream_type(iterator_type& beg, | |
216 iterator_type const& /* end */, | |
217 std::string const&) | |
218 { | |
219 return parse_date<date_type>(*beg); | |
220 } | |
221 | |
222 /* I believe the wchar stuff would be best elsewhere, perhaps in | |
223 * parse_date<>()? In the mean time this gets us started... */ | |
224 //! Helper function for 'date gregorian::from_stream()' | |
225 /*! Creates a string from the iterators that reference the | |
226 * begining & end of a wstring. All elements are | |
227 * used in output string */ | |
228 template<class date_type, class iterator_type> | |
229 inline | |
230 date_type from_stream_type(iterator_type& beg, | |
231 iterator_type const& end, | |
232 wchar_t) | |
233 { | |
234 std::ostringstream ss; | |
235 #if !defined(BOOST_DATE_TIME_NO_LOCALE) | |
236 std::locale loc; | |
237 std::ctype<wchar_t> const& fac = std::use_facet<std::ctype<wchar_t> >(loc); | |
238 while(beg != end) { | |
239 ss << fac.narrow(*beg++, 'X'); // 'X' will cause exception to be thrown | |
240 } | |
241 #else | |
242 while(beg != end) { | |
243 char c = 'X'; // 'X' will cause exception to be thrown | |
244 const wchar_t wc = *beg++; | |
245 if (wc >= 0 && wc <= 127) | |
246 c = static_cast< char >(wc); | |
247 ss << c; | |
248 } | |
249 #endif | |
250 return parse_date<date_type>(ss.str()); | |
251 } | |
252 #ifndef BOOST_NO_STD_WSTRING | |
253 //! Helper function for 'date gregorian::from_stream()' | |
254 /*! Creates a string from the first wstring found in the stream | |
255 * referenced by the begining & end iterators */ | |
256 template<class date_type, class iterator_type> | |
257 inline | |
258 date_type | |
259 from_stream_type(iterator_type& beg, | |
260 iterator_type const& /* end */, | |
261 std::wstring const&) { | |
262 std::wstring ws = *beg; | |
263 std::ostringstream ss; | |
264 std::wstring::iterator wsb = ws.begin(), wse = ws.end(); | |
265 #if !defined(BOOST_DATE_TIME_NO_LOCALE) | |
266 std::locale loc; | |
267 std::ctype<wchar_t> const& fac = std::use_facet<std::ctype<wchar_t> >(loc); | |
268 while(wsb != wse) { | |
269 ss << fac.narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown | |
270 } | |
271 #else | |
272 while(wsb != wse) { | |
273 char c = 'X'; // 'X' will cause exception to be thrown | |
274 const wchar_t wc = *wsb++; | |
275 if (wc >= 0 && wc <= 127) | |
276 c = static_cast< char >(wc); | |
277 ss << c; | |
278 } | |
279 #endif | |
280 return parse_date<date_type>(ss.str()); | |
281 } | |
282 #endif // BOOST_NO_STD_WSTRING | |
283 #if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) | |
284 // This function cannot be compiled with MSVC 6.0 due to internal compiler shorcomings | |
285 #else | |
286 //! function called by wrapper functions: date_period_from_(w)string() | |
287 template<class date_type, class charT> | |
288 period<date_type, typename date_type::duration_type> | |
289 from_simple_string_type(const std::basic_string<charT>& s){ | |
290 typedef typename std::basic_string<charT>::traits_type traits_type; | |
291 typedef typename boost::char_separator<charT, traits_type> char_separator; | |
292 typedef typename boost::tokenizer<char_separator, | |
293 typename std::basic_string<charT>::const_iterator, | |
294 std::basic_string<charT> > tokenizer; | |
295 const charT sep_list[4] = {'[','/',']','\0'}; | |
296 char_separator sep(sep_list); | |
297 tokenizer tokens(s, sep); | |
298 typename tokenizer::iterator tok_it = tokens.begin(); | |
299 std::basic_string<charT> date_string = *tok_it; | |
300 // get 2 string iterators and generate a date from them | |
301 typename std::basic_string<charT>::iterator date_string_start = date_string.begin(), | |
302 date_string_end = date_string.end(); | |
303 typedef typename std::iterator_traits<typename std::basic_string<charT>::iterator>::value_type value_type; | |
304 date_type d1 = from_stream_type<date_type>(date_string_start, date_string_end, value_type()); | |
305 date_string = *(++tok_it); // next token | |
306 date_string_start = date_string.begin(), date_string_end = date_string.end(); | |
307 date_type d2 = from_stream_type<date_type>(date_string_start, date_string_end, value_type()); | |
308 return period<date_type, typename date_type::duration_type>(d1, d2); | |
309 } | |
310 #endif | |
311 | |
312 } } //namespace date_time | |
313 | |
314 | |
315 | |
316 | |
317 #endif | |
318 |