File indexing completed on 2025-01-18 09:30:37
0001
0002 #ifndef DATE_TIME_DATE_GENERATOR_PARSER_HPP__
0003 #define DATE_TIME_DATE_GENERATOR_PARSER_HPP__
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <string>
0014 #include <vector>
0015 #include <iterator> // istreambuf_iterator
0016 #include <boost/throw_exception.hpp>
0017 #include <boost/date_time/compiler_config.hpp>
0018 #include <boost/date_time/string_parse_tree.hpp>
0019 #include <boost/date_time/date_generators.hpp>
0020 #include <boost/date_time/format_date_parser.hpp>
0021
0022 namespace boost { namespace date_time {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 template<class date_type, typename charT>
0041 class date_generator_parser
0042 {
0043 public:
0044 typedef std::basic_string<charT> string_type;
0045 typedef std::istreambuf_iterator<charT> stream_itr_type;
0046
0047 typedef typename date_type::month_type month_type;
0048 typedef typename date_type::day_of_week_type day_of_week_type;
0049 typedef typename date_type::day_type day_type;
0050
0051 typedef string_parse_tree<charT> parse_tree_type;
0052 typedef typename parse_tree_type::parse_match_result_type match_results;
0053 typedef std::vector<std::basic_string<charT> > collection_type;
0054
0055 typedef partial_date<date_type> partial_date_type;
0056 typedef nth_kday_of_month<date_type> nth_kday_type;
0057 typedef first_kday_of_month<date_type> first_kday_type;
0058 typedef last_kday_of_month<date_type> last_kday_type;
0059 typedef first_kday_after<date_type> kday_after_type;
0060 typedef first_kday_before<date_type> kday_before_type;
0061
0062 typedef charT char_type;
0063 static const char_type first_string[6];
0064 static const char_type second_string[7];
0065 static const char_type third_string[6];
0066 static const char_type fourth_string[7];
0067 static const char_type fifth_string[6];
0068 static const char_type last_string[5];
0069 static const char_type before_string[8];
0070 static const char_type after_string[6];
0071 static const char_type of_string[3];
0072
0073 enum phrase_elements {first=0, second, third, fourth, fifth, last,
0074 before, after, of, number_of_phrase_elements};
0075
0076
0077 date_generator_parser()
0078 {
0079 element_strings(string_type(first_string),
0080 string_type(second_string),
0081 string_type(third_string),
0082 string_type(fourth_string),
0083 string_type(fifth_string),
0084 string_type(last_string),
0085 string_type(before_string),
0086 string_type(after_string),
0087 string_type(of_string));
0088 }
0089
0090
0091 date_generator_parser(const string_type& first_str,
0092 const string_type& second_str,
0093 const string_type& third_str,
0094 const string_type& fourth_str,
0095 const string_type& fifth_str,
0096 const string_type& last_str,
0097 const string_type& before_str,
0098 const string_type& after_str,
0099 const string_type& of_str)
0100 {
0101 element_strings(first_str, second_str, third_str, fourth_str, fifth_str,
0102 last_str, before_str, after_str, of_str);
0103 }
0104
0105
0106 void element_strings(const string_type& first_str,
0107 const string_type& second_str,
0108 const string_type& third_str,
0109 const string_type& fourth_str,
0110 const string_type& fifth_str,
0111 const string_type& last_str,
0112 const string_type& before_str,
0113 const string_type& after_str,
0114 const string_type& of_str)
0115 {
0116 collection_type phrases;
0117 phrases.push_back(first_str);
0118 phrases.push_back(second_str);
0119 phrases.push_back(third_str);
0120 phrases.push_back(fourth_str);
0121 phrases.push_back(fifth_str);
0122 phrases.push_back(last_str);
0123 phrases.push_back(before_str);
0124 phrases.push_back(after_str);
0125 phrases.push_back(of_str);
0126 m_element_strings = parse_tree_type(phrases, this->first);
0127 }
0128
0129 void element_strings(const collection_type& col)
0130 {
0131 m_element_strings = parse_tree_type(col, this->first);
0132 }
0133
0134
0135 template<class facet_type>
0136 partial_date_type
0137 get_partial_date_type(stream_itr_type& sitr,
0138 stream_itr_type& stream_end,
0139 std::ios_base& a_ios,
0140 const facet_type& facet) const
0141 {
0142
0143 while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0144
0145 day_type d(1);
0146 month_type m(1);
0147 facet.get(sitr, stream_end, a_ios, d);
0148 facet.get(sitr, stream_end, a_ios, m);
0149
0150 return partial_date_type(d,m);
0151 }
0152
0153
0154 template<class facet_type>
0155 nth_kday_type
0156 get_nth_kday_type(stream_itr_type& sitr,
0157 stream_itr_type& stream_end,
0158 std::ios_base& a_ios,
0159 const facet_type& facet) const
0160 {
0161
0162 while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0163
0164 typename nth_kday_type::week_num wn;
0165 day_of_week_type wd(0);
0166 month_type m(1);
0167
0168 match_results mr = m_element_strings.match(sitr, stream_end);
0169 switch(mr.current_match) {
0170 case first : { wn = nth_kday_type::first; break; }
0171 case second : { wn = nth_kday_type::second; break; }
0172 case third : { wn = nth_kday_type::third; break; }
0173 case fourth : { wn = nth_kday_type::fourth; break; }
0174 case fifth : { wn = nth_kday_type::fifth; break; }
0175 default:
0176 {
0177 boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"));
0178 BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(wn = nth_kday_type::first);
0179 }
0180 }
0181 facet.get(sitr, stream_end, a_ios, wd);
0182 extract_element(sitr, stream_end, of);
0183 facet.get(sitr, stream_end, a_ios, m);
0184
0185 return nth_kday_type(wn, wd, m);
0186 }
0187
0188
0189 template<class facet_type>
0190 first_kday_type
0191 get_first_kday_type(stream_itr_type& sitr,
0192 stream_itr_type& stream_end,
0193 std::ios_base& a_ios,
0194 const facet_type& facet) const
0195 {
0196
0197 while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0198
0199 day_of_week_type wd(0);
0200 month_type m(1);
0201
0202 extract_element(sitr, stream_end, first);
0203 facet.get(sitr, stream_end, a_ios, wd);
0204 extract_element(sitr, stream_end, of);
0205 facet.get(sitr, stream_end, a_ios, m);
0206
0207
0208 return first_kday_type(wd, m);
0209 }
0210
0211
0212 template<class facet_type>
0213 last_kday_type
0214 get_last_kday_type(stream_itr_type& sitr,
0215 stream_itr_type& stream_end,
0216 std::ios_base& a_ios,
0217 const facet_type& facet) const
0218 {
0219
0220 while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0221
0222 day_of_week_type wd(0);
0223 month_type m(1);
0224
0225 extract_element(sitr, stream_end, last);
0226 facet.get(sitr, stream_end, a_ios, wd);
0227 extract_element(sitr, stream_end, of);
0228 facet.get(sitr, stream_end, a_ios, m);
0229
0230
0231 return last_kday_type(wd, m);
0232 }
0233
0234
0235 template<class facet_type>
0236 kday_before_type
0237 get_kday_before_type(stream_itr_type& sitr,
0238 stream_itr_type& stream_end,
0239 std::ios_base& a_ios,
0240 const facet_type& facet) const
0241 {
0242
0243 while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0244
0245 day_of_week_type wd(0);
0246
0247 facet.get(sitr, stream_end, a_ios, wd);
0248 extract_element(sitr, stream_end, before);
0249
0250 return kday_before_type(wd);
0251 }
0252
0253
0254 template<class facet_type>
0255 kday_after_type
0256 get_kday_after_type(stream_itr_type& sitr,
0257 stream_itr_type& stream_end,
0258 std::ios_base& a_ios,
0259 const facet_type& facet) const
0260 {
0261
0262 while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0263
0264 day_of_week_type wd(0);
0265
0266 facet.get(sitr, stream_end, a_ios, wd);
0267 extract_element(sitr, stream_end, after);
0268
0269 return kday_after_type(wd);
0270 }
0271
0272 private:
0273 parse_tree_type m_element_strings;
0274
0275
0276 void extract_element(stream_itr_type& sitr,
0277 stream_itr_type& stream_end,
0278 typename date_generator_parser::phrase_elements ele) const
0279 {
0280
0281 while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0282 match_results mr = m_element_strings.match(sitr, stream_end);
0283 if(mr.current_match != ele) {
0284 boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"));
0285 }
0286 }
0287
0288 };
0289
0290 template<class date_type, class CharT>
0291 const typename date_generator_parser<date_type, CharT>::char_type
0292 date_generator_parser<date_type, CharT>::first_string[6] =
0293 {'f','i','r','s','t'};
0294 template<class date_type, class CharT>
0295 const typename date_generator_parser<date_type, CharT>::char_type
0296 date_generator_parser<date_type, CharT>::second_string[7] =
0297 {'s','e','c','o','n','d'};
0298 template<class date_type, class CharT>
0299 const typename date_generator_parser<date_type, CharT>::char_type
0300 date_generator_parser<date_type, CharT>::third_string[6] =
0301 {'t','h','i','r','d'};
0302 template<class date_type, class CharT>
0303 const typename date_generator_parser<date_type, CharT>::char_type
0304 date_generator_parser<date_type, CharT>::fourth_string[7] =
0305 {'f','o','u','r','t','h'};
0306 template<class date_type, class CharT>
0307 const typename date_generator_parser<date_type, CharT>::char_type
0308 date_generator_parser<date_type, CharT>::fifth_string[6] =
0309 {'f','i','f','t','h'};
0310 template<class date_type, class CharT>
0311 const typename date_generator_parser<date_type, CharT>::char_type
0312 date_generator_parser<date_type, CharT>::last_string[5] =
0313 {'l','a','s','t'};
0314 template<class date_type, class CharT>
0315 const typename date_generator_parser<date_type, CharT>::char_type
0316 date_generator_parser<date_type, CharT>::before_string[8] =
0317 {'b','e','f','o','r','e'};
0318 template<class date_type, class CharT>
0319 const typename date_generator_parser<date_type, CharT>::char_type
0320 date_generator_parser<date_type, CharT>::after_string[6] =
0321 {'a','f','t','e','r'};
0322 template<class date_type, class CharT>
0323 const typename date_generator_parser<date_type, CharT>::char_type
0324 date_generator_parser<date_type, CharT>::of_string[3] =
0325 {'o','f'};
0326
0327 } }
0328
0329 #endif
0330