Back to home page

EIC code displayed by LXR

 
 

    


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 /* Copyright (c) 2005 CrystalClear Software, Inc.
0006  * Use, modification and distribution is subject to the 
0007  * Boost Software License, Version 1.0. (See accompanying
0008  * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
0009  * Author: Jeff Garland, Bart Garst
0010  * $Date$
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   //! Class for date_generator parsing 
0025   /*! The elements of a date_generator "phrase" are parsed from the input stream in a 
0026    *  particular order. All elements are required and the order in which they appear 
0027    *  cannot change, however, the elements themselves can be changed. The default 
0028    *  elements and their order are as follows:
0029    *
0030    * - partial_date                     => "dd Month"
0031    * - nth_day_of_the_week_in_month     => "nth weekday of month"
0032    * - first_day_of_the_week_in_month   => "first weekday of month"
0033    * - last_day_of_the_week_in_month    => "last weekday of month"
0034    * - first_day_of_the_week_after      => "weekday after"
0035    * - first_day_of_the_week_before     => "weekday before"
0036    *
0037    * Weekday and Month names and formats are handled via the date_input_facet. 
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     //! Creates a date_generator_parser with the default set of "element_strings"
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     //! Creates a date_generator_parser using a user defined set of element strings
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     //! Replace strings that determine nth week for generator
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); // enum first
0127     }
0128 
0129     void element_strings(const collection_type& col)
0130     {
0131       m_element_strings = parse_tree_type(col, this->first); // enum first
0132     }
0133 
0134     //! returns partial_date parsed from stream
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       // skip leading whitespace
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     //! returns nth_kday_of_week parsed from stream
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       // skip leading whitespace
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); // no default constructor
0166       month_type m(1);        // no default constructor
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       }                                         // week num
0181       facet.get(sitr, stream_end, a_ios, wd);   // day_of_week
0182       extract_element(sitr, stream_end, of);    // "of" element
0183       facet.get(sitr, stream_end, a_ios, m);    // month
0184 
0185       return nth_kday_type(wn, wd, m);
0186     }
0187 
0188     //! returns first_kday_of_week parsed from stream
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       // skip leading whitespace
0197       while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0198 
0199       day_of_week_type wd(0); // no default constructor
0200       month_type m(1);        // no default constructor
0201 
0202       extract_element(sitr, stream_end, first); // "first" element
0203       facet.get(sitr, stream_end, a_ios, wd);   // day_of_week
0204       extract_element(sitr, stream_end, of);    // "of" element
0205       facet.get(sitr, stream_end, a_ios, m);    // month
0206 
0207 
0208       return first_kday_type(wd, m);
0209     }
0210 
0211     //! returns last_kday_of_week parsed from stream
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       // skip leading whitespace
0220       while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0221 
0222       day_of_week_type wd(0); // no default constructor
0223       month_type m(1);        // no default constructor
0224  
0225       extract_element(sitr, stream_end, last); // "last" element
0226       facet.get(sitr, stream_end, a_ios, wd);  // day_of_week
0227       extract_element(sitr, stream_end, of);   // "of" element
0228       facet.get(sitr, stream_end, a_ios, m);   // month
0229 
0230 
0231       return last_kday_type(wd, m);
0232     }
0233 
0234     //! returns first_kday_of_week parsed from stream
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       // skip leading whitespace
0243       while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0244 
0245       day_of_week_type wd(0); // no default constructor
0246 
0247       facet.get(sitr, stream_end, a_ios, wd);   // day_of_week
0248       extract_element(sitr, stream_end, before);// "before" element
0249 
0250       return kday_before_type(wd);
0251     }
0252 
0253     //! returns first_kday_of_week parsed from stream
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       // skip leading whitespace
0262       while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; }
0263 
0264       day_of_week_type wd(0); // no default constructor
0265 
0266       facet.get(sitr, stream_end, a_ios, wd);   // day_of_week
0267       extract_element(sitr, stream_end, after); // "after" element
0268 
0269       return kday_after_type(wd);
0270     }
0271 
0272    private:
0273     parse_tree_type m_element_strings;
0274 
0275     //! Extracts phrase element from input. Throws ios_base::failure on error.
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       // skip leading whitespace
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 } } //namespace
0328 
0329 #endif // DATE_TIME_DATE_GENERATOR_PARSER_HPP__
0330