diff --git a/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp b/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp index be44043e07..cc5c266064 100644 --- a/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp +++ b/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp @@ -552,6 +552,30 @@ BOOST_AUTO_TEST_CASE(OpeningHoursMonthdayRanges_TestParseUnparse) } } +BOOST_AUTO_TEST_CASE(OpeningHoursYearRanges_TestParseUnparse) +{ + { + auto const rule = "1995"; + auto const parsedUnparsed = ParseAndUnparse(rule); + BOOST_CHECK_EQUAL(parsedUnparsed, rule); + } + { + auto const rule = "1997+"; + auto const parsedUnparsed = ParseAndUnparse(rule); + BOOST_CHECK_EQUAL(parsedUnparsed, rule); + } + { + auto const rule = "2018-2019"; + auto const parsedUnparsed = ParseAndUnparse(rule); + BOOST_CHECK_EQUAL(parsedUnparsed, rule); + } + { + auto const rule = "2018-2036/11"; + auto const parsedUnparsed = ParseAndUnparse(rule); + BOOST_CHECK_EQUAL(parsedUnparsed, rule); + } + +} // BOOST_AUTO_TEST_CASE(OpeningHours_TimeHit) // { diff --git a/3party/opening_hours/osm_parsers.hpp b/3party/opening_hours/osm_parsers.hpp index 420191ba36..b8d0e0cd58 100644 --- a/3party/opening_hours/osm_parsers.hpp +++ b/3party/opening_hours/osm_parsers.hpp @@ -88,33 +88,41 @@ namespace charset = boost::spirit::standard_wide; using space_type = charset::space_type; -// template -// class year_selector : public qi::grammar -// { -// protected: -// qi::rule year; -// qi::rule year_range; -// qi::rule main; -// public: -// year_selector() : year_selector::base_type(main) -// { -// using qi::uint_; -// using qi::lit; -// using charset::char_; +template +class year_selector : public qi::grammar +{ + protected: + qi::rule year_range; + qi::rule main; -// static const qi::int_parser _4digit = {}; + public: + year_selector() : year_selector::base_type(main) + { + using qi::uint_; + using qi::lit; + using qi::_1; + using qi::_2; + using qi::_3; + using qi::_val; -// year %= _4digit; -// year_range %= (year >> dash >> year >> '/' >> uint_) -// | (year >> dash >> year) -// | year >> char_('+') -// | year -// ; -// main %= year_range % ','; -// } -// }; + static const qi::int_parser year = {}; -// template + year_range = (year >> dash >> year >> '/' >> uint_) + [bind(&osmoh::YearRange::SetStart, _val, _1), + bind(&osmoh::YearRange::SetEnd, _val, _2), + bind(&osmoh::YearRange::SetPeriod, _val, _3)] + | (year >> dash >> year) [bind(&osmoh::YearRange::SetStart, _val, _1), + bind(&osmoh::YearRange::SetEnd, _val, _2)] + | (year >> lit('+')) [bind(&osmoh::YearRange::SetStart, _val, _1), + bind(&osmoh::YearRange::SetPlus, _val, true)] + | year [bind(&osmoh::YearRange::SetStart, _val, _1)] + ; + + main %= (year_range % ','); + } +}; + + // template // class week_selector : public qi::grammar // { // protected: diff --git a/3party/opening_hours/osm_time_range.cpp b/3party/opening_hours/osm_time_range.cpp index 1d30c9acf6..e7ac35413e 100644 --- a/3party/opening_hours/osm_time_range.cpp +++ b/3party/opening_hours/osm_time_range.cpp @@ -907,6 +907,86 @@ std::ostream & operator<<(std::ostream & ost, TMonthdayRanges const & ranges) } +bool YearRange::IsEmpty() const +{ + return !HasStart() && !HasEnd(); +} + +bool YearRange::HasStart() const +{ + return GetStart() != 0; +} + +bool YearRange::HasEnd() const +{ + return GetEnd() != 0; +} + +bool YearRange::HasPlus() const +{ + return m_plus; +} + +bool YearRange::HasPeriod() const +{ + return GetPeriod() != 0; +} + +YearRange::TYear YearRange::GetStart() const +{ + return m_start; +} + +YearRange::TYear YearRange::GetEnd() const +{ + return m_end; +} + +uint32_t YearRange::GetPeriod() const +{ + return m_period; +} + +void YearRange::SetStart(TYear const start) +{ + m_start = start; +} + +void YearRange::SetEnd(TYear const end) +{ + m_end = end; +} + +void YearRange::SetPlus(bool const plus) +{ + m_plus = plus; +} + +void YearRange::SetPeriod(uint32_t const period) +{ + m_period = period; +} + +std::ostream & operator<<(std::ostream & ost, YearRange const range) +{ + ost << range.GetStart(); + if (range.HasEnd()) + { + ost << '-' << range.GetEnd(); + if (range.HasPeriod()) + ost << '/' << range.GetPeriod(); + } + else if (range.HasPlus()) + ost << '+'; + return ost; +} + +std::ostream & operator<<(std::ostream & ost, TYearRanges const ranges) +{ + PrintVector(ost, ranges); + return ost; +} + // std::ostream & operator << (std::ostream & s, State const & w) // { // static char const * st[] = {"unknown", "closed", "open"}; diff --git a/3party/opening_hours/osm_time_range.hpp b/3party/opening_hours/osm_time_range.hpp index 4dfd504f69..5338d0f74b 100644 --- a/3party/opening_hours/osm_time_range.hpp +++ b/3party/opening_hours/osm_time_range.hpp @@ -414,6 +414,40 @@ using TMonthdayRanges = std::vector; std::ostream & operator<<(std::ostream & ost, MonthdayRange const & range); std::ostream & operator<<(std::ostream & ost, TMonthdayRanges const & ranges); + + +class YearRange +{ + public: + using TYear = uint16_t; + + public: + bool IsEmpty() const; + bool HasStart() const; + bool HasEnd() const; + bool HasPlus() const; + bool HasPeriod() const; + + TYear GetStart() const; + TYear GetEnd() const; + uint32_t GetPeriod() const; + + void SetStart(TYear const start); + void SetEnd(TYear const end); + void SetPlus(bool const plus); + void SetPeriod(uint32_t const period); + + private: + TYear m_start{}; + TYear m_end{}; + bool m_plus{false}; + uint32_t m_period{0}; +}; + +using TYearRanges = std::vector; + +std::ostream & operator<<(std::ostream & ost, YearRange const range); +std::ostream & operator<<(std::ostream & ost, TYearRanges const ranges); } // namespace osmoh @@ -470,51 +504,3 @@ std::ostream & operator<<(std::ostream & ost, TMonthdayRanges const & ranges); // osmoh::TTimeRules m_rules; // std::string m_comment; // }; - - - - -/// Trash - -// class TimeEx -// { -// public: -// enum EFlags -// { -// eNone = 0, -// eHours = 1, -// eMinutes = 2, -// ePlus = 4, -// eMinus = 8, -// eExt = 16, -// eSunrise = 32, -// eSunset = 64 -// }; - -// uint8_t hours; -// uint8_t minutes; -// uint8_t flags; - -// Time() : hours(0), minutes(0), flags(eNone) {} -// Time & Hours(uint8_t h) { hours = h; flags |= eHours; return *this; } -// Time & Minutes(uint8_t m) { minutes = m; flags |= eMinutes; return *this; } -// Time & Sunset() { flags = eSunset; return *this; } -// Time & Sunrise() { flags = eSunrise; return *this; } - -// std::string ToString() const; -// friend std::ostream & operator << (std::ostream & s, Time const & t); -// }; - -// class TimeSpanEx -// { -// public: -// Time from; -// Time to; -// uint8_t flags; -// Time period; - -// TimeSpan() : flags(Time::eNone) {} - -// std::string ToString() const; -// friend std::ostream & operator << (std::ostream & s, TimeSpan const & span); -// }; diff --git a/3party/opening_hours/parse.cpp b/3party/opening_hours/parse.cpp index 0d41f44cca..9f14c6e167 100644 --- a/3party/opening_hours/parse.cpp +++ b/3party/opening_hours/parse.cpp @@ -21,6 +21,11 @@ template struct context_parser; }; +template struct context_parser +{ + using type = osmoh::parsing::year_selector; +}; + template using context_parser_t = typename context_parser::type; @@ -67,4 +72,9 @@ bool Parse(std::string const & str, TMonthdayRanges & m) { return ParseImp(str, m); } + +bool Parse(std::string const & str, TYearRanges & y) +{ + return ParseImp(str, y); +} } // namespace osmoh diff --git a/3party/opening_hours/parse.hpp b/3party/opening_hours/parse.hpp index 634c2ac25e..913511553f 100644 --- a/3party/opening_hours/parse.hpp +++ b/3party/opening_hours/parse.hpp @@ -8,4 +8,5 @@ namespace osmoh bool Parse(std::string const &, TTimespans &); bool Parse(std::string const &, Weekdays &); bool Parse(std::string const &, TMonthdayRanges &); +bool Parse(std::string const &, TYearRanges &); } // namespace osmoh