forked from organicmaps/organicmaps
Merge pull request #358 from mgsergio/fix-old-parser
opening_hours parser reloading
This commit is contained in:
commit
2f2ffe130a
31 changed files with 161730 additions and 2016 deletions
|
@ -2,16 +2,30 @@
|
|||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = freetype fribidi minizip jansson tomcrypt protobuf osrm expat \
|
||||
succinct \
|
||||
|
||||
!linux* {
|
||||
SUBDIRS += opening_hours \
|
||||
|
||||
}
|
||||
|
||||
# TODO: Avoid duplication here and in omim.pro by moving opening_hours tests out of 3party.
|
||||
!iphone*:!tizen*:!android* {
|
||||
SUBDIRS += gflags \
|
||||
libtess2 \
|
||||
gmock \
|
||||
CONFIG *= desktop
|
||||
}
|
||||
|
||||
SUBDIRS = freetype fribidi minizip jansson tomcrypt protobuf osrm expat succinct
|
||||
|
||||
# TODO(mgsrergio): Move opening hours out of 3party to the main project tree.
|
||||
# See https://trello.com/c/tWYSnXSS/22-opening-hours-3party-boost-test-framework.
|
||||
SUBDIRS *= opening_hours
|
||||
CONFIG(desktop):!CONFIG(no-tests) {
|
||||
opening_hours_tests.subdir = opening_hours/opening_hours_tests
|
||||
opening_hours_tests.depends = opening_hours
|
||||
SUBDIRS *= opening_hours_tests
|
||||
|
||||
opening_hours_integration_tests.subdir = opening_hours/opening_hours_integration_tests
|
||||
opening_hours_integration_tests.depends = opening_hours
|
||||
SUBDIRS *= opening_hours_integration_tests
|
||||
|
||||
opening_hours_supported_features_tests.subdir = opening_hours/opening_hours_supported_features_tests
|
||||
opening_hours_supported_features_tests.depends = opening_hours
|
||||
SUBDIRS *= opening_hours_supported_features_tests
|
||||
}
|
||||
|
||||
CONFIG(desktop) {
|
||||
SUBDIRS *= gflags libtess2 gmock
|
||||
}
|
||||
|
|
|
@ -545,7 +545,7 @@ namespace boost { namespace proto
|
|||
BOOST_PROTO_USE_GET_POINTER();
|
||||
typedef typename detail::class_member_traits<function_type>::class_type class_type;
|
||||
return (
|
||||
BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, e))) ->*
|
||||
BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, e))) ->*
|
||||
BOOST_PROTO_DEFAULT_EVAL(~, 0, e)
|
||||
)();
|
||||
}
|
||||
|
|
1598
3party/opening_hours/opening_hours.cpp
Normal file
1598
3party/opening_hours/opening_hours.cpp
Normal file
File diff suppressed because it is too large
Load diff
656
3party/opening_hours/opening_hours.hpp
Normal file
656
3party/opening_hours/opening_hours.hpp
Normal file
|
@ -0,0 +1,656 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Mail.Ru Group
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
|
||||
class HourMinutes
|
||||
{
|
||||
public:
|
||||
using THours = std::chrono::hours;
|
||||
using TMinutes = std::chrono::minutes;
|
||||
|
||||
HourMinutes() = default;
|
||||
explicit HourMinutes(THours const duration);
|
||||
explicit HourMinutes(TMinutes const duration);
|
||||
|
||||
bool IsEmpty() const;
|
||||
|
||||
THours GetHours() const;
|
||||
TMinutes GetMinutes() const;
|
||||
TMinutes GetDuration() const;
|
||||
|
||||
THours::rep GetHoursCount() const;
|
||||
TMinutes::rep GetMinutesCount() const;
|
||||
TMinutes::rep GetDurationCount() const;
|
||||
|
||||
void SetHours(THours const hours);
|
||||
void SetMinutes(TMinutes const minutes);
|
||||
void SetDuration(TMinutes const duration);
|
||||
|
||||
void AddDuration(TMinutes const duration);
|
||||
|
||||
private:
|
||||
THours m_hours = THours::zero();
|
||||
TMinutes m_minutes = TMinutes::zero();
|
||||
bool m_empty = true;
|
||||
};
|
||||
|
||||
HourMinutes operator-(HourMinutes const & hm);
|
||||
std::ostream & operator<<(std::ostream & ost, HourMinutes const & hm);
|
||||
|
||||
class Time;
|
||||
|
||||
class TimeEvent
|
||||
{
|
||||
public:
|
||||
enum class Event
|
||||
{
|
||||
None,
|
||||
Sunrise,
|
||||
Sunset
|
||||
};
|
||||
|
||||
TimeEvent() = default;
|
||||
TimeEvent(Event const event);
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool HasOffset() const;
|
||||
|
||||
Event GetEvent() const;
|
||||
void SetEvent(Event const event);
|
||||
|
||||
HourMinutes const & GetOffset() const;
|
||||
void SetOffset(HourMinutes const & offset);
|
||||
void AddDurationToOffset(HourMinutes::TMinutes const duration);
|
||||
|
||||
Time GetEventTime() const;
|
||||
|
||||
private:
|
||||
Event m_event = Event::None;
|
||||
HourMinutes m_offset;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, TimeEvent const te);
|
||||
|
||||
class Time
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
None,
|
||||
HourMinutes,
|
||||
Event,
|
||||
};
|
||||
|
||||
public:
|
||||
using THours = HourMinutes::THours;
|
||||
using TMinutes = HourMinutes::TMinutes;
|
||||
|
||||
Time() = default;
|
||||
Time(HourMinutes const & hm);
|
||||
Time(TimeEvent const & te);
|
||||
|
||||
Type GetType() const;
|
||||
|
||||
THours::rep GetHoursCount() const;
|
||||
TMinutes::rep GetMinutesCount() const;
|
||||
|
||||
THours GetHours() const;
|
||||
TMinutes GetMinutes() const;
|
||||
|
||||
void AddDuration(TMinutes const duration);
|
||||
|
||||
TimeEvent const & GetEvent() const;
|
||||
void SetEvent(TimeEvent const & event);
|
||||
|
||||
HourMinutes const & GetHourMinutes() const;
|
||||
void SetHourMinutes(HourMinutes const & hm);
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsTime() const;
|
||||
bool IsEvent() const;
|
||||
bool IsHoursMinutes() const;
|
||||
|
||||
private:
|
||||
HourMinutes m_hourMinutes;
|
||||
TimeEvent m_event;
|
||||
|
||||
Type m_type = Type::None;
|
||||
};
|
||||
|
||||
inline constexpr Time::THours operator ""_h(unsigned long long int h)
|
||||
{
|
||||
return Time::THours(h);
|
||||
}
|
||||
|
||||
inline constexpr Time::TMinutes operator ""_min(unsigned long long int m)
|
||||
{
|
||||
return Time::TMinutes(m);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, Time const & time);
|
||||
|
||||
class TimespanPeriod
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
None,
|
||||
Minutes,
|
||||
HourMinutes
|
||||
};
|
||||
|
||||
TimespanPeriod() = default;
|
||||
TimespanPeriod(HourMinutes const & hm);
|
||||
TimespanPeriod(HourMinutes::TMinutes const minutes);
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsHoursMinutes() const;
|
||||
bool IsMinutes() const;
|
||||
|
||||
HourMinutes const & GetHourMinutes() const;
|
||||
HourMinutes::TMinutes GetMinutes() const;
|
||||
HourMinutes::TMinutes::rep GetMinutesCount() const;
|
||||
|
||||
private:
|
||||
HourMinutes::TMinutes m_minutes;
|
||||
HourMinutes m_hourMinutes;
|
||||
|
||||
Type m_type = Type::None;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, TimespanPeriod const p);
|
||||
|
||||
class Timespan
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool IsOpen() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasPlus() const;
|
||||
bool HasPeriod() const;
|
||||
|
||||
Time const & GetStart() const;
|
||||
Time const & GetEnd() const;
|
||||
TimespanPeriod const & GetPeriod() const;
|
||||
|
||||
void SetStart(Time const & start);
|
||||
void SetEnd(Time const & end);
|
||||
void SetPeriod(TimespanPeriod const & period);
|
||||
void SetPlus(bool const plus);
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
private:
|
||||
Time m_start;
|
||||
Time m_end;
|
||||
TimespanPeriod m_period;
|
||||
bool m_plus = false;
|
||||
};
|
||||
|
||||
using TTimespans = std::vector<Timespan>;
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, Timespan const & span);
|
||||
std::ostream & operator<<(std::ostream & ost, osmoh::TTimespans const & timespans);
|
||||
|
||||
class NthWeekdayOfTheMonthEntry
|
||||
{
|
||||
public:
|
||||
enum class NthDayOfTheMonth
|
||||
{
|
||||
None,
|
||||
First,
|
||||
Second,
|
||||
Third,
|
||||
Fourth,
|
||||
Fifth
|
||||
};
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
|
||||
NthDayOfTheMonth GetStart() const;
|
||||
NthDayOfTheMonth GetEnd() const;
|
||||
|
||||
void SetStart(NthDayOfTheMonth const s);
|
||||
void SetEnd(NthDayOfTheMonth const e);
|
||||
|
||||
private:
|
||||
NthDayOfTheMonth m_start = NthDayOfTheMonth::None;
|
||||
NthDayOfTheMonth m_end = NthDayOfTheMonth::None;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, NthWeekdayOfTheMonthEntry const entry);
|
||||
|
||||
enum class Weekday
|
||||
{
|
||||
None,
|
||||
Sunday,
|
||||
Monday,
|
||||
Tuesday,
|
||||
Wednesday,
|
||||
Thursday,
|
||||
Friday,
|
||||
Saturday
|
||||
};
|
||||
|
||||
inline constexpr Weekday ToWeekday(uint64_t const day)
|
||||
{
|
||||
using TDay = decltype(day);
|
||||
return ((day <= static_cast<TDay>(Weekday::None) ||
|
||||
day > static_cast<TDay>(Weekday::Saturday))
|
||||
? Weekday::None
|
||||
: static_cast<Weekday>(day));
|
||||
}
|
||||
|
||||
inline constexpr Weekday operator ""_weekday(unsigned long long int day)
|
||||
{
|
||||
return ToWeekday(day);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, Weekday const wday);
|
||||
|
||||
class WeekdayRange
|
||||
{
|
||||
using TNths = std::vector<NthWeekdayOfTheMonthEntry>;
|
||||
|
||||
public:
|
||||
bool HasWday(Weekday const & wday) const;
|
||||
|
||||
bool HasSunday() const;
|
||||
bool HasMonday() const;
|
||||
bool HasTuesday() const;
|
||||
bool HasWednesday() const;
|
||||
bool HasThursday() const;
|
||||
bool HasFriday() const;
|
||||
bool HasSaturday() const;
|
||||
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasOffset() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
Weekday GetStart() const;
|
||||
Weekday GetEnd() const;
|
||||
|
||||
void SetStart(Weekday const & wday);
|
||||
void SetEnd(Weekday const & wday);
|
||||
|
||||
int32_t GetOffset() const;
|
||||
void SetOffset(int32_t const offset);
|
||||
|
||||
bool HasNth() const;
|
||||
TNths const & GetNths() const;
|
||||
|
||||
void AddNth(NthWeekdayOfTheMonthEntry const & entry);
|
||||
|
||||
private:
|
||||
Weekday m_start = Weekday::None;
|
||||
Weekday m_end = Weekday::None;
|
||||
int32_t m_offset = 0;
|
||||
TNths m_nths;
|
||||
};
|
||||
|
||||
using TWeekdayRanges = std::vector<WeekdayRange>;
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, WeekdayRange const & range);
|
||||
std::ostream & operator<<(std::ostream & ost, TWeekdayRanges const & ranges);
|
||||
|
||||
class Holiday
|
||||
{
|
||||
public:
|
||||
bool IsPlural() const;
|
||||
void SetPlural(bool const plural);
|
||||
|
||||
int32_t GetOffset() const;
|
||||
void SetOffset(int32_t const offset);
|
||||
|
||||
private:
|
||||
bool m_plural = false;
|
||||
int32_t m_offset = 0;
|
||||
};
|
||||
|
||||
using THolidays = std::vector<Holiday>;
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, Holiday const & holiday);
|
||||
std::ostream & operator<<(std::ostream & ost, THolidays const & holidys);
|
||||
|
||||
// Correspond to weekday_selector in osm opening hours.
|
||||
class Weekdays
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool HasWeekday() const;
|
||||
bool HasHolidays() const;
|
||||
|
||||
TWeekdayRanges const & GetWeekdayRanges() const;
|
||||
THolidays const & GetHolidays() const;
|
||||
|
||||
void SetWeekdayRanges(TWeekdayRanges const ranges);
|
||||
void SetHolidays(THolidays const & holidays);
|
||||
|
||||
void AddWeekdayRange(WeekdayRange const range);
|
||||
void AddHoliday(Holiday const & holiday);
|
||||
|
||||
private:
|
||||
TWeekdayRanges m_weekdayRanges;
|
||||
THolidays m_holidays;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, Weekdays const & weekday);
|
||||
|
||||
class DateOffset
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool HasWDayOffset() const;
|
||||
bool HasOffset() const;
|
||||
|
||||
bool IsWDayOffsetPositive() const;
|
||||
|
||||
Weekday GetWDayOffset() const;
|
||||
int32_t GetOffset() const;
|
||||
|
||||
void SetWDayOffset(Weekday const wday);
|
||||
void SetOffset(int32_t const offset);
|
||||
void SetWDayOffsetPositive(bool const on);
|
||||
|
||||
private:
|
||||
Weekday m_wdayOffest = Weekday::None;
|
||||
bool m_positive = true;
|
||||
int32_t m_offset = 0;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, DateOffset const & offset);
|
||||
|
||||
class MonthDay
|
||||
{
|
||||
public:
|
||||
enum class Month
|
||||
{
|
||||
None,
|
||||
Jan,
|
||||
Feb,
|
||||
Mar,
|
||||
Apr,
|
||||
May,
|
||||
Jun,
|
||||
Jul,
|
||||
Aug,
|
||||
Sep,
|
||||
Oct,
|
||||
Nov,
|
||||
Dec
|
||||
};
|
||||
|
||||
enum class VariableDate
|
||||
{
|
||||
None,
|
||||
Easter
|
||||
};
|
||||
|
||||
using TYear = uint16_t;
|
||||
using TDayNum = uint8_t;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsVariable() const;
|
||||
|
||||
bool HasYear() const;
|
||||
bool HasMonth() const;
|
||||
bool HasDayNum() const;
|
||||
bool HasOffset() const;
|
||||
|
||||
TYear GetYear() const;
|
||||
Month GetMonth() const;
|
||||
TDayNum GetDayNum() const;
|
||||
DateOffset const & GetOffset() const;
|
||||
VariableDate GetVariableDate() const;
|
||||
|
||||
void SetYear(TYear const year);
|
||||
void SetMonth(Month const month);
|
||||
void SetDayNum(TDayNum const daynum);
|
||||
void SetOffset(DateOffset const & offset);
|
||||
void SetVariableDate(VariableDate const date);
|
||||
|
||||
private:
|
||||
TYear m_year = 0;
|
||||
Month m_month = Month::None;
|
||||
TDayNum m_daynum = 0;
|
||||
VariableDate m_variable_date = VariableDate::None;
|
||||
DateOffset m_offset;
|
||||
};
|
||||
|
||||
inline constexpr MonthDay::Month ToMonth(uint64_t const month)
|
||||
{
|
||||
using TMonth = decltype(month);
|
||||
return ((month <= static_cast<TMonth>(MonthDay::Month::None) ||
|
||||
month > static_cast<TMonth>(MonthDay::Month::Dec))
|
||||
? MonthDay::Month::None
|
||||
: static_cast<osmoh::MonthDay::Month>(month));
|
||||
}
|
||||
|
||||
inline constexpr MonthDay::Month operator ""_M(unsigned long long int month)
|
||||
{
|
||||
return ToMonth(month);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, MonthDay::Month const month);
|
||||
std::ostream & operator<<(std::ostream & ost, MonthDay::VariableDate const date);
|
||||
std::ostream & operator<<(std::ostream & ost, MonthDay const md);
|
||||
|
||||
class MonthdayRange
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasPeriod() const;
|
||||
bool HasPlus() const;
|
||||
|
||||
MonthDay const & GetStart() const;
|
||||
MonthDay const & GetEnd() const;
|
||||
uint32_t GetPeriod() const;
|
||||
|
||||
void SetStart(MonthDay const & start);
|
||||
void SetEnd(MonthDay const & end);
|
||||
void SetPeriod(uint32_t const period);
|
||||
void SetPlus(bool const plus);
|
||||
|
||||
private:
|
||||
MonthDay m_start;
|
||||
MonthDay m_end;
|
||||
uint32_t m_period = 0;
|
||||
bool m_plus = false;
|
||||
};
|
||||
|
||||
using TMonthdayRanges = std::vector<MonthdayRange>;
|
||||
|
||||
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;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsOpen() 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 = 0;
|
||||
TYear m_end = 0;
|
||||
bool m_plus = false;
|
||||
uint32_t m_period = 0;
|
||||
};
|
||||
|
||||
using TYearRanges = std::vector<YearRange>;
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, YearRange const range);
|
||||
std::ostream & operator<<(std::ostream & ost, TYearRanges const ranges);
|
||||
|
||||
class WeekRange
|
||||
{
|
||||
public:
|
||||
using TWeek = uint8_t;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsOpen() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasPeriod() const;
|
||||
|
||||
TWeek GetStart() const;
|
||||
TWeek GetEnd() const;
|
||||
uint32_t GetPeriod() const;
|
||||
|
||||
void SetStart(TWeek const start);
|
||||
void SetEnd(TWeek const end);
|
||||
void SetPeriod(uint32_t const period);
|
||||
|
||||
private:
|
||||
TWeek m_start = 0;
|
||||
TWeek m_end = 0;
|
||||
uint32_t m_period = 0;
|
||||
};
|
||||
|
||||
using TWeekRanges = std::vector<WeekRange>;
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, WeekRange const range);
|
||||
std::ostream & operator<<(std::ostream & ost, TWeekRanges const ranges);
|
||||
|
||||
class RuleSequence
|
||||
{
|
||||
public:
|
||||
enum class Modifier
|
||||
{
|
||||
DefaultOpen,
|
||||
Open,
|
||||
Closed,
|
||||
Unknown,
|
||||
Comment
|
||||
};
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsTwentyFourHours() const;
|
||||
|
||||
bool HasYears() const;
|
||||
bool HasMonths() const;
|
||||
bool HasWeeks() const;
|
||||
bool HasWeekdays() const;
|
||||
bool HasTimes() const;
|
||||
bool HasComment() const;
|
||||
bool HasModifierComment() const;
|
||||
bool HasSeparatorForReadability() const;
|
||||
|
||||
TYearRanges const & GetYears() const;
|
||||
TMonthdayRanges const & GetMonths() const;
|
||||
TWeekRanges const & GetWeeks() const;
|
||||
Weekdays const & GetWeekdays() const;
|
||||
TTimespans const & GetTimes() const;
|
||||
|
||||
std::string const & GetComment() const;
|
||||
std::string const & GetModifierComment() const;
|
||||
std::string const & GetAnySeparator() const;
|
||||
|
||||
Modifier GetModifier() const;
|
||||
|
||||
void SetTwentyFourHours(bool const on);
|
||||
void SetYears(TYearRanges const & years);
|
||||
void SetMonths(TMonthdayRanges const & months);
|
||||
void SetWeeks(TWeekRanges const & weeks);
|
||||
|
||||
void SetWeekdays(Weekdays const & weekdays);
|
||||
void SetTimes(TTimespans const & times);
|
||||
|
||||
void SetComment(std::string const & comment);
|
||||
void SetModifierComment(std::string & comment);
|
||||
void SetAnySeparator(std::string const & separator);
|
||||
void SetSeparatorForReadability(bool const on);
|
||||
|
||||
void SetModifier(Modifier const modifier);
|
||||
|
||||
private:
|
||||
bool m_twentyFourHours{false};
|
||||
|
||||
TYearRanges m_years;
|
||||
TMonthdayRanges m_months;
|
||||
TWeekRanges m_weeks;
|
||||
|
||||
Weekdays m_weekdays;
|
||||
TTimespans m_times;
|
||||
|
||||
std::string m_comment;
|
||||
std::string m_anySeparator = ";";
|
||||
bool m_separatorForReadability = false;
|
||||
|
||||
Modifier m_modifier = Modifier::DefaultOpen;
|
||||
std::string m_modifierComment;
|
||||
};
|
||||
|
||||
using TRuleSequences = std::vector<RuleSequence>;
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, RuleSequence::Modifier const modifier);
|
||||
std::ostream & operator<<(std::ostream & ost, RuleSequence const & sequence);
|
||||
std::ostream & operator<<(std::ostream & ost, TRuleSequences const & sequences);
|
||||
|
||||
class OpeningHours
|
||||
{
|
||||
public:
|
||||
OpeningHours(std::string const & rule);
|
||||
OpeningHours(TRuleSequences const & rule);
|
||||
|
||||
bool IsOpen(time_t const dateTime) const;
|
||||
bool IsClosed(time_t const dateTime) const;
|
||||
bool IsUnknown(time_t const dateTime) const;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
private:
|
||||
TRuleSequences m_rule;
|
||||
bool const m_valid;
|
||||
};
|
||||
} // namespace osmoh
|
|
@ -4,14 +4,22 @@
|
|||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
ROOT_DIR = ../..
|
||||
|
||||
TARGET = opening_hours
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
|
||||
ROOT_DIR = ../..
|
||||
|
||||
include($$ROOT_DIR/common.pri)
|
||||
|
||||
SOURCES += osm_time_range.cpp
|
||||
HEADERS += opening_hours.hpp \
|
||||
opening_hours_parsers.hpp \
|
||||
opening_hours_parsers_terminals.hpp \
|
||||
parse_opening_hours.hpp \
|
||||
rules_evaluation_private.hpp \
|
||||
rules_evaluation.hpp
|
||||
|
||||
HEADERS += osm_time_range.hpp
|
||||
SOURCES += rules_evaluation.cpp \
|
||||
opening_hours.cpp \
|
||||
parse_opening_hours.cpp
|
||||
|
|
155961
3party/opening_hours/opening_hours_integration_tests/opening-count.lst
Normal file
155961
3party/opening_hours/opening_hours_integration_tests/opening-count.lst
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,221 @@
|
|||
#include "parse_opening_hours.hpp"
|
||||
#include "rules_evaluation.hpp"
|
||||
|
||||
#define BOOST_TEST_MODULE OpeningHoursIntegration
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
std::string ToString(T const & t)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << t;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HasPeriod(std::vector<T> const & v)
|
||||
{
|
||||
auto const hasPeriod = [](T const & t) { return t.HasPeriod(); };
|
||||
return std::any_of(begin(v), end(v), hasPeriod);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HasPlus(std::vector<T> const & v)
|
||||
{
|
||||
auto const hasPlus = [](T const & t) { return t.HasPlus(); };
|
||||
return std::any_of(begin(v), end(v), hasPlus);
|
||||
}
|
||||
|
||||
bool HasExtendedHours(osmoh::TTimespans const & spans)
|
||||
{
|
||||
auto const hasExtendedHours = [](osmoh::Timespan const & s) -> bool
|
||||
{
|
||||
if (!s.HasEnd())
|
||||
return false;
|
||||
|
||||
auto const startDuration = s.GetStart().GetMinutes() + s.GetStart().GetHours();
|
||||
auto const endDuration = s.GetEnd().GetMinutes() + s.GetEnd().GetHours();
|
||||
|
||||
return endDuration > 24 * std::chrono::minutes(60) || startDuration > endDuration;
|
||||
};
|
||||
return std::any_of(begin(spans), end(spans), hasExtendedHours);
|
||||
}
|
||||
|
||||
bool HasOffset(osmoh::TMonthdayRanges const & mr)
|
||||
{
|
||||
auto const hasOffset = [](osmoh::MonthdayRange const & md) {
|
||||
return
|
||||
md.GetStart().HasOffset() ||
|
||||
md.GetEnd().HasOffset();
|
||||
};
|
||||
return std::any_of(begin(mr), end(mr), hasOffset);
|
||||
}
|
||||
|
||||
bool HasOffset(osmoh::Weekdays const & wd)
|
||||
{
|
||||
auto const hasOffset = [](osmoh::WeekdayRange const & w) { return w.HasOffset(); };
|
||||
return std::any_of(begin(wd.GetWeekdayRanges()), end(wd.GetWeekdayRanges()), hasOffset);
|
||||
}
|
||||
|
||||
template <typename ParserResult>
|
||||
bool CompareNormalized(std::string const & original, ParserResult const & pretendent)
|
||||
{
|
||||
auto originalCopy = original;
|
||||
auto pretendentCopy = ToString(pretendent);
|
||||
|
||||
boost::to_lower(originalCopy);
|
||||
boost::to_lower(pretendentCopy);
|
||||
|
||||
boost::replace_all(originalCopy, "off", "closed");
|
||||
|
||||
boost::replace_all(originalCopy, " ", "");
|
||||
boost::replace_all(pretendentCopy, " ", "");
|
||||
|
||||
return pretendentCopy == originalCopy;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
Parsed,
|
||||
Serialised,
|
||||
Period,
|
||||
Plus,
|
||||
// True if a rule has Timespen with more than 24 hours at the end
|
||||
// or and greater than start.
|
||||
// Example:
|
||||
// 12:00-29:00
|
||||
// 13:12-06:15
|
||||
ExtendedHours,
|
||||
Offset,
|
||||
Count_
|
||||
};
|
||||
using TRuleFeatures = std::array<bool, Count_>;
|
||||
|
||||
std::ostream & operator<<(std::ostream & ost, TRuleFeatures const & f)
|
||||
{
|
||||
std::copy(begin(f), end(f), std::ostream_iterator<bool>(ost, "\t"));
|
||||
return ost;
|
||||
}
|
||||
|
||||
TRuleFeatures DescribeRule(osmoh::TRuleSequences const & rule)
|
||||
{
|
||||
TRuleFeatures features{};
|
||||
for (auto const & r : rule)
|
||||
{
|
||||
features[Period] |= HasPeriod(r.GetTimes());
|
||||
features[Period] |= HasPeriod(r.GetMonths());
|
||||
features[Period] |= HasPeriod(r.GetYears());
|
||||
features[Period] |= HasPeriod(r.GetWeeks());
|
||||
|
||||
features[Plus] |= HasPlus(r.GetTimes());
|
||||
features[Plus] |= HasPlus(r.GetMonths());
|
||||
features[Plus] |= HasPlus(r.GetYears());
|
||||
|
||||
features[Offset] |= HasOffset(r.GetMonths());
|
||||
features[Offset] |= HasOffset(r.GetWeekdays());
|
||||
|
||||
features[ExtendedHours] |= HasExtendedHours(r.GetTimes());
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/// How to run:
|
||||
/// 1. copy opening-count.lst to where the binary is
|
||||
/// 2. run with --log_level=message
|
||||
BOOST_AUTO_TEST_CASE(OpeningHours_CountFailed)
|
||||
{
|
||||
std::ifstream datalist("opening-count.lst");
|
||||
BOOST_REQUIRE_MESSAGE(datalist.is_open(),
|
||||
"Can't open ./opening-count.lst: " << std::strerror(errno));
|
||||
|
||||
std::string line;
|
||||
|
||||
size_t line_num = 0;
|
||||
size_t num_failed = 0;
|
||||
size_t num_total = 0;
|
||||
|
||||
std::map<size_t, size_t> hist;
|
||||
std::map<TRuleFeatures, size_t> featuresDistrib;
|
||||
|
||||
while (std::getline(datalist, line))
|
||||
{
|
||||
size_t count = 1;
|
||||
std::string datastr;
|
||||
|
||||
auto d = line.find('|');
|
||||
if (d == std::string::npos)
|
||||
{
|
||||
BOOST_WARN_MESSAGE((d != std::string::npos),
|
||||
"Incorrect line " << line_num << " format: " << line);
|
||||
datastr = line;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = std::stol(line.substr(0, d));
|
||||
datastr = line.substr(d + 1);
|
||||
}
|
||||
|
||||
line_num++;
|
||||
|
||||
osmoh::TRuleSequences rule;
|
||||
auto const isParsed = Parse(datastr, rule);
|
||||
TRuleFeatures features{};
|
||||
|
||||
if (isParsed)
|
||||
features = DescribeRule(rule);
|
||||
features[Parsed] = true;
|
||||
features[Serialised] = true;
|
||||
|
||||
if (!isParsed)
|
||||
{
|
||||
num_failed += count;
|
||||
++hist[count];
|
||||
features[Parsed] = false;
|
||||
features[Serialised] = false;
|
||||
BOOST_TEST_MESSAGE("-- " << count << " :[" << datastr << "]");
|
||||
}
|
||||
else if (!CompareNormalized(datastr, rule))
|
||||
{
|
||||
num_failed += count;
|
||||
++hist[count];
|
||||
features[Serialised] = false;
|
||||
BOOST_TEST_MESSAGE("- " << count << " :[" << datastr << "]");
|
||||
BOOST_TEST_MESSAGE("+ " << count << " :[" << ToString(rule) << "]");
|
||||
}
|
||||
|
||||
featuresDistrib[features] += count;
|
||||
num_total += count;
|
||||
}
|
||||
|
||||
BOOST_CHECK_MESSAGE((num_failed == 0),
|
||||
"Failed " << num_failed <<
|
||||
" of " << num_total <<
|
||||
" (" << double(num_failed)/(double(num_total)/100) << "%)");
|
||||
|
||||
{
|
||||
std::stringstream message;
|
||||
for (auto const & e : hist)
|
||||
message << "Weight: " << e.first << " Count: " << e.second << std::endl;
|
||||
|
||||
BOOST_TEST_MESSAGE(message.str());
|
||||
}
|
||||
{
|
||||
std::stringstream message;
|
||||
message << "Parsed\tSerialised\tPeriod\tPlus\tExtendedHours\tOffset\tCount" << std::endl;
|
||||
for (auto const & e : featuresDistrib)
|
||||
message << e.first << '\t' << e.second << std::endl;
|
||||
|
||||
BOOST_TEST_MESSAGE(message.str());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
TARGET = opening_hours_integration_tests
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
TEMPLATE = app
|
||||
|
||||
ROOT_DIR = ../../..
|
||||
DEPENDENCIES += opening_hours \
|
||||
|
||||
include($$ROOT_DIR/common.pri)
|
||||
|
||||
OPENING_HOURS_INCLUDE = $$ROOT_DIR/3party/opening_hours
|
||||
INCLUDEPATH += $$OPENING_HOURS_INCLUDE
|
||||
|
||||
HEADERS += $$OPENING_HOURS_INCLUDE/opening_hours.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/parse_opening_hours.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/rules_evaluation.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/rules_evaluation_private.hpp
|
||||
|
||||
SOURCES += opening_hours_integration_tests.cpp
|
488
3party/opening_hours/opening_hours_parsers.hpp
Normal file
488
3party/opening_hours/opening_hours_parsers.hpp
Normal file
|
@ -0,0 +1,488 @@
|
|||
#pragma once
|
||||
|
||||
#include "opening_hours.hpp"
|
||||
|
||||
// #define BOOST_SPIRIT_DEBUG
|
||||
#define BOOST_SPIRIT_USE_PHOENIX_V3
|
||||
#include <boost/spirit/include/phoenix_bind.hpp>
|
||||
#include <boost/spirit/include/phoenix_fusion.hpp>
|
||||
#include <boost/spirit/include/phoenix_object.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/spirit/include/phoenix_statement.hpp>
|
||||
#include <boost/spirit/include/phoenix_stl.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/date_time/gregorian/gregorian.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
#else
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/date_time/gregorian/gregorian.hpp>
|
||||
#endif
|
||||
|
||||
#include "opening_hours_parsers_terminals.hpp"
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
namespace parsing
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace charset = boost::spirit::standard_wide;
|
||||
|
||||
using space_type = charset::space_type;
|
||||
|
||||
template <class Iterator>
|
||||
class year_selector : public qi::grammar<Iterator, osmoh::TYearRanges(), space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, osmoh::YearRange(), space_type> year_range;
|
||||
qi::rule<Iterator, osmoh::TYearRanges(), space_type> main;
|
||||
|
||||
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;
|
||||
using osmoh::YearRange;
|
||||
|
||||
static const qi::int_parser<unsigned, 10, 4, 4> year = {};
|
||||
|
||||
year_range = (year >> dash >> year >> '/' >> uint_) [bind(&YearRange::SetStart, _val, _1),
|
||||
bind(&YearRange::SetEnd, _val, _2),
|
||||
bind(&YearRange::SetPeriod, _val, _3)]
|
||||
| (year >> dash >> year) [bind(&YearRange::SetStart, _val, _1),
|
||||
bind(&YearRange::SetEnd, _val, _2)]
|
||||
| (year >> lit('+')) [bind(&YearRange::SetStart, _val, _1),
|
||||
bind(&YearRange::SetPlus, _val, true)]
|
||||
| year [bind(&YearRange::SetStart, _val, _1)]
|
||||
;
|
||||
|
||||
main %= (year_range % ',');
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class week_selector : public qi::grammar<Iterator, osmoh::TWeekRanges(), space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, osmoh::WeekRange(), space_type> week;
|
||||
qi::rule<Iterator, osmoh::TWeekRanges(), space_type> main;
|
||||
|
||||
public:
|
||||
week_selector() : week_selector::base_type(main)
|
||||
{
|
||||
using qi::uint_;
|
||||
using qi::lit;
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_3;
|
||||
using qi::_val;
|
||||
using osmoh::WeekRange;
|
||||
|
||||
week = (weeknum >> dash >> weeknum >> '/' >> uint_) [bind(&WeekRange::SetStart, _val, _1),
|
||||
bind(&WeekRange::SetEnd, _val, _2),
|
||||
bind(&WeekRange::SetPeriod, _val, _3)]
|
||||
| (weeknum >> dash >> weeknum) [bind(&WeekRange::SetStart, _val, _1),
|
||||
bind(&WeekRange::SetEnd, _val, _2)]
|
||||
| weeknum [bind(&WeekRange::SetStart, _val, _1)]
|
||||
;
|
||||
|
||||
main %= charset::no_case[lit("week")] >> (week % ',');
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class month_selector : public qi::grammar<Iterator, TMonthdayRanges(), space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, int32_t(), space_type, qi::locals<int32_t>> day_offset;
|
||||
qi::rule<Iterator, DateOffset(), space_type, qi::locals<bool>> date_offset;
|
||||
|
||||
qi::rule<Iterator, MonthDay(), space_type> date_left;
|
||||
qi::rule<Iterator, MonthDay(), space_type> date_right;
|
||||
qi::rule<Iterator, MonthDay(), space_type> date_from;
|
||||
qi::rule<Iterator, MonthDay(), space_type> date_to;
|
||||
qi::rule<Iterator, MonthDay(), space_type> date_from_with_offset;
|
||||
qi::rule<Iterator, MonthDay(), space_type> date_to_with_offset;
|
||||
|
||||
qi::rule<Iterator, MonthdayRange(), space_type> monthday_range;
|
||||
qi::rule<Iterator, TMonthdayRanges(), space_type> main;
|
||||
|
||||
public:
|
||||
month_selector() : month_selector::base_type(main)
|
||||
{
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_3;
|
||||
using qi::_a;
|
||||
using qi::_val;
|
||||
using qi::uint_;
|
||||
using qi::ushort_;
|
||||
using qi::lit;
|
||||
using qi::double_;
|
||||
using qi::lexeme;
|
||||
using osmoh::DateOffset;
|
||||
using osmoh::MonthDay;
|
||||
using osmoh::MonthdayRange;
|
||||
|
||||
static const qi::int_parser<unsigned, 10, 4, 4> year = {};
|
||||
|
||||
day_offset = ((lit('+')[_a = 1] | lit('-')[_a = -1]) >>
|
||||
ushort_ >> charset::no_case[(lit("days") | lit("day"))]) [_val = _a * _1];
|
||||
|
||||
date_offset = ((lit('+')[_a = true] | lit('-')[_a = false])
|
||||
>> charset::no_case[wdays] >> day_offset)
|
||||
[bind(&DateOffset::SetWDayOffset, _val, _1),
|
||||
bind(&DateOffset::SetOffset, _val, _2),
|
||||
bind(&DateOffset::SetWDayOffsetPositive, _val, _a)]
|
||||
| ((lit('+')[_a = true] | lit('-') [_a = false]) >> charset::no_case[wdays])
|
||||
[bind(&DateOffset::SetWDayOffset, _val, _1),
|
||||
bind(&DateOffset::SetWDayOffsetPositive, _val, _a)]
|
||||
| day_offset [bind(&DateOffset::SetOffset, _val, _1)]
|
||||
;
|
||||
|
||||
date_left = (year >> charset::no_case[month]) [bind(&MonthDay::SetYear, _val, _1),
|
||||
bind(&MonthDay::SetMonth, _val, _2)]
|
||||
|
||||
| charset::no_case[month] [bind(&MonthDay::SetMonth, _val, _1)]
|
||||
;
|
||||
|
||||
date_right = charset::no_case[month] [bind(&MonthDay::SetMonth, _val, _1)]
|
||||
;
|
||||
|
||||
date_from = (date_left >> (daynum >> !(lit(':') >> qi::digit)))
|
||||
[_val = _1, bind(&MonthDay::SetDayNum, _val, _2)]
|
||||
| (year >> charset::no_case[lit("easter")]) [bind(&MonthDay::SetYear, _val, _1),
|
||||
bind(&MonthDay::SetVariableDate, _val,
|
||||
MonthDay::VariableDate::Easter)]
|
||||
| charset::no_case[lit("easter")] [bind(&MonthDay::SetVariableDate, _val,
|
||||
MonthDay::VariableDate::Easter)]
|
||||
;
|
||||
|
||||
date_to = date_from [_val = _1]
|
||||
| (daynum >> !(lit(':') >> qi::digit)) [bind(&MonthDay::SetDayNum, _val, _1)]
|
||||
;
|
||||
|
||||
date_from_with_offset = (date_from >> date_offset)
|
||||
[_val = _1, bind(&MonthDay::SetOffset, _val, _2)]
|
||||
| date_from [_val = _1]
|
||||
;
|
||||
|
||||
date_to_with_offset = (date_to >> date_offset)
|
||||
[_val = _1, bind(&MonthDay::SetOffset, _val, _2)]
|
||||
| date_to [_val = _1]
|
||||
;
|
||||
|
||||
monthday_range = (date_from_with_offset >> dash >> date_to_with_offset)
|
||||
[bind(&MonthdayRange::SetStart, _val, _1),
|
||||
bind(&MonthdayRange::SetEnd, _val, _2)]
|
||||
| (date_from_with_offset >> '+') [bind(&MonthdayRange::SetStart, _val, _1),
|
||||
bind(&MonthdayRange::SetPlus, _val, true)]
|
||||
| (date_left >> dash >> date_right >> '/' >> uint_)
|
||||
[bind(&MonthdayRange::SetStart, _val, _1),
|
||||
bind(&MonthdayRange::SetEnd, _val, _2),
|
||||
bind(&MonthdayRange::SetPeriod, _val, _3)]
|
||||
| (date_left >> lit("-") >> date_right) [bind(&MonthdayRange::SetStart, _val, _1),
|
||||
bind(&MonthdayRange::SetEnd, _val, _2)]
|
||||
| date_from [bind(&MonthdayRange::SetStart, _val, _1)]
|
||||
| date_left [bind(&MonthdayRange::SetStart, _val, _1)]
|
||||
;
|
||||
|
||||
main %= (monthday_range % ',');
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(monthday_range);
|
||||
BOOST_SPIRIT_DEBUG_NODE(day_offset);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_offset);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_left);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_right);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_from);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_to);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_from_with_offset);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_to_with_offset);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class weekday_selector : public qi::grammar<Iterator, osmoh::Weekdays(), space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, osmoh::NthWeekdayOfTheMonthEntry::NthDayOfTheMonth(), space_type> nth;
|
||||
qi::rule<Iterator, osmoh::NthWeekdayOfTheMonthEntry(), space_type> nth_entry;
|
||||
qi::rule<Iterator, int32_t(), space_type, qi::locals<int8_t>> day_offset;
|
||||
qi::rule<Iterator, osmoh::WeekdayRange(), space_type> weekday_range;
|
||||
qi::rule<Iterator, osmoh::TWeekdayRanges(), space_type> weekday_sequence;
|
||||
qi::rule<Iterator, osmoh::Holiday(), space_type> holiday;
|
||||
qi::rule<Iterator, osmoh::THolidays(), space_type> holiday_sequence;
|
||||
qi::rule<Iterator, osmoh::Weekdays(), space_type> main;
|
||||
|
||||
public:
|
||||
weekday_selector() : weekday_selector::base_type(main)
|
||||
{
|
||||
using qi::_a;
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_val;
|
||||
using qi::lit;
|
||||
using qi::ushort_;
|
||||
using boost::phoenix::bind;
|
||||
using osmoh::NthWeekdayOfTheMonthEntry;
|
||||
using osmoh::Holiday;
|
||||
using osmoh::WeekdayRange;
|
||||
using osmoh::Weekdays;
|
||||
|
||||
nth = ushort_(1)[_val = NthWeekdayOfTheMonthEntry::NthDayOfTheMonth::First]
|
||||
| ushort_(2) [_val = NthWeekdayOfTheMonthEntry::NthDayOfTheMonth::Second]
|
||||
| ushort_(3) [_val = NthWeekdayOfTheMonthEntry::NthDayOfTheMonth::Third]
|
||||
| ushort_(4) [_val = NthWeekdayOfTheMonthEntry::NthDayOfTheMonth::Fourth]
|
||||
| ushort_(5) [_val = NthWeekdayOfTheMonthEntry::NthDayOfTheMonth::Fifth];
|
||||
|
||||
nth_entry = (nth >> dash >> nth) [bind(&NthWeekdayOfTheMonthEntry::SetStart, _val, _1),
|
||||
bind(&NthWeekdayOfTheMonthEntry::SetEnd, _val, _2)]
|
||||
| (lit('-') >> nth) [bind(&NthWeekdayOfTheMonthEntry::SetEnd, _val, _1)]
|
||||
| nth [bind(&NthWeekdayOfTheMonthEntry::SetStart, _val, _1)]
|
||||
;
|
||||
|
||||
day_offset =
|
||||
( (lit('+')[_a = 1] | lit('-') [_a = -1]) >>
|
||||
ushort_ [_val = _1 * _a] >>
|
||||
charset::no_case[(lit("days") | lit("day"))] )
|
||||
;
|
||||
|
||||
holiday = (charset::no_case[lit("SH")] [bind(&Holiday::SetPlural, _val, false)]
|
||||
>> -day_offset [bind(&Holiday::SetOffset, _val, _1)])
|
||||
| charset::no_case[lit("PH")] [bind(&Holiday::SetPlural, _val, true)]
|
||||
;
|
||||
|
||||
holiday_sequence %= (holiday % ',');
|
||||
|
||||
weekday_range =
|
||||
( charset::no_case[wdays] [bind(&WeekdayRange::SetStart, _val, _1)] >>
|
||||
'[' >> (nth_entry [bind(&WeekdayRange::AddNth, _val, _1)]) % ',') >> ']' >>
|
||||
-(day_offset [bind(&WeekdayRange::SetOffset, _val, _1)])
|
||||
| charset::no_case[(wdays >> dash >> wdays)] [bind(&WeekdayRange::SetStart, _val, _1),
|
||||
bind(&WeekdayRange::SetEnd, _val, _2)]
|
||||
| charset::no_case[wdays] [bind(&WeekdayRange::SetStart, _val, _1)]
|
||||
;
|
||||
|
||||
weekday_sequence %= (weekday_range % ',') >> !qi::no_skip[charset::alpha]
|
||||
;
|
||||
|
||||
main = (holiday_sequence >> -lit(',') >> weekday_sequence)
|
||||
[bind(&Weekdays::SetHolidays, _val, _1),
|
||||
bind(&Weekdays::SetWeekdayRanges, _val, _2)]
|
||||
| holiday_sequence [bind(&Weekdays::SetHolidays, _val, _1)]
|
||||
| weekday_sequence [bind(&Weekdays::SetWeekdayRanges, _val, _1)]
|
||||
;
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(weekday_sequence);
|
||||
BOOST_SPIRIT_DEBUG_NODE(weekday_range);
|
||||
BOOST_SPIRIT_DEBUG_NODE(holiday_sequence);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class time_selector : public qi::grammar<Iterator, osmoh::TTimespans(), space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, osmoh::HourMinutes(), space_type> hour_minutes;
|
||||
qi::rule<Iterator, osmoh::HourMinutes(), space_type> extended_hour_minutes;
|
||||
qi::rule<Iterator, osmoh::TimeEvent(), space_type> variable_time;
|
||||
qi::rule<Iterator, osmoh::Time(), space_type> extended_time;
|
||||
qi::rule<Iterator, osmoh::Time(), space_type> time;
|
||||
qi::rule<Iterator, osmoh::Timespan(), space_type> timespan;
|
||||
qi::rule<Iterator, osmoh::TTimespans(), space_type> main;
|
||||
|
||||
public:
|
||||
time_selector() : time_selector::base_type(main)
|
||||
{
|
||||
using qi::int_;
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_3;
|
||||
using qi::_a;
|
||||
using qi::_val;
|
||||
using qi::lit;
|
||||
using charset::char_;
|
||||
using boost::phoenix::bind;
|
||||
using boost::phoenix::construct;
|
||||
using osmoh::HourMinutes;
|
||||
using osmoh::TimeEvent;
|
||||
using osmoh::Time;
|
||||
using osmoh::Timespan;
|
||||
|
||||
hour_minutes =
|
||||
(hours >> lit(':') >> minutes) [bind(&HourMinutes::AddDuration, _val, _1),
|
||||
bind(&HourMinutes::AddDuration, _val, _2)]
|
||||
;
|
||||
|
||||
extended_hour_minutes =
|
||||
(exthours >> lit(':') >> minutes)[bind(&HourMinutes::AddDuration, _val, _1),
|
||||
bind(&HourMinutes::AddDuration, _val, _2)]
|
||||
;
|
||||
|
||||
variable_time =
|
||||
( lit('(')
|
||||
>> charset::no_case[event] [bind(&TimeEvent::SetEvent, _val, _1)]
|
||||
>> ( (lit('+') >> hour_minutes) [bind(&TimeEvent::SetOffset, _val, _1)]
|
||||
| (lit('-') >> hour_minutes) [bind(&TimeEvent::SetOffset, _val, -_1)] )
|
||||
>> lit(')')
|
||||
)
|
||||
| charset::no_case[event][bind(&TimeEvent::SetEvent, _val, _1)]
|
||||
;
|
||||
|
||||
extended_time = extended_hour_minutes [bind(&Time::SetHourMinutes, _val, _1)]
|
||||
| variable_time [bind(&Time::SetEvent, _val, _1)]
|
||||
;
|
||||
|
||||
time = hour_minutes [bind(&Time::SetHourMinutes, _val, _1)]
|
||||
| variable_time [bind(&Time::SetEvent, _val, _1)]
|
||||
;
|
||||
|
||||
timespan =
|
||||
(time >> dash >> extended_time >> '/' >> hour_minutes)
|
||||
[bind(&Timespan::SetStart, _val, _1),
|
||||
bind(&Timespan::SetEnd, _val, _2),
|
||||
bind(&Timespan::SetPeriod, _val, _3)]
|
||||
|
||||
| (time >> dash >> extended_time >> '/' >> minutes)
|
||||
[bind(&Timespan::SetStart, _val, _1),
|
||||
bind(&Timespan::SetEnd, _val, _2),
|
||||
bind(&Timespan::SetPeriod, _val, _3)]
|
||||
|
||||
| (time >> dash >> extended_time >> '+')
|
||||
[bind(&Timespan::SetStart, _val, _1),
|
||||
bind(&Timespan::SetEnd, _val, _2),
|
||||
bind(&Timespan::SetPlus, _val, true)]
|
||||
|
||||
| (time >> dash >> extended_time)
|
||||
[bind(&Timespan::SetStart, _val, _1),
|
||||
bind(&Timespan::SetEnd, _val, _2)]
|
||||
|
||||
| (time >> '+')
|
||||
[bind(&Timespan::SetStart, _val, _1),
|
||||
bind(&Timespan::SetPlus, _val, true)]
|
||||
|
||||
| time[bind(&Timespan::SetStart, _val, _1)]
|
||||
;
|
||||
|
||||
main %= timespan % ',';
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(timespan);
|
||||
BOOST_SPIRIT_DEBUG_NODE(time);
|
||||
BOOST_SPIRIT_DEBUG_NODE(extended_time);
|
||||
BOOST_SPIRIT_DEBUG_NODE(variable_time);
|
||||
BOOST_SPIRIT_DEBUG_NODE(extended_hour_minutes);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class time_domain : public qi::grammar<Iterator, osmoh::TRuleSequences(), space_type>
|
||||
{
|
||||
protected:
|
||||
weekday_selector<Iterator> weekday_selector;
|
||||
time_selector<Iterator> time_selector;
|
||||
year_selector<Iterator> year_selector;
|
||||
month_selector<Iterator> month_selector;
|
||||
week_selector<Iterator> week_selector;
|
||||
|
||||
qi::rule<Iterator, std::string()> comment;
|
||||
qi::rule<Iterator, std::string(), space_type> separator;
|
||||
|
||||
qi::rule<Iterator, qi::unused_type(osmoh::RuleSequence &), space_type> small_range_selectors;
|
||||
qi::rule<Iterator, qi::unused_type(osmoh::RuleSequence &), space_type> wide_range_selectors;
|
||||
qi::rule<Iterator, qi::unused_type(osmoh::RuleSequence &), space_type> rule_modifier;
|
||||
|
||||
qi::rule<Iterator, osmoh::RuleSequence(), space_type> rule_sequence;
|
||||
qi::rule<Iterator, osmoh::TRuleSequences(), space_type> main;
|
||||
|
||||
public:
|
||||
time_domain() : time_domain::base_type(main)
|
||||
{
|
||||
using qi::lit;
|
||||
using qi::lexeme;
|
||||
using qi::_1;
|
||||
using qi::_a;
|
||||
using qi::_r1;
|
||||
using qi::_val;
|
||||
using charset::char_;
|
||||
using qi::eps;
|
||||
using qi::lazy;
|
||||
using phx::back;
|
||||
using phx::push_back;
|
||||
using phx::construct;
|
||||
using osmoh::RuleSequence;
|
||||
|
||||
using Modifier = RuleSequence::Modifier;
|
||||
|
||||
comment %= '"' >> +(char_ - '"') >> '"'
|
||||
;
|
||||
|
||||
separator %= charset::string(";")
|
||||
| charset::string("||")
|
||||
| charset::string(",")
|
||||
;
|
||||
|
||||
wide_range_selectors =
|
||||
( -(year_selector [bind(&RuleSequence::SetYears, _r1, _1)]) >>
|
||||
-(month_selector [bind(&RuleSequence::SetMonths, _r1, _1)]) >>
|
||||
-(week_selector [bind(&RuleSequence::SetWeeks, _r1, _1)]) >>
|
||||
-(lit(':') [bind(&RuleSequence::SetSeparatorForReadability, _r1, true)]))
|
||||
| (comment >> ':') [bind(&RuleSequence::SetComment, _r1, _1)]
|
||||
;
|
||||
|
||||
small_range_selectors =
|
||||
( -(weekday_selector [bind(&RuleSequence::SetWeekdays, _r1, _1)]) >>
|
||||
-(time_selector [bind(&RuleSequence::SetTimes, _r1, _1)]))
|
||||
;
|
||||
|
||||
rule_modifier =
|
||||
(charset::no_case[lit("open")]
|
||||
[bind(&RuleSequence::SetModifier, _r1, Modifier::Open)] >>
|
||||
-(comment [bind(&RuleSequence::SetModifierComment, _r1, _1)]))
|
||||
|
||||
| ((charset::no_case[lit("closed") | lit("off")])
|
||||
[bind(&RuleSequence::SetModifier, _r1, Modifier::Closed)] >>
|
||||
-(comment [bind(&RuleSequence::SetModifierComment, _r1, _1)]))
|
||||
|
||||
| (charset::no_case[lit("unknown")]
|
||||
[bind(&RuleSequence::SetModifier, _r1, Modifier::Unknown)] >>
|
||||
-(comment [bind(&RuleSequence::SetModifierComment, _r1, _1)]))
|
||||
|
||||
| comment [bind(&RuleSequence::SetModifier, _r1, Modifier::Comment),
|
||||
bind(&RuleSequence::SetModifierComment, _r1, _1)]
|
||||
;
|
||||
|
||||
rule_sequence =
|
||||
( lit("24/7") [bind(&RuleSequence::SetTwentyFourHours, _val, true)]
|
||||
| ( -wide_range_selectors(_val) >>
|
||||
-small_range_selectors(_val) )) >>
|
||||
-rule_modifier(_val)
|
||||
;
|
||||
|
||||
main = ( -(lit("opening_hours") >> lit('=')) >>
|
||||
(rule_sequence [push_back(_val, _1)] %
|
||||
(separator [phx::bind(&RuleSequence::SetAnySeparator, back(_val), _1)])))
|
||||
;
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(rule_sequence);
|
||||
BOOST_SPIRIT_DEBUG_NODE(rule_modifier);
|
||||
BOOST_SPIRIT_DEBUG_NODE(small_range_selectors);
|
||||
BOOST_SPIRIT_DEBUG_NODE(wide_range_selectors);
|
||||
}
|
||||
};
|
||||
} // namespace parsing
|
||||
} // namespace osmoh
|
||||
#undef BOOST_SPIRIT_USE_PHOENIX_V3
|
143
3party/opening_hours/opening_hours_parsers_terminals.hpp
Normal file
143
3party/opening_hours/opening_hours_parsers_terminals.hpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
|
||||
// This header file should be used only with opening_hours_parsers.hpp.
|
||||
// It's only purpose is to avoid polution opening_hours_parsers.hpp with
|
||||
// it's content.
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
namespace parsing
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
struct dash_ : public qi::symbols<char>
|
||||
{
|
||||
dash_()
|
||||
{
|
||||
add
|
||||
("-")
|
||||
/* not standard */
|
||||
// (L"–")(L"—")(L"-")(L"~")(L"~")(L"〜")(L"to")(L"às")(L"ás")(L"as")(L"a")(L"ate")(L"bis")
|
||||
;
|
||||
}
|
||||
} dash;
|
||||
|
||||
struct event_ : public qi::symbols<char, osmoh::TimeEvent::Event>
|
||||
{
|
||||
event_()
|
||||
{
|
||||
add
|
||||
("dawn", osmoh::TimeEvent::Event::Sunrise)
|
||||
("sunrise", osmoh::TimeEvent::Event::Sunrise)
|
||||
("sunset", osmoh::TimeEvent::Event::Sunset)
|
||||
("dusk", osmoh::TimeEvent::Event::Sunset)
|
||||
;
|
||||
}
|
||||
} event;
|
||||
|
||||
struct wdays_ : qi::symbols<char, osmoh::Weekday>
|
||||
{
|
||||
wdays_()
|
||||
{
|
||||
add
|
||||
("su", 1_weekday)("mo", 2_weekday)("tu", 3_weekday)("we", 4_weekday)("th", 5_weekday)("fr", 6_weekday)("sa", 7_weekday) // en
|
||||
// (L"mon", 0)(L"tue", 1)(L"wed", 2)(L"thu", 3)(L"fri", 4)(L"sat", 5)(L"sun", 6) // en
|
||||
// (L"пн", 0)(L"вт", 1)(L"ср", 2)(L"чт", 3)(L"пт", 4)(L"сб", 5)(L"вс", 6) // ru
|
||||
// (L"пн.", 0)(L"вт.", 1)(L"ср.", 2)(L"чт.", 3)(L"пт.", 4)(L"сб.", 5)(L"вс.", 6) // ru
|
||||
// (L"lu", 0)(L"ma", 1)(L"me", 2)(L"je", 3)(L"ve", 4)(L"sa", 5)(L"di", 6) // fr
|
||||
// (L"lu", 0)(L"ma", 1)(L"me", 2)(L"gi", 3)(L"ve", 4)(L"sa", 5)(L"do", 6) // it
|
||||
// (L"lu", 0)(L"ma", 1)(L"mi", 2)(L"ju", 3)(L"vie", 4)(L"sá", 5)(L"do", 6) // sp
|
||||
// (L"週一", 0)(L"週二", 1)(L"週三", 2)(L"週四", 3)(L"週五", 4)(L"週六", 5)(L"週日", 6) // ch traditional
|
||||
// (L"senin", 0)(L"selasa", 1)(L"rabu", 2)(L"kamis", 3)(L"jum'at", 4)(L"sabtu", 5)(L"minggu", 6) // indonesian
|
||||
|
||||
// (L"wd", 2)
|
||||
|
||||
;
|
||||
}
|
||||
} wdays;
|
||||
|
||||
struct month_ : qi::symbols<char, osmoh::MonthDay::Month>
|
||||
{
|
||||
month_()
|
||||
{
|
||||
add
|
||||
("jan", 1_M)("feb", 2_M)("mar", 3_M)("apr", 4_M)("may", 5_M)("jun", 6_M)
|
||||
("jul", 7_M)("aug", 8_M)("sep", 9_M)("oct", 10_M)("nov", 11_M)("dec", 12_M)
|
||||
;
|
||||
}
|
||||
} month;
|
||||
|
||||
struct hours_ : qi::symbols<char, osmoh::Time::THours>
|
||||
{
|
||||
hours_()
|
||||
{
|
||||
add
|
||||
( "0", 0_h)( "1", 1_h)( "2", 2_h)( "3", 3_h)( "4", 4_h)( "5", 5_h)( "6", 6_h)( "7", 7_h)( "8", 8_h)( "9", 9_h) /* not standard */
|
||||
("00", 0_h)("01", 1_h)("02", 2_h)("03", 3_h)("04", 4_h)("05", 5_h)("06", 6_h)("07", 7_h)("08", 8_h)("09", 9_h)
|
||||
("10", 10_h)("11", 11_h)("12", 12_h)("13", 13_h)("14", 14_h)("15", 15_h)("16", 16_h)("17", 17_h)("18", 18_h)("19", 19_h)
|
||||
("20", 20_h)("21", 21_h)("22", 22_h)("23", 23_h)("24", 24_h)
|
||||
;
|
||||
}
|
||||
} hours;
|
||||
|
||||
struct exthours_ : qi::symbols<char, osmoh::Time::THours>
|
||||
{
|
||||
exthours_()
|
||||
{
|
||||
add
|
||||
( "0", 0_h)( "1", 1_h)( "2", 2_h)( "3", 3_h)( "4", 4_h)( "5", 5_h)( "6", 6_h)( "7", 7_h)( "8", 8_h)( "9", 9_h) /* not standard */
|
||||
("00", 0_h)("01", 1_h)("02", 2_h)("03", 3_h)("04", 4_h)("05", 5_h)("06", 6_h)("07", 7_h)("08", 8_h)("09", 9_h)
|
||||
("10", 10_h)("11", 11_h)("12", 12_h)("13", 13_h)("14", 14_h)("15", 15_h)("16", 16_h)("17", 17_h)("18", 18_h)("19", 19_h)
|
||||
("20", 20_h)("21", 21_h)("22", 22_h)("23", 23_h)("24", 24_h)("25", 25_h)("26", 26_h)("27", 27_h)("28", 28_h)("29", 29_h)
|
||||
("30", 30_h)("31", 31_h)("32", 32_h)("33", 33_h)("34", 34_h)("35", 35_h)("36", 36_h)("37", 37_h)("38", 38_h)("39", 39_h)
|
||||
("40", 40_h)("41", 41_h)("42", 42_h)("43", 43_h)("44", 44_h)("45", 45_h)("46", 46_h)("47", 47_h)("48", 48_h)
|
||||
;
|
||||
}
|
||||
} exthours;
|
||||
|
||||
struct minutes_ : qi::symbols<char, osmoh::Time::TMinutes>
|
||||
{
|
||||
minutes_()
|
||||
{
|
||||
add
|
||||
( "0", 0_min)( "1", 1_min)( "2", 2_min)( "3", 3_min)( "4", 4_min)( "5", 5_min)( "6", 6_min)( "7", 7_min)( "8", 8_min)( "9", 9_min) /* not standard */
|
||||
("00", 0_min)("01", 1_min)("02", 2_min)("03", 3_min)("04", 4_min)("05", 5_min)("06", 6_min)("07", 7_min)("08", 8_min)("09", 9_min)
|
||||
("10", 10_min)("11", 11_min)("12", 12_min)("13", 13_min)("14", 14_min)("15", 15_min)("16", 16_min)("17", 17_min)("18", 18_min)("19", 19_min)
|
||||
("20", 20_min)("21", 21_min)("22", 22_min)("23", 23_min)("24", 24_min)("25", 25_min)("26", 26_min)("27", 27_min)("28", 28_min)("29", 29_min)
|
||||
("30", 30_min)("31", 31_min)("32", 32_min)("33", 33_min)("34", 34_min)("35", 35_min)("36", 36_min)("37", 37_min)("38", 38_min)("39", 39_min)
|
||||
("40", 40_min)("41", 41_min)("42", 42_min)("43", 43_min)("44", 44_min)("45", 45_min)("46", 46_min)("47", 47_min)("48", 48_min)("49", 49_min)
|
||||
("50", 50_min)("51", 51_min)("52", 52_min)("53", 53_min)("54", 54_min)("55", 55_min)("56", 56_min)("57", 57_min)("58", 58_min)("59", 59_min)
|
||||
;
|
||||
}
|
||||
} minutes;
|
||||
|
||||
struct weeknum_ : qi::symbols<char, unsigned>
|
||||
{
|
||||
weeknum_()
|
||||
{
|
||||
add
|
||||
( "1", 1)( "2", 2)( "3", 3)( "4", 4)( "5", 5)( "6", 6)( "7", 7)( "8", 8)( "9", 9)
|
||||
("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
|
||||
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
|
||||
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)("25", 25)("26", 26)("27", 27)("28", 28)("29", 29)
|
||||
("30", 30)("31", 31)("32", 32)("33", 33)("34", 34)("35", 35)("36", 36)("37", 37)("38", 38)("39", 39)
|
||||
("40", 40)("41", 41)("42", 42)("43", 43)("44", 44)("45", 45)("46", 46)("47", 47)("48", 48)("49", 49)
|
||||
("50", 50)("51", 51)("52", 52)("53", 53)
|
||||
;
|
||||
}
|
||||
} weeknum;
|
||||
|
||||
struct daynum_ : qi::symbols<char, MonthDay::TDayNum>
|
||||
{
|
||||
daynum_()
|
||||
{
|
||||
add
|
||||
("1", 1)("2", 2)("3", 3)("4", 4)("5", 5)("6", 6)("7", 7)("8", 8)("9", 9)
|
||||
("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
|
||||
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
|
||||
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)("25", 25)("26", 26)("27", 27)("28", 28)("29", 29)
|
||||
("30", 30)("31", 31)
|
||||
;
|
||||
}
|
||||
} daynum;
|
||||
} // namespace parsing
|
||||
} // namespace osmoh
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,19 @@
|
|||
TARGET = opening_hours_supported_features_tests
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
TEMPLATE = app
|
||||
|
||||
ROOT_DIR = ../../..
|
||||
DEPENDENCIES += opening_hours \
|
||||
|
||||
include($$ROOT_DIR/common.pri)
|
||||
|
||||
OPENING_HOURS_INCLUDE = $$ROOT_DIR/3party/opening_hours
|
||||
INCLUDEPATH += $$OPENING_HOURS_INCLUDE
|
||||
|
||||
HEADERS += $$OPENING_HOURS_INCLUDE/opening_hours.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/parse_opening_hours.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/rules_evaluation.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/rules_evaluation_private.hpp
|
||||
|
||||
SOURCES += opening_hours_supported_features_tests.cpp
|
1388
3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp
Normal file
1388
3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,19 @@
|
|||
TARGET = opening_hours_tests
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
TEMPLATE = app
|
||||
|
||||
ROOT_DIR = ../../..
|
||||
DEPENDENCIES += opening_hours \
|
||||
|
||||
include($$ROOT_DIR/common.pri)
|
||||
|
||||
OPENING_HOURS_INCLUDE = $$ROOT_DIR/3party/opening_hours
|
||||
INCLUDEPATH += $$OPENING_HOURS_INCLUDE
|
||||
|
||||
HEADERS += $$OPENING_HOURS_INCLUDE/opening_hours.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/parse_opening_hours.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/rules_evaluation.hpp \
|
||||
$$OPENING_HOURS_INCLUDE/rules_evaluation_private.hpp
|
||||
|
||||
SOURCES += opening_hours_tests.cpp
|
|
@ -1,951 +0,0 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Mail.Ru Group
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "osm_time_range.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <vector>
|
||||
#include <codecvt>
|
||||
|
||||
//#define BOOST_SPIRIT_DEBUG 1
|
||||
#define BOOST_SPIRIT_USE_PHOENIX_V3
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/spirit/include/phoenix_fusion.hpp>
|
||||
#include <boost/spirit/include/phoenix_stl.hpp>
|
||||
#include <boost/spirit/include/phoenix_statement.hpp>
|
||||
#include <boost/spirit/include/phoenix_bind.hpp>
|
||||
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/date_time/gregorian/gregorian.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
#else
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/date_time/gregorian/gregorian.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
|
||||
std::ostream & operator << (std::ostream & s, Time const & t)
|
||||
{
|
||||
bool event = (t.flags & Time::eSunrise) || (t.flags & Time::eSunset);
|
||||
if (event)
|
||||
s << ((t.flags & Time::eSunrise) ? "sunrise" : "sunset") << " (";
|
||||
std::ios_base::fmtflags sf = s.flags();
|
||||
if (t.flags & (Time::ePlus | Time::eMinus))
|
||||
s << ((t.flags & Time::ePlus) ? "+" : "-");
|
||||
if (t.flags & Time::eHours)
|
||||
s << std::setw(2) << std::setfill('0') << (int)t.hours;
|
||||
if (t.flags & Time::eMinutes)
|
||||
s << ":" << std::setw(2) << std::setfill('0') << (int)t.minutes;
|
||||
s.flags(sf);
|
||||
if (event)
|
||||
s << ")";
|
||||
return s;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & s, TimeSpan const & span)
|
||||
{
|
||||
s << span.from;
|
||||
if (span.to.flags)
|
||||
s << '-' << span.to;
|
||||
if (span.flags == Time::ePlus)
|
||||
s << "...";
|
||||
if (span.flags == Time::eExt)
|
||||
s << '/' << span.period;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & s, Weekdays const & w)
|
||||
{
|
||||
static char const * wdays[] = {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"};
|
||||
static uint8_t const kDaysInWeek = 7;
|
||||
static uint8_t const kWeeksInMonth = 5;
|
||||
|
||||
for (size_t i = 0; i < kDaysInWeek; ++i)
|
||||
{
|
||||
if (w.weekdays & (1 << i))
|
||||
{
|
||||
if (w.weekdays & ((1 << i) - 1))
|
||||
s << ',';
|
||||
s << wdays[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (w.nth)
|
||||
{
|
||||
s << "[";
|
||||
|
||||
uint8_t a = w.nth & 0xFF;
|
||||
for (size_t i = 0; i < kWeeksInMonth; ++i)
|
||||
{
|
||||
if (a & (1 << i))
|
||||
{
|
||||
if (a & ((1 << i) - 1))
|
||||
s << ',';
|
||||
s << (i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
a = (w.nth >> 8) & 0xFF;
|
||||
for (size_t i = 0; i < kWeeksInMonth; ++i)
|
||||
{
|
||||
if (a & (1 << i))
|
||||
{
|
||||
if (a & ((1 << i) - 1))
|
||||
s << ',';
|
||||
s << '-' << (i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
s << "]";
|
||||
}
|
||||
|
||||
if (w.offset)
|
||||
s << ' ' << w.offset << " day(s)";
|
||||
return s;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & s, State const & w)
|
||||
{
|
||||
static char const * st[] = {"unknown", "closed", "open"};
|
||||
s << ' ' << st[w.state] << " " << w.comment;
|
||||
return s;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & s, TimeRule const & w)
|
||||
{
|
||||
for (auto const & e : w.weekdays)
|
||||
s << e;
|
||||
if (!w.weekdays.empty() && !w.timespan.empty())
|
||||
s << ' ';
|
||||
for (auto const & e : w.timespan)
|
||||
s << e;
|
||||
|
||||
return s << w.state;
|
||||
}
|
||||
|
||||
boost::posix_time::time_period make_time_period(boost::gregorian::date const & d, osmoh::TimeSpan const & ts)
|
||||
{
|
||||
using boost::posix_time::ptime;
|
||||
using boost::posix_time::hours;
|
||||
using boost::posix_time::minutes;
|
||||
using boost::posix_time::time_period;
|
||||
|
||||
/// TODO(yershov@): Need create code for calculate real values
|
||||
ptime sunrise(d, hours(6));
|
||||
ptime sunset(d, hours(19));
|
||||
|
||||
ptime t1, t2;
|
||||
|
||||
if (ts.from.flags & osmoh::Time::eSunrise)
|
||||
t1 = sunrise;
|
||||
else if (ts.from.flags & osmoh::Time::eSunset)
|
||||
t1 = sunset;
|
||||
else
|
||||
t1 = ptime(d, hours((ts.from.flags & osmoh::Time::eHours) ? ts.from.hours : 0) + minutes((ts.from.flags & osmoh::Time::eMinutes) ? ts.from.minutes : 0));
|
||||
|
||||
t2 = t1;
|
||||
|
||||
if (ts.to.flags & osmoh::Time::eSunrise)
|
||||
t2 = sunrise;
|
||||
else if (ts.to.flags & osmoh::Time::eSunset)
|
||||
t2 = sunset;
|
||||
else
|
||||
{
|
||||
t2 = ptime(d, hours((ts.to.flags & osmoh::Time::eHours) ? ts.to.hours : 24) + minutes((ts.to.flags & osmoh::Time::eMinutes) ? ts.to.minutes : 0));
|
||||
if (t2 < t1)
|
||||
t2 += hours(24);
|
||||
}
|
||||
|
||||
return time_period(t1, t2);
|
||||
}
|
||||
|
||||
} // namespace osmoh
|
||||
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT
|
||||
(
|
||||
osmoh::Time,
|
||||
(uint8_t, hours)
|
||||
(uint8_t, minutes)
|
||||
(uint8_t, flags)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT
|
||||
(
|
||||
osmoh::TimeSpan,
|
||||
(osmoh::Time, from)
|
||||
(osmoh::Time, to)
|
||||
(uint8_t, flags)
|
||||
(osmoh::Time, period)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT
|
||||
(
|
||||
osmoh::Weekdays,
|
||||
(uint8_t, weekdays)
|
||||
(uint16_t, nth)
|
||||
(int32_t, offset)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT
|
||||
(
|
||||
osmoh::State,
|
||||
(uint8_t, state)
|
||||
(std::string, comment)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT
|
||||
(
|
||||
osmoh::TimeRule,
|
||||
(std::vector<osmoh::Weekdays>, weekdays)
|
||||
(std::vector<osmoh::TimeSpan>, timespan)
|
||||
(osmoh::State, state)
|
||||
(uint8_t, int_flags)
|
||||
)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace phx = boost::phoenix;
|
||||
|
||||
namespace charset = boost::spirit::standard_wide;
|
||||
using space_type = charset::space_type;
|
||||
|
||||
|
||||
class test_impl
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
struct result { typedef void type; };
|
||||
|
||||
template <typename Arg>
|
||||
void operator() (const Arg & a) const
|
||||
{
|
||||
std::cout << a << " \t(" << typeid(a).name() << ")" << std::endl;
|
||||
}
|
||||
};
|
||||
phx::function<test_impl> const test = test_impl();
|
||||
|
||||
class dash_ : public qi::symbols<wchar_t>
|
||||
{
|
||||
public:
|
||||
dash_()
|
||||
{
|
||||
add
|
||||
(L"-")
|
||||
/* not standard */
|
||||
(L"–")(L"—")(L"-")(L"~")(L"~")(L"〜")(L"to")(L"às")(L"ás")(L"as")(L"a")(L"ate")(L"bis")
|
||||
;
|
||||
}
|
||||
} dash;
|
||||
|
||||
class event_ : public qi::symbols<wchar_t, uint8_t>
|
||||
{
|
||||
public:
|
||||
event_()
|
||||
{
|
||||
add
|
||||
(L"dawn", osmoh::Time::eSunrise)(L"sunrise", osmoh::Time::eSunrise)(L"sunset", osmoh::Time::eSunset)(L"dusk", osmoh::Time::eSunset)
|
||||
;
|
||||
}
|
||||
} event;
|
||||
|
||||
struct wdays_ : qi::symbols<wchar_t, unsigned>
|
||||
{
|
||||
wdays_()
|
||||
{
|
||||
add
|
||||
(L"mo", 0)(L"tu", 1)(L"we", 2)(L"th", 3)(L"fr", 4)(L"sa", 5)(L"su", 6) // en
|
||||
(L"mon", 0)(L"tue", 1)(L"wed", 2)(L"thu", 3)(L"fri", 4)(L"sat", 5)(L"sun", 6) // en
|
||||
(L"пн", 0)(L"вт", 1)(L"ср", 2)(L"чт", 3)(L"пт", 4)(L"сб", 5)(L"вс", 6) // ru
|
||||
(L"пн.", 0)(L"вт.", 1)(L"ср.", 2)(L"чт.", 3)(L"пт.", 4)(L"сб.", 5)(L"вс.", 6) // ru
|
||||
(L"lu", 0)(L"ma", 1)(L"me", 2)(L"je", 3)(L"ve", 4)(L"sa", 5)(L"di", 6) // fr
|
||||
(L"lu", 0)(L"ma", 1)(L"me", 2)(L"gi", 3)(L"ve", 4)(L"sa", 5)(L"do", 6) // it
|
||||
(L"lu", 0)(L"ma", 1)(L"mi", 2)(L"ju", 3)(L"vie", 4)(L"sá", 5)(L"do", 6) // sp
|
||||
(L"週一", 0)(L"週二", 1)(L"週三", 2)(L"週四", 3)(L"週五", 4)(L"週六", 5)(L"週日", 6) // ch traditional
|
||||
(L"senin", 0)(L"selasa", 1)(L"rabu", 2)(L"kamis", 3)(L"jum'at", 4)(L"sabtu", 5)(L"minggu", 6) // indonesian
|
||||
|
||||
(L"wd", 2)
|
||||
|
||||
;
|
||||
}
|
||||
} wdays;
|
||||
|
||||
struct month_ : qi::symbols<wchar_t, unsigned>
|
||||
{
|
||||
month_()
|
||||
{
|
||||
add
|
||||
(L"jan", 1)(L"feb", 2)(L"mar", 3)(L"apr", 4)(L"may", 5)(L"jun", 6)
|
||||
(L"jul", 7)(L"aug", 8)(L"sep", 9)(L"oct", 10)(L"nov", 11)(L"dec", 12)
|
||||
;
|
||||
}
|
||||
} month;
|
||||
|
||||
struct hours_ : qi::symbols<char, uint8_t>
|
||||
{
|
||||
hours_()
|
||||
{
|
||||
add
|
||||
( "0", 0)( "1", 1)( "2", 2)( "3", 3)( "4", 4)( "5", 5)( "6", 6)( "7", 7)( "8", 8)( "9", 9) /* not standard */
|
||||
("00", 0)("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
|
||||
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
|
||||
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)
|
||||
;
|
||||
}
|
||||
} hours;
|
||||
|
||||
struct exthours_ : qi::symbols<char, uint8_t>
|
||||
{
|
||||
exthours_()
|
||||
{
|
||||
add
|
||||
( "0", 0)( "1", 1)( "2", 2)( "3", 3)( "4", 4)( "5", 5)( "6", 6)( "7", 7)( "8", 8)( "9", 9) /* not standard */
|
||||
("00", 0)("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
|
||||
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
|
||||
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)("25", 25)("26", 26)("27", 27)("28", 28)("29", 29)
|
||||
("30", 30)("31", 31)("32", 32)("33", 33)("34", 34)("35", 35)("36", 36)("37", 37)("38", 38)("39", 39)
|
||||
("40", 40)("41", 41)("42", 42)("43", 43)("44", 44)("45", 45)("46", 46)("47", 47)("48", 48)
|
||||
;
|
||||
}
|
||||
} exthours;
|
||||
|
||||
struct minutes_ : qi::symbols<char, uint8_t>
|
||||
{
|
||||
minutes_()
|
||||
{
|
||||
add
|
||||
( "0", 0)( "1", 1)( "2", 2)( "3", 3)( "4", 4)( "5", 5)( "6", 6)( "7", 7)( "8", 8)( "9", 9) /* not standard */
|
||||
("00", 0)("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
|
||||
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
|
||||
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)("25", 25)("26", 26)("27", 27)("28", 28)("29", 29)
|
||||
("30", 30)("31", 31)("32", 32)("33", 33)("34", 34)("35", 35)("36", 36)("37", 37)("38", 38)("39", 39)
|
||||
("40", 40)("41", 41)("42", 42)("43", 43)("44", 44)("45", 45)("46", 46)("47", 47)("48", 48)("49", 49)
|
||||
("50", 50)("51", 51)("52", 52)("53", 53)("54", 54)("55", 55)("56", 56)("57", 57)("58", 58)("59", 59)
|
||||
;
|
||||
}
|
||||
} minutes;
|
||||
|
||||
struct weeknum_ : qi::symbols<char, unsigned>
|
||||
{
|
||||
weeknum_()
|
||||
{
|
||||
add ( "1", 1)( "2", 2)( "3", 3)( "4", 4)( "5", 5)( "6", 6)( "7", 7)( "8", 8)( "9", 9)
|
||||
("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
|
||||
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
|
||||
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)("25", 25)("26", 26)("27", 27)("28", 28)("29", 29)
|
||||
("30", 30)("31", 31)("32", 32)("33", 33)("34", 34)("35", 35)("36", 36)("37", 37)("38", 38)("39", 39)
|
||||
("40", 40)("41", 41)("42", 42)("43", 43)("44", 44)("45", 45)("46", 46)("47", 47)("48", 48)("49", 49)
|
||||
("50", 50)("51", 51)("52", 52)("53", 53)
|
||||
;
|
||||
}
|
||||
} weeknum;
|
||||
|
||||
struct daynum_ : qi::symbols<char, unsigned>
|
||||
{
|
||||
daynum_()
|
||||
{
|
||||
add ("1", 1)("2", 2)("3", 3)("4", 4)("5", 5)("6", 6)("7", 7)("8", 8)("9", 9)
|
||||
("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
|
||||
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
|
||||
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)("25", 25)("26", 26)("27", 27)("28", 28)("29", 29)
|
||||
("30", 30)("31", 31)
|
||||
;
|
||||
}
|
||||
} daynum;
|
||||
|
||||
template <class Iterator>
|
||||
class year_selector_parser : public qi::grammar<Iterator, space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, space_type> year;
|
||||
qi::rule<Iterator, space_type> year_range;
|
||||
qi::rule<Iterator, space_type> main;
|
||||
public:
|
||||
year_selector_parser() : year_selector_parser::base_type(main)
|
||||
{
|
||||
using qi::uint_;
|
||||
using qi::lit;
|
||||
using charset::char_;
|
||||
|
||||
static const qi::int_parser<unsigned, 10, 4, 4> _4digit = {};
|
||||
|
||||
year %= _4digit;
|
||||
year_range %= (year >> dash >> year >> '/' >> uint_)
|
||||
| (year >> dash >> year)
|
||||
| year >> char_('+')
|
||||
| year
|
||||
;
|
||||
main %= year_range % ',';
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class week_selector_parser : public qi::grammar<Iterator, space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, space_type> week;
|
||||
qi::rule<Iterator, space_type> year_range;
|
||||
qi::rule<Iterator, space_type> main;
|
||||
public:
|
||||
week_selector_parser() : week_selector_parser::base_type(main)
|
||||
{
|
||||
using qi::uint_;
|
||||
using qi::lit;
|
||||
using charset::char_;
|
||||
|
||||
week %= (weeknum >> dash >> weeknum >> '/' >> uint_)
|
||||
| (weeknum >> dash >> weeknum)
|
||||
| weeknum
|
||||
;
|
||||
|
||||
main %= charset::no_case[lit("week")] >> week % ',';
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class month_selector_parser : public qi::grammar<Iterator, space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, space_type> date;
|
||||
qi::rule<Iterator, space_type> day_offset;
|
||||
qi::rule<Iterator, space_type> date_with_offsets;
|
||||
qi::rule<Iterator, space_type> monthday_range;
|
||||
qi::rule<Iterator, space_type> month_range;
|
||||
qi::rule<Iterator, space_type> main;
|
||||
public:
|
||||
month_selector_parser() : month_selector_parser::base_type(main)
|
||||
{
|
||||
using qi::int_;
|
||||
using qi::lit;
|
||||
using qi::double_;
|
||||
using qi::lexeme;
|
||||
using charset::char_;
|
||||
|
||||
static const qi::int_parser<unsigned, 10, 4, 4> year = {};
|
||||
|
||||
day_offset %= (char_('+') | char_('-')) >> int_ >> charset::no_case[(lit("days") | lit("day"))];
|
||||
|
||||
date %= charset::no_case[(-year >> month >> daynum)]
|
||||
| (-year >> charset::no_case[lit("easter")])
|
||||
| daynum >> !(lit(':') >> qi::digit)
|
||||
;
|
||||
|
||||
date_with_offsets %= date >> -((char_('+') | char_('-')) >> charset::no_case[wdays] >> qi::no_skip[qi::space]) >> -day_offset;
|
||||
|
||||
monthday_range %= (date_with_offsets >> dash >> date_with_offsets)
|
||||
| (date_with_offsets >> '+')
|
||||
| date_with_offsets
|
||||
| charset::no_case[(-year >> month >> dash >> month >> '/' >> int_)]
|
||||
| charset::no_case[(-year >> month >> dash >> month)]
|
||||
| charset::no_case[(-year >> month)]
|
||||
;
|
||||
|
||||
month_range %= charset::no_case[(month >> dash >> month)]
|
||||
| charset::no_case[month]
|
||||
;
|
||||
|
||||
main %= (monthday_range % ',') | (month_range % ',');
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(month_range);
|
||||
BOOST_SPIRIT_DEBUG_NODE(monthday_range);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date_with_offsets);
|
||||
BOOST_SPIRIT_DEBUG_NODE(date);
|
||||
BOOST_SPIRIT_DEBUG_NODE(day_offset);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Iterator>
|
||||
class weekday_selector_parser : public qi::grammar<Iterator, std::vector<osmoh::Weekdays>(), space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, uint8_t(), space_type> nth;
|
||||
qi::rule<Iterator, uint16_t(), space_type> nth_entry;
|
||||
qi::rule<Iterator, int32_t(), space_type, qi::locals<int8_t>> day_offset;
|
||||
qi::rule<Iterator, space_type> holyday;
|
||||
qi::rule<Iterator, space_type> holiday_sequence;
|
||||
qi::rule<Iterator, osmoh::Weekdays(), space_type> weekday_range;
|
||||
qi::rule<Iterator, std::vector<osmoh::Weekdays>(), space_type> weekday_sequence;
|
||||
qi::rule<Iterator, std::vector<osmoh::Weekdays>(), space_type> main;
|
||||
public:
|
||||
weekday_selector_parser() : weekday_selector_parser::base_type(main)
|
||||
{
|
||||
using qi::_a;
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_val;
|
||||
using qi::lit;
|
||||
using qi::ushort_;
|
||||
using boost::phoenix::at_c;
|
||||
|
||||
nth %= ushort_(1) | ushort_(2) | ushort_(3) | ushort_(4) | ushort_(5);
|
||||
|
||||
nth_entry = (nth >> dash >> nth) [_val |= ((2 << ((_2-1)-(_1-1))) - 1) << (_1-1)]
|
||||
| (lit('-') >> nth) [_val |= (0x0100 << (_1 - 1))]
|
||||
| nth [_val |= (1 << (_1 - 1))]
|
||||
;
|
||||
|
||||
day_offset = (lit('+')[_a = 1] | lit('-') [_a = -1]) >> ushort_[_val = _1*_a] >> charset::no_case[(lit(L"days") | lit(L"day"))];
|
||||
holyday %= (charset::no_case[lit(L"SH")] >> -day_offset) | charset::no_case[lit(L"PH")];
|
||||
holiday_sequence %= holyday % ',';
|
||||
weekday_range = (charset::no_case[wdays][at_c<0>(_val) |= (1<<_1)]
|
||||
>> L'[' >> nth_entry[at_c<1>(_val) |= _1] % L',' >> L']' >> day_offset[at_c<2>(_val) = _1])
|
||||
| (charset::no_case[wdays][at_c<0>(_val) |= (1<<_1)] >> L'[' >> nth_entry[at_c<1>(_val) |= _1] % L',' >> L']')
|
||||
| charset::no_case[(wdays >> dash >> wdays)] [at_c<0>(_val) |= ((2 << ((_2)-(_1))) - 1) << (_1)]
|
||||
| charset::no_case[wdays][at_c<0>(_val) |= (1<<_1)]
|
||||
;
|
||||
|
||||
weekday_sequence %= (weekday_range % L',') >> !qi::no_skip[charset::alpha] >> -lit(L':');
|
||||
|
||||
main = (holiday_sequence >> -lit(L',') >> weekday_sequence[_val = _1])
|
||||
| weekday_sequence[_val = _1] >> -(-lit(L',') >> holiday_sequence)
|
||||
| holiday_sequence
|
||||
;
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(weekday_sequence);
|
||||
BOOST_SPIRIT_DEBUG_NODE(weekday_range);
|
||||
BOOST_SPIRIT_DEBUG_NODE(holiday_sequence);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class time_selector_parser : public qi::grammar<Iterator, std::vector<osmoh::TimeSpan>(), space_type>
|
||||
{
|
||||
protected:
|
||||
qi::rule<Iterator, osmoh::Time(), space_type, qi::locals<uint8_t>> hour_minutes;
|
||||
qi::rule<Iterator, osmoh::Time(), space_type, qi::locals<uint8_t>> extended_hour_minutes;
|
||||
qi::rule<Iterator, osmoh::Time(), space_type> variable_time;
|
||||
qi::rule<Iterator, osmoh::Time(), space_type> extended_time;
|
||||
qi::rule<Iterator, osmoh::Time(), space_type> time;
|
||||
qi::rule<Iterator, osmoh::TimeSpan(), space_type> timespan;
|
||||
qi::rule<Iterator, std::vector<osmoh::TimeSpan>(), space_type> main;
|
||||
|
||||
class validate_timespan_impl
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
struct result { typedef bool type; };
|
||||
|
||||
bool operator() (osmoh::TimeSpan const & ts) const
|
||||
{
|
||||
using boost::posix_time::ptime;
|
||||
using boost::posix_time::time_duration;
|
||||
using boost::posix_time::hours;
|
||||
using boost::posix_time::minutes;
|
||||
using boost::posix_time::time_period;
|
||||
|
||||
bool result = true;
|
||||
if (ts.period.flags)
|
||||
{
|
||||
time_period tp = osmoh::make_time_period(boost::gregorian::day_clock::local_day(), ts);
|
||||
result = (tp.length() >= time_duration(ts.period.hours, ts.period.minutes, 0 /* seconds */));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
time_selector_parser() : time_selector_parser::base_type(main)
|
||||
{
|
||||
using qi::int_;
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_3;
|
||||
using qi::_a;
|
||||
using qi::_val;
|
||||
using qi::lit;
|
||||
using qi::_pass;
|
||||
using charset::char_;
|
||||
using boost::phoenix::at_c;
|
||||
|
||||
phx::function<validate_timespan_impl> const validate_timespan = validate_timespan_impl();
|
||||
|
||||
hour_minutes = hours[at_c<0>(_val) = _1, at_c<2>(_val) |= osmoh::Time::eHours]
|
||||
|| (((lit(':') | lit(":") | lit('.')) >> minutes[at_c<1>(_val) = _1,
|
||||
at_c<2>(_val) |= osmoh::Time::eMinutes])
|
||||
^ charset::no_case[lit('h') | lit("hs") | lit("hrs") | lit("uhr")]
|
||||
^ (charset::no_case[lit("am")][_a = 0] | charset::no_case[lit("pm")][_a = 1])
|
||||
[phx::if_(at_c<0>(_val) <= 12)[at_c<0>(_val) += (12 * _a)]])
|
||||
;
|
||||
|
||||
extended_hour_minutes = exthours[at_c<0>(_val) = _1, at_c<2>(_val) |= osmoh::Time::eHours]
|
||||
|| (((lit(':') | lit(":") | lit('.')) >> minutes[at_c<1>(_val) = _1,
|
||||
at_c<2>(_val) |= osmoh::Time::eMinutes])
|
||||
^ charset::no_case[lit('h') | lit("hs") | lit("hrs") | lit("uhr")]
|
||||
^ (charset::no_case[lit("am")][_a = 0] | charset::no_case[lit("pm")][_a = 1])
|
||||
[phx::if_(at_c<0>(_val) <= 12)[at_c<0>(_val) += (12 * _a)]])
|
||||
;
|
||||
|
||||
variable_time =
|
||||
(lit('(')
|
||||
>> charset::no_case[event][at_c<2>(_val) |= _1]
|
||||
>> (
|
||||
char_('+')[at_c<2>(_val) |= osmoh::Time::ePlus]
|
||||
| char_('-')[at_c<2>(_val) |= osmoh::Time::eMinus]
|
||||
)
|
||||
>> hour_minutes[at_c<2>(_1) |= at_c<2>(_val), _val = _1]
|
||||
>> lit(')')
|
||||
)
|
||||
| charset::no_case[event][at_c<2>(_val) |= _1]
|
||||
;
|
||||
|
||||
extended_time %= extended_hour_minutes | variable_time;
|
||||
|
||||
time %= hour_minutes | variable_time;
|
||||
|
||||
timespan =
|
||||
(time >> dash >> extended_time >> L'/' >> hour_minutes)
|
||||
[at_c<0>(_val) = _1, at_c<1>(_val) = _2, at_c<2>(_val) |= osmoh::Time::eExt,
|
||||
at_c<3>(_val) = _3]
|
||||
| (time >> dash >> extended_time >> L'/' >> minutes)
|
||||
[at_c<0>(_val) = _1, at_c<1>(_val) = _2, at_c<2>(_val) |= osmoh::Time::eExt,
|
||||
at_c<1>(at_c<3>(_val)) = _3, at_c<2>(at_c<3>(_val)) = osmoh::Time::eMinutes]
|
||||
| (time >> dash >> extended_time >> char_(L'+'))
|
||||
[at_c<0>(_val) = _1, at_c<1>(_val) = _2, at_c<2>(_val) |= osmoh::Time::ePlus]
|
||||
| (time >> dash >> extended_time)
|
||||
[at_c<0>(_val) = _1, at_c<1>(_val) = _2]
|
||||
| (time >> char_(L'+'))
|
||||
[at_c<0>(_val) = _1, at_c<2>(_val) |= osmoh::Time::ePlus]
|
||||
| time [at_c<0>(_val) = _1]
|
||||
;
|
||||
|
||||
main %= timespan[_pass = validate_timespan(_1)] % ',';
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(timespan);
|
||||
BOOST_SPIRIT_DEBUG_NODE(time);
|
||||
BOOST_SPIRIT_DEBUG_NODE(extended_time);
|
||||
BOOST_SPIRIT_DEBUG_NODE(variable_time);
|
||||
BOOST_SPIRIT_DEBUG_NODE(extended_hour_minutes);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class selectors_parser : public qi::grammar<Iterator, osmoh::TimeRule(), space_type>
|
||||
{
|
||||
protected:
|
||||
weekday_selector_parser<Iterator> weekday_selector;
|
||||
time_selector_parser<Iterator> time_selector;
|
||||
year_selector_parser<Iterator> year_selector;
|
||||
month_selector_parser<Iterator> month_selector;
|
||||
week_selector_parser<Iterator> week_selector;
|
||||
|
||||
qi::rule<Iterator, std::string(), space_type> comment;
|
||||
qi::rule<Iterator, osmoh::TimeRule(), space_type> small_range_selectors;
|
||||
qi::rule<Iterator, space_type> wide_range_selectors;
|
||||
qi::rule<Iterator, osmoh::TimeRule(), space_type> main;
|
||||
public:
|
||||
selectors_parser() : selectors_parser::base_type(main)
|
||||
{
|
||||
using qi::_1;
|
||||
using qi::_val;
|
||||
using qi::lit;
|
||||
using qi::lexeme;
|
||||
using charset::char_;
|
||||
using boost::phoenix::at_c;
|
||||
using osmoh::State;
|
||||
|
||||
comment %= lexeme['"' >> +(char_ - '"') >> '"'];
|
||||
wide_range_selectors = -year_selector >> -month_selector >> -week_selector >> -lit(':') | (comment >> ':');
|
||||
small_range_selectors = -weekday_selector[at_c<0>(_val) = _1] >> -( lit("24/7") | time_selector[at_c<1>(_val) = _1]);
|
||||
|
||||
main =
|
||||
(
|
||||
lit(L"24/7")
|
||||
| lit(L"24時間営業")
|
||||
| lit(L"7/24")
|
||||
| lit(L"24時間")
|
||||
| charset::no_case[lit(L"daily 24/7")]
|
||||
| charset::no_case[lit(L"24 hours")]
|
||||
| charset::no_case[lit(L"24 horas")]
|
||||
| charset::no_case[lit(L"круглосуточно")]
|
||||
| charset::no_case[lit(L"24 часа")]
|
||||
| charset::no_case[lit(L"24 hrs")]
|
||||
| charset::no_case[lit(L"nonstop")]
|
||||
| charset::no_case[lit(L"24hrs")]
|
||||
| charset::no_case[lit(L"open 24 hours")]
|
||||
| charset::no_case[lit(L"24 stunden")]
|
||||
)[at_c<0>(at_c<2>(_val)) = State::eOpen]
|
||||
| (-wide_range_selectors >> small_range_selectors[_val = _1, at_c<0>(at_c<2>(_val)) = State::eOpen])
|
||||
;
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(small_range_selectors);
|
||||
BOOST_SPIRIT_DEBUG_NODE(wide_range_selectors);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class time_domain_parser : public qi::grammar<Iterator, std::vector<osmoh::TimeRule>(), space_type, qi::locals<qi::rule<Iterator, space_type>*>>
|
||||
{
|
||||
protected:
|
||||
selectors_parser<Iterator> selector_sequence;
|
||||
|
||||
qi::rule<Iterator, std::string(), space_type> comment;
|
||||
qi::rule<Iterator, space_type> separator;
|
||||
qi::rule<Iterator, space_type> base_separator;
|
||||
qi::rule<Iterator, osmoh::TimeRule(), space_type> rule_sequence;
|
||||
qi::rule<Iterator, osmoh::State(), space_type> rule_modifier;
|
||||
qi::rule<Iterator, std::vector<osmoh::TimeRule>(), space_type, qi::locals<qi::rule<Iterator, space_type>*>> main;
|
||||
|
||||
public:
|
||||
time_domain_parser() : time_domain_parser::base_type(main)
|
||||
{
|
||||
using qi::lit;
|
||||
using qi::lexeme;
|
||||
using qi::_1;
|
||||
using qi::_a;
|
||||
using qi::_val;
|
||||
using charset::char_;
|
||||
using boost::phoenix::at_c;
|
||||
using qi::lazy;
|
||||
using qi::eps;
|
||||
using osmoh::State;
|
||||
|
||||
comment %= lexeme['"' >> +(char_ - '"') >> '"'] | lexeme['(' >> +(char_ - ')') >> ')'];
|
||||
base_separator = lit(';') | lit("||");
|
||||
separator = lit(';') | lit("||") | lit(',');
|
||||
|
||||
rule_modifier =
|
||||
(charset::no_case[lit("open")][at_c<0>(_val) = State::eOpen] >> -comment[at_c<1>(_val) = _1])
|
||||
| ((charset::no_case[lit("closed") | lit("off")])[at_c<0>(_val) = State::eClosed] >> -comment[at_c<1>(_val) = _1])
|
||||
| (charset::no_case[lit("unknown")][at_c<0>(_val) = State::eUnknown] >> -comment[at_c<1>(_val) = _1])
|
||||
| comment[at_c<0>(_val) = State::eUnknown, at_c<1>(_val) = _1]
|
||||
;
|
||||
|
||||
rule_sequence = selector_sequence[_val = _1]
|
||||
>> -rule_modifier[at_c<2>(_val) = _1, at_c<3>(_val) = 1];
|
||||
|
||||
main %= -(lit("opening_hours") >> lit('='))
|
||||
>> rule_sequence[_a = phx::val(&base_separator),
|
||||
phx::if_(at_c<3>(_1) || phx::size(at_c<1>(_1)))[_a = phx::val(&separator)]] % lazy(*_a);
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODE(main);
|
||||
BOOST_SPIRIT_DEBUG_NODE(rule_sequence);
|
||||
BOOST_SPIRIT_DEBUG_NODE(rule_modifier);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
bool parse_timerange(Iterator first, Iterator last, std::vector<osmoh::TimeRule> & context)
|
||||
{
|
||||
using qi::double_;
|
||||
using qi::phrase_parse;
|
||||
using charset::space;
|
||||
|
||||
time_domain_parser<Iterator> time_domain;
|
||||
|
||||
bool r = phrase_parse(
|
||||
first, /* start iterator */
|
||||
last, /* end iterator */
|
||||
time_domain, /* the parser */
|
||||
space, /* the skip-parser */
|
||||
context /* result storage */
|
||||
);
|
||||
|
||||
if (first != last) // fail if we did not get a full match
|
||||
return false;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool check_weekday(osmoh::Weekdays const & wd, boost::gregorian::date const & d)
|
||||
{
|
||||
using namespace boost::gregorian;
|
||||
|
||||
bool hit = false;
|
||||
typedef nth_day_of_the_week_in_month nth_dow;
|
||||
if (wd.nth)
|
||||
{
|
||||
for (uint8_t i = 0; (wd.weekdays & (0xFF ^ ((1 << i) - 1))); ++i)
|
||||
{
|
||||
if (!(wd.weekdays & (1 << i)))
|
||||
continue;
|
||||
|
||||
uint8_t a = wd.nth & 0xFF;
|
||||
for (size_t j = 0; (a & (0xFF ^ ((1 << j) - 1))); ++j)
|
||||
{
|
||||
if (a & (1 << j))
|
||||
{
|
||||
nth_dow ndm(nth_dow::week_num(j + 1), nth_dow::day_of_week_type((i + 1 == 7) ? 0 : (i + 1)), d.month());
|
||||
hit |= (d == ndm.get_date(d.year()));
|
||||
}
|
||||
}
|
||||
a = (wd.nth >> 8) & 0xFF;
|
||||
for (size_t j = 0; (a & (0xFF ^ ((1 << j) - 1))); ++j)
|
||||
{
|
||||
if (a & (1 << j))
|
||||
{
|
||||
last_day_of_the_week_in_month lwdm(nth_dow::day_of_week_type((i + 1 == 7) ? 0 : (i + 1)), d.month());
|
||||
hit |= (d == ((lwdm.get_date(d.year()) - weeks(j)) + days(wd.offset)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t i = 0; (wd.weekdays & (0xFF ^ ((1 << i) - 1))); ++i)
|
||||
{
|
||||
if (!(wd.weekdays & (1 << i)))
|
||||
continue;
|
||||
hit |= (d.day_of_week() == ((i + 1 == 7) ? 0 : (i + 1)));
|
||||
}
|
||||
}
|
||||
/* very useful in debug */
|
||||
// std::cout << d.day_of_week() << " " << d << " --> " << wd << (hit ? " hit" : " miss") << std::endl;
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool check_timespan(osmoh::TimeSpan const &ts, boost::gregorian::date const & d, boost::posix_time::ptime const & p)
|
||||
{
|
||||
using boost::gregorian::days;
|
||||
using boost::posix_time::ptime;
|
||||
using boost::posix_time::hours;
|
||||
using boost::posix_time::minutes;
|
||||
using boost::posix_time::time_period;
|
||||
|
||||
time_period tp1 = osmoh::make_time_period(d-days(1), ts);
|
||||
time_period tp2 = osmoh::make_time_period(d, ts);
|
||||
/* very useful in debug */
|
||||
// std::cout << ts << "\t" << tp1 << "(" << p << ")" << (tp1.contains(p) ? " hit" : " miss") << std::endl;
|
||||
// std::cout << ts << "\t" << tp2 << "(" << p << ")" << (tp2.contains(p) ? " hit" : " miss") << std::endl;
|
||||
return tp1.contains(p) || tp2.contains(p);
|
||||
}
|
||||
|
||||
bool check_rule(osmoh::TimeRule const & r, std::tm const & stm, std::ostream * hitcontext = nullptr)
|
||||
{
|
||||
bool next = false;
|
||||
|
||||
// check 24/7
|
||||
if (r.weekdays.empty() && r.timespan.empty() && r.state.state == osmoh::State::eOpen)
|
||||
return true;
|
||||
|
||||
boost::gregorian::date date = boost::gregorian::date_from_tm(stm);
|
||||
boost::posix_time::ptime pt = boost::posix_time::ptime_from_tm(stm);
|
||||
|
||||
next = r.weekdays.empty();
|
||||
for (auto const & wd : r.weekdays)
|
||||
{
|
||||
if (check_weekday(wd, date))
|
||||
{
|
||||
if (hitcontext)
|
||||
*hitcontext << wd << " ";
|
||||
next = true;
|
||||
}
|
||||
}
|
||||
if (!next)
|
||||
return next;
|
||||
|
||||
next = r.timespan.empty();
|
||||
for (auto const & ts : r.timespan)
|
||||
{
|
||||
if (check_timespan(ts, date, pt))
|
||||
{
|
||||
if (hitcontext)
|
||||
*hitcontext << ts << " ";
|
||||
next = true;
|
||||
}
|
||||
}
|
||||
return next && !(r.timespan.empty() && r.weekdays.empty());
|
||||
}
|
||||
|
||||
|
||||
} // anonymouse namespace
|
||||
|
||||
OSMTimeRange::OSMTimeRange(std::string const & rules)
|
||||
: m_sourceString(rules)
|
||||
, m_valid(false)
|
||||
, m_state(osmoh::State::eUnknown)
|
||||
{
|
||||
parse();
|
||||
}
|
||||
|
||||
void OSMTimeRange::parse()
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::wstring src = converter.from_bytes(m_sourceString);
|
||||
m_valid = parse_timerange(src.begin(), src.end(), m_rules);
|
||||
}
|
||||
|
||||
OSMTimeRange & OSMTimeRange::operator () (time_t timestamp)
|
||||
{
|
||||
std::tm stm = *localtime(×tamp);
|
||||
|
||||
osmoh::State::EState true_state[3][3] = {
|
||||
{osmoh::State::eUnknown, osmoh::State::eClosed, osmoh::State::eOpen},
|
||||
{osmoh::State::eClosed , osmoh::State::eClosed, osmoh::State::eOpen},
|
||||
{osmoh::State::eOpen , osmoh::State::eClosed, osmoh::State::eOpen}
|
||||
};
|
||||
|
||||
osmoh::State::EState false_state[3][3] = {
|
||||
{osmoh::State::eUnknown, osmoh::State::eOpen , osmoh::State::eClosed},
|
||||
{osmoh::State::eClosed , osmoh::State::eClosed , osmoh::State::eClosed},
|
||||
{osmoh::State::eOpen , osmoh::State::eOpen , osmoh::State::eOpen}
|
||||
};
|
||||
|
||||
m_state = osmoh::State::eUnknown;
|
||||
m_comment = std::string();
|
||||
|
||||
for (auto const & el : m_rules)
|
||||
{
|
||||
bool hit = false;
|
||||
if ((hit = check_rule(el, stm)))
|
||||
{
|
||||
m_state = true_state[m_state][el.state.state];
|
||||
m_comment = el.state.comment;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = false_state[m_state][el.state.state];
|
||||
}
|
||||
/* very useful in debug */
|
||||
// char const * st[] = {"unknown", "closed", "open"};
|
||||
// std::cout << "-[" << hit << "]-------------------[" << el << "]: " << st[m_state] << "--------------------" << std::endl;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OSMTimeRange & OSMTimeRange::operator () (std::string const & timestr, char const * timefmt)
|
||||
{
|
||||
std::tm when = {};
|
||||
std::stringstream ss(timestr);
|
||||
ss >> std::get_time(&when, timefmt);
|
||||
return this->operator()(std::mktime(&when));
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Mail.Ru Group
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
class Time
|
||||
{
|
||||
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) {}
|
||||
inline Time & Hours(uint8_t h) { hours = h; flags |= eHours; return *this; }
|
||||
inline Time & Minutes(uint8_t m) { minutes = m; flags |= eMinutes; return *this; }
|
||||
inline Time & Sunset() { flags = eSunset; return *this; }
|
||||
inline Time & Sunrise() { flags = eSunrise; return *this; }
|
||||
|
||||
friend std::ostream & operator << (std::ostream & s, Time const & t);
|
||||
};
|
||||
|
||||
class TimeSpan
|
||||
{
|
||||
public:
|
||||
Time from;
|
||||
Time to;
|
||||
uint8_t flags;
|
||||
Time period;
|
||||
|
||||
TimeSpan() : flags(Time::eNone) {}
|
||||
|
||||
friend std::ostream & operator << (std::ostream & s, TimeSpan const & span);
|
||||
};
|
||||
|
||||
class Weekdays
|
||||
{
|
||||
public:
|
||||
uint8_t weekdays;
|
||||
uint16_t nth;
|
||||
int32_t offset;
|
||||
|
||||
Weekdays() : weekdays(0), nth(0), offset(0) {}
|
||||
|
||||
friend std::ostream & operator << (std::ostream & s, Weekdays const & w);
|
||||
};
|
||||
|
||||
class State
|
||||
{
|
||||
public:
|
||||
enum EState {
|
||||
eUnknown = 0,
|
||||
eClosed = 1,
|
||||
eOpen = 2
|
||||
};
|
||||
|
||||
uint8_t state;
|
||||
std::string comment;
|
||||
|
||||
State() : state(eUnknown) {}
|
||||
};
|
||||
|
||||
class TimeRule
|
||||
{
|
||||
public:
|
||||
std::vector<Weekdays> weekdays;
|
||||
std::vector<TimeSpan> timespan;
|
||||
State state;
|
||||
uint8_t int_flags = 0;
|
||||
};
|
||||
} // namespace osmoh
|
||||
|
||||
class OSMTimeRange
|
||||
{
|
||||
std::string m_sourceString;
|
||||
bool m_valid;
|
||||
osmoh::State::EState m_state;
|
||||
std::vector<osmoh::TimeRule> m_rules;
|
||||
std::string m_comment;
|
||||
|
||||
public:
|
||||
OSMTimeRange(std::string const & rules);
|
||||
|
||||
inline bool IsValid() const { return m_valid; }
|
||||
inline bool IsOpen() const { return m_state == osmoh::State::eOpen; }
|
||||
inline bool IsClosed() const { return m_state == osmoh::State::eClosed; }
|
||||
inline bool IsUnknown() const { return m_state == osmoh::State::eUnknown; }
|
||||
inline std::string const & Comment() const { return m_comment; }
|
||||
|
||||
OSMTimeRange & operator()(time_t timestamp);
|
||||
OSMTimeRange & operator()(std::string const & timestr, char const * timefmt="%d-%m-%Y %R");
|
||||
|
||||
private:
|
||||
void parse();
|
||||
};
|
||||
|
98
3party/opening_hours/parse_opening_hours.cpp
Normal file
98
3party/opening_hours/parse_opening_hours.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "parse_opening_hours.hpp"
|
||||
#include "opening_hours_parsers.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Context, typename Iterator>
|
||||
struct context_parser;
|
||||
|
||||
template<typename Iterator> struct context_parser<osmoh::TTimespans, Iterator>
|
||||
{
|
||||
using type = osmoh::parsing::time_selector<Iterator>;
|
||||
};
|
||||
|
||||
template<typename Iterator> struct context_parser<osmoh::Weekdays, Iterator>
|
||||
{
|
||||
using type = osmoh::parsing::weekday_selector<Iterator>;
|
||||
};
|
||||
|
||||
template<typename Iterator> struct context_parser<osmoh::TMonthdayRanges, Iterator>
|
||||
{
|
||||
using type = osmoh::parsing::month_selector<Iterator>;
|
||||
};
|
||||
|
||||
template<typename Iterator> struct context_parser<osmoh::TYearRanges, Iterator>
|
||||
{
|
||||
using type = osmoh::parsing::year_selector<Iterator>;
|
||||
};
|
||||
|
||||
template<typename Iterator> struct context_parser<osmoh::TWeekRanges, Iterator>
|
||||
{
|
||||
using type = osmoh::parsing::week_selector<Iterator>;
|
||||
};
|
||||
|
||||
template<typename Iterator> struct context_parser<osmoh::TRuleSequences, Iterator>
|
||||
{
|
||||
using type = osmoh::parsing::time_domain<Iterator>;
|
||||
};
|
||||
|
||||
|
||||
template <typename Context, typename Iterator>
|
||||
using context_parser_t = typename context_parser<Context, Iterator>::type;
|
||||
|
||||
template <typename Context>
|
||||
bool ParseImp(std::string const & str, Context & context)
|
||||
{
|
||||
using boost::spirit::qi::phrase_parse;
|
||||
using boost::spirit::standard_wide::space;
|
||||
|
||||
context_parser_t<Context, decltype(begin(str))> parser;
|
||||
#ifndef NDEBUG
|
||||
boost::spirit::qi::what(parser);
|
||||
#endif
|
||||
|
||||
auto first = begin(str);
|
||||
auto const last = end(str);
|
||||
auto parsed = phrase_parse(first, last, parser,
|
||||
space, context);
|
||||
|
||||
if (!parsed || first != last)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
bool Parse(std::string const & str, TTimespans & s)
|
||||
{
|
||||
return ParseImp(str, s);
|
||||
}
|
||||
|
||||
bool Parse(std::string const & str, Weekdays & w)
|
||||
{
|
||||
return ParseImp(str, w);
|
||||
}
|
||||
|
||||
bool Parse(std::string const & str, TMonthdayRanges & m)
|
||||
{
|
||||
return ParseImp(str, m);
|
||||
}
|
||||
|
||||
bool Parse(std::string const & str, TYearRanges & y)
|
||||
{
|
||||
return ParseImp(str, y);
|
||||
}
|
||||
|
||||
bool Parse(std::string const & str, TWeekRanges & w)
|
||||
{
|
||||
return ParseImp(str, w);
|
||||
}
|
||||
|
||||
bool Parse(std::string const & str, TRuleSequences & r)
|
||||
{
|
||||
return ParseImp(str, r);
|
||||
}
|
||||
} // namespace osmoh
|
14
3party/opening_hours/parse_opening_hours.hpp
Normal file
14
3party/opening_hours/parse_opening_hours.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "opening_hours.hpp"
|
||||
#include <string>
|
||||
|
||||
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 &);
|
||||
bool Parse(std::string const &, TWeekRanges &);
|
||||
bool Parse(std::string const &, TRuleSequences &);
|
||||
} // namespace osmoh
|
293
3party/opening_hours/rules_evaluation.cpp
Normal file
293
3party/opening_hours/rules_evaluation.cpp
Normal file
|
@ -0,0 +1,293 @@
|
|||
#include "rules_evaluation.hpp"
|
||||
#include "rules_evaluation_private.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
|
||||
namespace
|
||||
{
|
||||
using THourMinutes = std::tuple<int, int>;
|
||||
|
||||
constexpr osmoh::MonthDay::TYear kTMYearOrigin = 1900;
|
||||
|
||||
inline bool ToHourMinutes(osmoh::Time const & t, THourMinutes & hm)
|
||||
{
|
||||
if (!t.IsHoursMinutes())
|
||||
return false;
|
||||
hm = THourMinutes{t.GetHoursCount(), t.GetMinutesCount()};
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ToHourMinutes(std::tm const & t, THourMinutes & hm)
|
||||
{
|
||||
hm = THourMinutes{t.tm_hour, t.tm_min};
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int CompareMonthDayTimeTuple(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
{
|
||||
if (monthDay.HasYear())
|
||||
{
|
||||
if (monthDay.GetYear() != date.tm_year + kTMYearOrigin)
|
||||
return monthDay.GetYear() != date.tm_year + kTMYearOrigin;
|
||||
}
|
||||
|
||||
if (monthDay.HasMonth())
|
||||
{
|
||||
if (monthDay.GetMonth() != osmoh::ToMonth(date.tm_mon + 1))
|
||||
return static_cast<int>(monthDay.GetMonth()) - (date.tm_mon + 1);
|
||||
}
|
||||
|
||||
if (monthDay.HasDayNum())
|
||||
{
|
||||
if (monthDay.GetDayNum() != date.tm_mday)
|
||||
return monthDay.GetDayNum() - date.tm_mday;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator<=(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
{
|
||||
return CompareMonthDayTimeTuple(monthDay, date) < 1;
|
||||
}
|
||||
|
||||
inline bool operator<=(std::tm const & date, osmoh::MonthDay const & monthDay)
|
||||
{
|
||||
return CompareMonthDayTimeTuple(monthDay, date) > -1;
|
||||
}
|
||||
|
||||
inline bool operator==(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
{
|
||||
return CompareMonthDayTimeTuple(monthDay, date) == 0;
|
||||
}
|
||||
|
||||
// Fill result with fields that present in start and missing in end.
|
||||
inline osmoh::MonthDay NormalizeEnd(osmoh::MonthDay const & start, osmoh::MonthDay const & end)
|
||||
{
|
||||
osmoh::MonthDay result = start;
|
||||
if (end.HasYear())
|
||||
result.SetYear(end.GetYear());
|
||||
if (end.HasMonth())
|
||||
result.SetMonth(end.GetMonth());
|
||||
if (end.HasDayNum())
|
||||
result.SetDayNum(end.GetDayNum());
|
||||
return result;
|
||||
}
|
||||
|
||||
inline uint8_t GetWeekNumber(std::tm const & date)
|
||||
{
|
||||
char buff[4]{};
|
||||
if (strftime(&buff[0], sizeof(buff), "%V", &date) == 0)
|
||||
return 0;
|
||||
|
||||
uint32_t weekNumber;
|
||||
std::stringstream sstr(buff);
|
||||
sstr >> weekNumber;
|
||||
return weekNumber;
|
||||
}
|
||||
|
||||
inline bool IsBetweenLooped(osmoh::Weekday const start,
|
||||
osmoh::Weekday const end,
|
||||
osmoh::Weekday const p)
|
||||
{
|
||||
if (start <= end)
|
||||
return start <= p && p <= end;
|
||||
return p >= end || start <= p;
|
||||
}
|
||||
|
||||
inline osmoh::RuleState ModifierToRuleState(osmoh::RuleSequence::Modifier const modifier)
|
||||
{
|
||||
using Modifier = osmoh::RuleSequence::Modifier;
|
||||
|
||||
switch(modifier)
|
||||
{
|
||||
case Modifier::DefaultOpen:
|
||||
case Modifier::Open:
|
||||
return osmoh::RuleState::Open;
|
||||
|
||||
case Modifier::Closed:
|
||||
return osmoh::RuleState::Closed;
|
||||
|
||||
case Modifier::Unknown:
|
||||
case Modifier::Comment:
|
||||
return osmoh::RuleState::Unknown;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
bool IsActive(Timespan const & span, std::tm const & time)
|
||||
{
|
||||
if (span.HasStart() && span.HasEnd())
|
||||
{
|
||||
THourMinutes start;
|
||||
THourMinutes end;
|
||||
THourMinutes toBeChecked;
|
||||
|
||||
if (!ToHourMinutes(span.GetStart(), start))
|
||||
return false;
|
||||
|
||||
if (!ToHourMinutes(span.GetEnd(), end))
|
||||
return false;
|
||||
|
||||
if (!ToHourMinutes(time, toBeChecked))
|
||||
return false;
|
||||
|
||||
// TODO(mgsergio): We don't handle extended hours yet.
|
||||
// Extended hours handling could be implemented through
|
||||
// splitting rule with extended hours into separated rules.
|
||||
// See https://trello.com/c/Efsvs6PP/23-opening-hours-extended-hours
|
||||
if (end <= start || end > THourMinutes{24, 00})
|
||||
// It's better to say we are open, cause
|
||||
// in search result page only `closed' lables are shown.
|
||||
// So from user's perspective `unknown' and `open'
|
||||
// mean same as `not closed'.
|
||||
return true;
|
||||
|
||||
return start <= toBeChecked && toBeChecked <= end;
|
||||
}
|
||||
else if (span.HasStart() && span.HasPlus())
|
||||
{
|
||||
// TODO(mgsergio): Not implemented yet
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsActive(WeekdayRange const & range, std::tm const & date)
|
||||
{
|
||||
if (range.IsEmpty())
|
||||
return false;
|
||||
|
||||
auto const wday = ToWeekday(date.tm_wday + 1);
|
||||
if (wday == Weekday::None)
|
||||
return false;
|
||||
|
||||
if (range.HasEnd())
|
||||
return IsBetweenLooped(range.GetStart(), range.GetEnd(), wday);
|
||||
|
||||
return range.GetStart() == wday;
|
||||
}
|
||||
|
||||
bool IsActive(Holiday const & holiday, std::tm const & date)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsActive(Weekdays const & weekdays, std::tm const & date)
|
||||
{
|
||||
for (auto const & wr : weekdays.GetWeekdayRanges())
|
||||
if (IsActive(wr, date))
|
||||
return true;
|
||||
|
||||
for (auto const & hd : weekdays.GetHolidays())
|
||||
if (IsActive(hd, date))
|
||||
return true;
|
||||
|
||||
return
|
||||
weekdays.GetWeekdayRanges().empty() &&
|
||||
weekdays.GetHolidays().empty();
|
||||
}
|
||||
|
||||
bool IsActive(MonthdayRange const & range, std::tm const & date)
|
||||
{
|
||||
if (range.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (range.HasEnd())
|
||||
return
|
||||
range.GetStart() <= date &&
|
||||
date <= NormalizeEnd(range.GetStart(), range.GetEnd());
|
||||
|
||||
return range.GetStart() == date;
|
||||
}
|
||||
|
||||
bool IsActive(YearRange const & range, std::tm const & date)
|
||||
{
|
||||
if (range.IsEmpty())
|
||||
return false;
|
||||
|
||||
auto const year = date.tm_year + kTMYearOrigin;
|
||||
|
||||
if (range.HasEnd())
|
||||
return range.GetStart() <= year && year <= range.GetEnd();
|
||||
|
||||
return range.GetStart() == year;
|
||||
}
|
||||
|
||||
bool IsActive(WeekRange const & range, std::tm const & date)
|
||||
{
|
||||
if (range.IsEmpty())
|
||||
return false;
|
||||
|
||||
auto const weekNumber = GetWeekNumber(date);
|
||||
|
||||
if (range.HasEnd())
|
||||
return range.GetStart() <= weekNumber && weekNumber <= range.GetEnd();
|
||||
|
||||
return range.GetStart() == weekNumber;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool IsActiveAny(std::vector<T> const & selectors, std::tm const & date)
|
||||
{
|
||||
for (auto const & selector : selectors)
|
||||
{
|
||||
if (IsActive(selector, date))
|
||||
return true;
|
||||
}
|
||||
|
||||
return selectors.empty();
|
||||
}
|
||||
|
||||
bool IsActive(RuleSequence const & rule, std::tm const & date)
|
||||
{
|
||||
if (rule.IsTwentyFourHours())
|
||||
return true;
|
||||
|
||||
return
|
||||
IsActiveAny(rule.GetYears(), date) &&
|
||||
IsActiveAny(rule.GetMonths(), date) &&
|
||||
IsActiveAny(rule.GetWeeks(), date) &&
|
||||
IsActive(rule.GetWeekdays(), date) &&
|
||||
IsActiveAny(rule.GetTimes(), date);
|
||||
}
|
||||
|
||||
RuleState GetState(TRuleSequences const & rules, std::tm const & date)
|
||||
{
|
||||
auto emptyRuleIt = rules.rend();
|
||||
for (auto it = rules.rbegin(); it != rules.rend(); ++it)
|
||||
{
|
||||
if (IsActive(*it, date))
|
||||
{
|
||||
if (it->IsEmpty() && emptyRuleIt == rules.rend())
|
||||
emptyRuleIt = it;
|
||||
else
|
||||
return ModifierToRuleState(it->GetModifier());
|
||||
}
|
||||
}
|
||||
|
||||
if (emptyRuleIt != rules.rend())
|
||||
{
|
||||
if (emptyRuleIt->HasComment())
|
||||
return RuleState::Unknown;
|
||||
else
|
||||
return ModifierToRuleState(emptyRuleIt->GetModifier());
|
||||
}
|
||||
|
||||
return (rules.empty()
|
||||
? RuleState::Unknown
|
||||
: RuleState::Closed);
|
||||
}
|
||||
|
||||
RuleState GetState(TRuleSequences const & rules, time_t const dateTime)
|
||||
{
|
||||
std::tm tm{};
|
||||
localtime_r(&dateTime, &tm);
|
||||
return GetState(rules, tm);
|
||||
}
|
||||
} // namespace osmoh
|
32
3party/opening_hours/rules_evaluation.hpp
Normal file
32
3party/opening_hours/rules_evaluation.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include "opening_hours.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
enum class RuleState
|
||||
{
|
||||
Open,
|
||||
Closed,
|
||||
Unknown
|
||||
};
|
||||
RuleState GetState(TRuleSequences const & rules, std::tm const & date);
|
||||
RuleState GetState(TRuleSequences const & rules, time_t const dateTime);
|
||||
|
||||
inline bool IsOpen(TRuleSequences const & rules, time_t const dateTime)
|
||||
{
|
||||
return GetState(rules, dateTime) == RuleState::Open;
|
||||
}
|
||||
|
||||
inline bool IsClosed(TRuleSequences const & rules, time_t const dateTime)
|
||||
{
|
||||
return GetState(rules, dateTime) == RuleState::Closed;
|
||||
}
|
||||
|
||||
inline bool IsUnknown(TRuleSequences const & rules, time_t const dateTime)
|
||||
{
|
||||
return GetState(rules, dateTime) == RuleState::Unknown;
|
||||
}
|
||||
} // namespace osmoh
|
15
3party/opening_hours/rules_evaluation_private.hpp
Normal file
15
3party/opening_hours/rules_evaluation_private.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include "opening_hours.hpp"
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
bool IsActive(Timespan const & spsn, std::tm const & date);
|
||||
bool IsActive(WeekdayRange const & range, std::tm const & date);
|
||||
bool IsActive(Holiday const & holiday, std::tm const & date);
|
||||
bool IsActive(Weekdays const & weekdays, std::tm const & date);
|
||||
bool IsActive(MonthdayRange const & range, std::tm const & date);
|
||||
bool IsActive(YearRange const & range, std::tm const & date);
|
||||
bool IsActive(WeekRange const & range, std::tm const & date);
|
||||
bool IsActive(RuleSequence const & rule, std::tm const & date);
|
||||
} // namespace osmoh
|
|
@ -5,18 +5,12 @@ TEMPLATE = app
|
|||
|
||||
ROOT_DIR = ../..
|
||||
DEPENDENCIES = indexer platform geometry coding base protobuf tomcrypt
|
||||
!linux {
|
||||
DEPENDENCIES += opening_hours
|
||||
}
|
||||
|
||||
include($$ROOT_DIR/common.pri)
|
||||
|
||||
QT *= core
|
||||
|
||||
!linux {
|
||||
SOURCES += opening_hours_test.cpp
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
test_mwm_set.hpp \
|
||||
test_polylines.hpp \
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
#include "../../testing/testing.hpp"
|
||||
|
||||
#include "../../3party/opening_hours/osm_time_range.hpp"
|
||||
|
||||
UNIT_TEST(OpeningHours_Parse)
|
||||
{
|
||||
{
|
||||
OSMTimeRange oh("06:00-09:00/03");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("06:00-07:00/03");
|
||||
TEST(oh.IsValid() == false, ());
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("sunrise-sunset");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Su-Th sunset-24:00, 04:00-sunrise; Fr-Sa sunset-sunrise");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Apr-Sep Su [1,3] 14:30-17:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("06:00+");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("06:00-07:00+");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("24/7");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("06:13-15:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Mo-Su 08:00-23:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("(sunrise+02:00)-(sunset-04:12)");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Mo-Sa; PH off");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Jan-Mar 07:00-19:00;Apr-Sep 07:00-22:00;Oct-Dec 07:00-19:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Mo closed");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("06:00-23:00 open \"Dining in\"");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("06:00-23:00 open \"Dining in\" || 00:00-24:00 open \"Drive-through\"");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Tu-Th 20:00-03:00 open \"Club and bar\"; Fr-Sa 20:00-04:00 open \"Club and bar\" || Su-Mo 18:00-02:00 open \"bar\" || Tu-Th 18:00-03:00 open \"bar\" || Fr-Sa 18:00-04:00 open \"bar\"");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("09:00-21:00 \"call us\"");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("10:00-13:30,17:00-20:30");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Apr-Sep: Mo-Fr 09:00-13:00,14:00-18:00; Apr-Sep: Sa 10:00-13:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Mo,We,Th,Fr 12:00-18:00; Sa-Su 12:00-17:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Su-Th 11:00-03:00, Fr-Sa 11:00-05:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Mo-We 17:00-01:00, Th,Fr 15:00-01:00; PH off");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
/* test disabled because we go out from DSL definition in some cases */
|
||||
// OSMTimeRange oh("Tu-Su, Ph 10:00-18:00");
|
||||
// TEST(oh.IsValid() == false, ("Broken parser"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Tu-Su 10:00-18:00, Mo 12:00-17:00");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("06:00-07:00/21:03");
|
||||
TEST(oh.IsValid() == false, ("Period can't be large then interval"));
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("sunset-sunrise");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(OpeningHours_TimeHit)
|
||||
{
|
||||
{
|
||||
OSMTimeRange oh("06:13-15:00; 16:30+");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("12-12-2013 7:00").IsOpen(), ());
|
||||
TEST(oh("12-12-2013 16:00").IsClosed(), ());
|
||||
TEST(oh("12-12-2013 20:00").IsOpen(), ());
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("We-Sa; Mo[1,3] closed; Su[-1,-2] closed; Fr[2] open; Fr[-2], Fr open; Su[-2] -2 days");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("20-03-2015 18:00").IsOpen(), ());
|
||||
TEST(oh("17-03-2015 18:00").IsClosed(), ());
|
||||
}
|
||||
|
||||
{
|
||||
OSMTimeRange oh("We-Fr; Mo[1,3] closed; Su[-1,-2] closed");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("20-03-2015 18:00").IsOpen(), ());
|
||||
TEST(oh("17-03-2015 18:00").IsClosed(), ());
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("We-Fr; Mo[1,3] +1 day closed; Su[-1,-2] -3 days closed");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("20-03-2015 18:00").IsOpen(), ());
|
||||
TEST(oh("17-03-2015 18:00").IsClosed(), ());
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Mo-Su 14:30-17:00; Mo[1] closed; Su[-1] closed");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("09-03-2015 16:00").IsOpen(), ());
|
||||
TEST(oh("02-03-2015 16:00").IsClosed(), ());
|
||||
TEST(oh("22-03-2015 16:00").IsOpen(), ());
|
||||
TEST(oh("29-03-2015 16:00").IsClosed(), ());
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("PH,Tu-Su 10:00-18:00; Sa[1] 10:00-18:00 open \"Eintritt ins gesamte Haus frei\"; Jan 1,Dec 24,Dec 25,easter -2 days: closed");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("03-03-2015 16:00").IsOpen(), ());
|
||||
TEST(oh.Comment().empty(), ());
|
||||
TEST(oh("07-03-2015 16:00").IsOpen(), ());
|
||||
TEST(oh.Comment().empty() == false, ());
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("Mo-Su 11:00+; Mo [1,3] off");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("04-03-2015 16:00").IsOpen(), ());
|
||||
TEST(oh("09-03-2015 16:00").IsOpen(), ());
|
||||
TEST(oh("02-03-2015 16:00").IsClosed(), ());
|
||||
TEST(oh("16-03-2015 16:00").IsClosed(), ());
|
||||
}
|
||||
{
|
||||
OSMTimeRange oh("08:00-16:00 open, 16:00-03:00 open \"public room\"");
|
||||
TEST(oh.IsValid(), ("Incorrect schedule string"));
|
||||
TEST(oh("01-03-2015 20:00").IsOpen(), ());
|
||||
TEST(oh("01-03-2015 20:00").Comment() == "public room", ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9,9 +9,7 @@ ROOT_DIR = ../..
|
|||
DEPENDENCIES = map render gui routing search storage graphics indexer platform anim geometry coding base \
|
||||
freetype fribidi expat protobuf tomcrypt jansson osrm stats_client minizip succinct
|
||||
|
||||
!linux* {
|
||||
DEPENDENCIES *= opening_hours
|
||||
}
|
||||
DEPENDENCIES *= opening_hours
|
||||
|
||||
drape {
|
||||
DEPENDENCIES *= drape_frontend drape
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "3party/opening_hours/osm_time_range.hpp"
|
||||
#include "3party/opening_hours/opening_hours.hpp"
|
||||
|
||||
#include "std/chrono.hpp"
|
||||
|
||||
|
@ -31,11 +31,23 @@ inline string DebugPrint(EPlaceState state)
|
|||
|
||||
inline EPlaceState PlaceStateCheck(string const & openingHours, time_t timestamp)
|
||||
{
|
||||
OSMTimeRange oh(openingHours);
|
||||
osmoh::OpeningHours oh(openingHours);
|
||||
|
||||
auto future = system_clock::from_time_t(timestamp);
|
||||
future += minutes(15);
|
||||
size_t nowState = oh(timestamp).IsOpen() ? 0 : 1;
|
||||
size_t futureState = oh(system_clock::to_time_t(future)).IsOpen() ? 0 : 1;
|
||||
|
||||
enum {OPEN = 0, CLOSED = 1};
|
||||
|
||||
size_t nowState = OPEN;
|
||||
size_t futureState = OPEN;
|
||||
|
||||
// TODO(mgsergio): Switch to three-stated model instead of two-staed
|
||||
// I.e. set unknown if we can't parse or can't answer whether it's open.
|
||||
if (oh.IsValid())
|
||||
{
|
||||
nowState = oh.IsOpen(timestamp) ? OPEN : CLOSED;
|
||||
futureState = oh.IsOpen(system_clock::to_time_t(future)) ? OPEN : CLOSED;
|
||||
}
|
||||
|
||||
EPlaceState state[2][2] = {{EPlaceState::Open, EPlaceState::CloseSoon},
|
||||
{EPlaceState::OpenSoon, EPlaceState::Closed}};
|
||||
|
|
|
@ -4,10 +4,7 @@ DEPENDENCIES = map render gui routing search storage indexer graphics platform a
|
|||
freetype expat fribidi tomcrypt jansson protobuf osrm stats_client minizip succinct
|
||||
|
||||
|
||||
!linux* {
|
||||
DEPENDENCIES += opening_hours \
|
||||
|
||||
}
|
||||
DEPENDENCIES += opening_hours \
|
||||
|
||||
drape {
|
||||
DEPENDENCIES *= drape_frontend drape
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# This subproject implements integration tests.
|
||||
# This subproject implements integration tests.
|
||||
# This tests are launched on the whole world dataset.
|
||||
|
||||
# It is recommended to place tests here in the following cases:
|
||||
|
@ -13,10 +13,7 @@ TEMPLATE = app
|
|||
ROOT_DIR = ../..
|
||||
DEPENDENCIES = map routing search storage indexer platform geometry coding base osrm jansson protobuf tomcrypt succinct stats_client
|
||||
|
||||
# this dependency is not built on Linux
|
||||
!linux* {
|
||||
DEPENDENCIES += opening_hours
|
||||
}
|
||||
DEPENDENCIES += opening_hours
|
||||
|
||||
macx-*: LIBS *= "-framework IOKit" "-framework SystemConfiguration"
|
||||
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
#include "base/string_utils.hpp"
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#ifndef OMIM_OS_LINUX
|
||||
// Lib opening_hours is not built for Linux since stdlib doesn't have required functions.
|
||||
#include "3party/opening_hours/osm_time_range.hpp"
|
||||
#endif
|
||||
#include "3party/opening_hours/opening_hours.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
|
@ -37,12 +34,18 @@ void ProcessMetadata(FeatureType const & ft, Result::Metadata & meta)
|
|||
|
||||
meta.m_cuisine = src.Get(feature::Metadata::FMD_CUISINE);
|
||||
|
||||
#ifndef OMIM_OS_LINUX
|
||||
// Lib opening_hours is not built for Linux since stdlib doesn't have required functions.
|
||||
string const openHours = src.Get(feature::Metadata::FMD_OPEN_HOURS);
|
||||
if (!openHours.empty())
|
||||
meta.m_isClosed = OSMTimeRange(openHours)(time(nullptr)).IsClosed();
|
||||
#endif
|
||||
{
|
||||
osmoh::OpeningHours oh(openHours);
|
||||
|
||||
// TODO(mgsergio): Switch to three-stated model instead of two-staed
|
||||
// I.e. set unknown if we can't parse or can't answer whether it's open.
|
||||
if (oh.IsValid())
|
||||
meta.m_isClosed = oh.IsClosed(time(nullptr));
|
||||
else
|
||||
meta.m_isClosed = false;
|
||||
}
|
||||
|
||||
meta.m_stars = 0;
|
||||
(void) strings::to_int(src.Get(feature::Metadata::FMD_STARS), meta.m_stars);
|
||||
|
|
|
@ -9,10 +9,8 @@ ROOT_DIR = ../..
|
|||
DEPENDENCIES = generator routing search storage stats_client jansson indexer platform geometry coding base \
|
||||
tess2 protobuf tomcrypt
|
||||
|
||||
!linux* {
|
||||
DEPENDENCIES += opening_hours \
|
||||
DEPENDENCIES += opening_hours \
|
||||
|
||||
}
|
||||
|
||||
include($$ROOT_DIR/common.pri)
|
||||
|
||||
|
|
|
@ -7,10 +7,27 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
670C61FA1AC3517200C38A8C /* osm_time_range.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670C61F71AC3517200C38A8C /* osm_time_range.hpp */; };
|
||||
671C61FF1AE7AF4000076BD0 /* osm_time_range.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670C61F61AC3517200C38A8C /* osm_time_range.cpp */; };
|
||||
671C62011AE7AF4400076BD0 /* osm_time_range.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670C61F61AC3517200C38A8C /* osm_time_range.cpp */; };
|
||||
671C62021AE7AF4800076BD0 /* osm_time_range_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670C61F51AC3517200C38A8C /* osm_time_range_tests.cpp */; };
|
||||
E91738901BECCB5400717F6E /* opening_hours_parsers_terminals.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E91738861BECCB5400717F6E /* opening_hours_parsers_terminals.hpp */; };
|
||||
E91738911BECCB5400717F6E /* opening_hours_parsers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E91738871BECCB5400717F6E /* opening_hours_parsers.hpp */; };
|
||||
E91738921BECCB5400717F6E /* opening_hours.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E91738881BECCB5400717F6E /* opening_hours.cpp */; };
|
||||
E91738931BECCB5400717F6E /* opening_hours.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E91738891BECCB5400717F6E /* opening_hours.hpp */; };
|
||||
E91738941BECCB5400717F6E /* parse_opening_hours.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E917388B1BECCB5400717F6E /* parse_opening_hours.cpp */; };
|
||||
E91738951BECCB5400717F6E /* parse_opening_hours.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E917388C1BECCB5400717F6E /* parse_opening_hours.hpp */; };
|
||||
E91738961BECCB5400717F6E /* rules_evaluation_private.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E917388D1BECCB5400717F6E /* rules_evaluation_private.hpp */; };
|
||||
E91738971BECCB5400717F6E /* rules_evaluation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E917388E1BECCB5400717F6E /* rules_evaluation.cpp */; };
|
||||
E91738981BECCB5400717F6E /* rules_evaluation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E917388F1BECCB5400717F6E /* rules_evaluation.hpp */; };
|
||||
E917389C1BECCC1000717F6E /* libopening_hours.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670C61E71AC3511700C38A8C /* libopening_hours.a */; };
|
||||
E91738AE1BECCFAC00717F6E /* opening_hours_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E91738A81BECCF4800717F6E /* opening_hours_tests.cpp */; };
|
||||
E91738BA1BECD03B00717F6E /* opening_hours_supported_features_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E91738AC1BECCF9C00717F6E /* opening_hours_supported_features_tests.cpp */; };
|
||||
E91738BB1BECD05A00717F6E /* libopening_hours.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670C61E71AC3511700C38A8C /* libopening_hours.a */; };
|
||||
E91738C71BECD09100717F6E /* libopening_hours.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670C61E71AC3511700C38A8C /* libopening_hours.a */; };
|
||||
E91738C81BECD09700717F6E /* opening_hours_integration_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E91738AA1BECCF7A00717F6E /* opening_hours_integration_tests.cpp */; };
|
||||
E91738CA1BECD0E100717F6E /* opening-count.lst in CopyFiles */ = {isa = PBXBuildFile; fileRef = E91738C91BECD0CE00717F6E /* opening-count.lst */; };
|
||||
E91739021BECD54300717F6E /* opening_hours_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E91738A81BECCF4800717F6E /* opening_hours_tests.cpp */; };
|
||||
E91739031BECD55700717F6E /* libopening_hours.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670C61E71AC3511700C38A8C /* libopening_hours.a */; };
|
||||
E917391F1BECD61400717F6E /* opening_hours_integration_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E91738AA1BECCF7A00717F6E /* opening_hours_integration_tests.cpp */; };
|
||||
E91739201BECD61A00717F6E /* libopening_hours.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 670C61E71AC3511700C38A8C /* libopening_hours.a */; };
|
||||
E91739211BECD62E00717F6E /* opening-count.lst in Resources */ = {isa = PBXBuildFile; fileRef = E91738C91BECD0CE00717F6E /* opening-count.lst */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
|
@ -23,15 +40,49 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
E91738B11BECD02B00717F6E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
E91738BE1BECD08500717F6E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 12;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 6;
|
||||
files = (
|
||||
E91738CA1BECD0E100717F6E /* opening-count.lst in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
670C61E71AC3511700C38A8C /* libopening_hours.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libopening_hours.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
670C61F51AC3517200C38A8C /* osm_time_range_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = osm_time_range_tests.cpp; sourceTree = "<group>"; };
|
||||
670C61F61AC3517200C38A8C /* osm_time_range.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = osm_time_range.cpp; sourceTree = "<group>"; };
|
||||
670C61F71AC3517200C38A8C /* osm_time_range.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = osm_time_range.hpp; sourceTree = "<group>"; };
|
||||
670C61FF1AC351AC00C38A8C /* opening_hours_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = opening_hours_test; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
670D05B71B0E0C290013A7AC /* defaults.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = defaults.xcconfig; path = ../defaults.xcconfig; sourceTree = "<group>"; };
|
||||
E91738861BECCB5400717F6E /* opening_hours_parsers_terminals.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = opening_hours_parsers_terminals.hpp; sourceTree = "<group>"; };
|
||||
E91738871BECCB5400717F6E /* opening_hours_parsers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = opening_hours_parsers.hpp; sourceTree = "<group>"; };
|
||||
E91738881BECCB5400717F6E /* opening_hours.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opening_hours.cpp; sourceTree = "<group>"; };
|
||||
E91738891BECCB5400717F6E /* opening_hours.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = opening_hours.hpp; sourceTree = "<group>"; };
|
||||
E917388B1BECCB5400717F6E /* parse_opening_hours.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_opening_hours.cpp; sourceTree = "<group>"; };
|
||||
E917388C1BECCB5400717F6E /* parse_opening_hours.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = parse_opening_hours.hpp; sourceTree = "<group>"; };
|
||||
E917388D1BECCB5400717F6E /* rules_evaluation_private.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rules_evaluation_private.hpp; sourceTree = "<group>"; };
|
||||
E917388E1BECCB5400717F6E /* rules_evaluation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rules_evaluation.cpp; sourceTree = "<group>"; };
|
||||
E917388F1BECCB5400717F6E /* rules_evaluation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rules_evaluation.hpp; sourceTree = "<group>"; };
|
||||
E91738A81BECCF4800717F6E /* opening_hours_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opening_hours_tests.cpp; sourceTree = "<group>"; };
|
||||
E91738AA1BECCF7A00717F6E /* opening_hours_integration_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opening_hours_integration_tests.cpp; sourceTree = "<group>"; };
|
||||
E91738AC1BECCF9C00717F6E /* opening_hours_supported_features_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opening_hours_supported_features_tests.cpp; sourceTree = "<group>"; };
|
||||
E91738B31BECD02B00717F6E /* opening_hours_supported_features_tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = opening_hours_supported_features_tests; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E91738C01BECD08500717F6E /* opening_hours_integration_tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = opening_hours_integration_tests; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E91738C91BECD0CE00717F6E /* opening-count.lst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "opening-count.lst"; sourceTree = "<group>"; };
|
||||
E91738CF1BECD36E00717F6E /* opening_hours_tests_ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = opening_hours_tests_ios.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E91738E21BECD36E00717F6E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E91739081BECD60000717F6E /* opening_hours_integration_tests_ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = opening_hours_integration_tests_ios.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -46,6 +97,39 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E917389C1BECCC1000717F6E /* libopening_hours.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91738B01BECD02B00717F6E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91738BB1BECD05A00717F6E /* libopening_hours.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91738BD1BECD08500717F6E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91738C71BECD09100717F6E /* libopening_hours.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91738CC1BECD36E00717F6E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91739031BECD55700717F6E /* libopening_hours.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91739051BECD60000717F6E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91739201BECD61A00717F6E /* libopening_hours.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -56,7 +140,11 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
670D05B71B0E0C290013A7AC /* defaults.xcconfig */,
|
||||
E91738A71BECCEDB00717F6E /* opening_hours_supported_features_tests */,
|
||||
E91738A61BECCED700717F6E /* opening_hours_integration_tests */,
|
||||
E91738A51BECCEB000717F6E /* opening_hours_tests */,
|
||||
670C61E91AC3511700C38A8C /* opening_hours */,
|
||||
E91738D01BECD36E00717F6E /* opening_hours_tests_ios */,
|
||||
670C61E81AC3511700C38A8C /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
|
@ -66,6 +154,10 @@
|
|||
children = (
|
||||
670C61E71AC3511700C38A8C /* libopening_hours.a */,
|
||||
670C61FF1AC351AC00C38A8C /* opening_hours_test */,
|
||||
E91738B31BECD02B00717F6E /* opening_hours_supported_features_tests */,
|
||||
E91738C01BECD08500717F6E /* opening_hours_integration_tests */,
|
||||
E91738CF1BECD36E00717F6E /* opening_hours_tests_ios.app */,
|
||||
E91739081BECD60000717F6E /* opening_hours_integration_tests_ios.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -73,14 +165,56 @@
|
|||
670C61E91AC3511700C38A8C /* opening_hours */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
670C61F51AC3517200C38A8C /* osm_time_range_tests.cpp */,
|
||||
670C61F61AC3517200C38A8C /* osm_time_range.cpp */,
|
||||
670C61F71AC3517200C38A8C /* osm_time_range.hpp */,
|
||||
E91738861BECCB5400717F6E /* opening_hours_parsers_terminals.hpp */,
|
||||
E91738871BECCB5400717F6E /* opening_hours_parsers.hpp */,
|
||||
E91738881BECCB5400717F6E /* opening_hours.cpp */,
|
||||
E91738891BECCB5400717F6E /* opening_hours.hpp */,
|
||||
E917388B1BECCB5400717F6E /* parse_opening_hours.cpp */,
|
||||
E917388C1BECCB5400717F6E /* parse_opening_hours.hpp */,
|
||||
E917388D1BECCB5400717F6E /* rules_evaluation_private.hpp */,
|
||||
E917388E1BECCB5400717F6E /* rules_evaluation.cpp */,
|
||||
E917388F1BECCB5400717F6E /* rules_evaluation.hpp */,
|
||||
);
|
||||
name = opening_hours;
|
||||
path = ../../3party/opening_hours;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E91738A51BECCEB000717F6E /* opening_hours_tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E91738A81BECCF4800717F6E /* opening_hours_tests.cpp */,
|
||||
);
|
||||
name = opening_hours_tests;
|
||||
path = ../../3party/opening_hours/opening_hours_tests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E91738A61BECCED700717F6E /* opening_hours_integration_tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E91738C91BECD0CE00717F6E /* opening-count.lst */,
|
||||
E91738AA1BECCF7A00717F6E /* opening_hours_integration_tests.cpp */,
|
||||
);
|
||||
name = opening_hours_integration_tests;
|
||||
path = ../../3party/opening_hours/opening_hours_integration_tests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E91738A71BECCEDB00717F6E /* opening_hours_supported_features_tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E91738AC1BECCF9C00717F6E /* opening_hours_supported_features_tests.cpp */,
|
||||
);
|
||||
name = opening_hours_supported_features_tests;
|
||||
path = ../../3party/opening_hours/opening_hours_supported_features_tests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E91738D01BECD36E00717F6E /* opening_hours_tests_ios */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E91738E21BECD36E00717F6E /* Info.plist */,
|
||||
);
|
||||
path = opening_hours_tests_ios;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
|
@ -88,7 +222,12 @@
|
|||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
670C61FA1AC3517200C38A8C /* osm_time_range.hpp in Headers */,
|
||||
E91738981BECCB5400717F6E /* rules_evaluation.hpp in Headers */,
|
||||
E91738911BECCB5400717F6E /* opening_hours_parsers.hpp in Headers */,
|
||||
E91738931BECCB5400717F6E /* opening_hours.hpp in Headers */,
|
||||
E91738901BECCB5400717F6E /* opening_hours_parsers_terminals.hpp in Headers */,
|
||||
E91738951BECCB5400717F6E /* parse_opening_hours.hpp in Headers */,
|
||||
E91738961BECCB5400717F6E /* rules_evaluation_private.hpp in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -129,6 +268,74 @@
|
|||
productReference = 670C61FF1AC351AC00C38A8C /* opening_hours_test */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
E91738B21BECD02B00717F6E /* opening_hours_supported_features_tests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E91738B71BECD02B00717F6E /* Build configuration list for PBXNativeTarget "opening_hours_supported_features_tests" */;
|
||||
buildPhases = (
|
||||
E91738AF1BECD02B00717F6E /* Sources */,
|
||||
E91738B01BECD02B00717F6E /* Frameworks */,
|
||||
E91738B11BECD02B00717F6E /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = opening_hours_supported_features_tests;
|
||||
productName = opening_hours_supported_features_tests;
|
||||
productReference = E91738B31BECD02B00717F6E /* opening_hours_supported_features_tests */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
E91738BF1BECD08500717F6E /* opening_hours_integration_tests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E91738C41BECD08500717F6E /* Build configuration list for PBXNativeTarget "opening_hours_integration_tests" */;
|
||||
buildPhases = (
|
||||
E91738BC1BECD08500717F6E /* Sources */,
|
||||
E91738BD1BECD08500717F6E /* Frameworks */,
|
||||
E91738BE1BECD08500717F6E /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = opening_hours_integration_tests;
|
||||
productName = opening_hours_integration_tests;
|
||||
productReference = E91738C01BECD08500717F6E /* opening_hours_integration_tests */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
E91738CE1BECD36E00717F6E /* opening_hours_tests_ios */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E91738F91BECD36F00717F6E /* Build configuration list for PBXNativeTarget "opening_hours_tests_ios" */;
|
||||
buildPhases = (
|
||||
E91738CB1BECD36E00717F6E /* Sources */,
|
||||
E91738CC1BECD36E00717F6E /* Frameworks */,
|
||||
E91738CD1BECD36E00717F6E /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = opening_hours_tests_ios;
|
||||
productName = opening_hours_tests_ios;
|
||||
productReference = E91738CF1BECD36E00717F6E /* opening_hours_tests_ios.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
E91739071BECD60000717F6E /* opening_hours_integration_tests_ios */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E917391C1BECD60000717F6E /* Build configuration list for PBXNativeTarget "opening_hours_integration_tests_ios" */;
|
||||
buildPhases = (
|
||||
E91739041BECD60000717F6E /* Sources */,
|
||||
E91739051BECD60000717F6E /* Frameworks */,
|
||||
E91739061BECD60000717F6E /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = opening_hours_integration_tests_ios;
|
||||
productName = opening_hours_integration_tests_ios;
|
||||
productReference = E91739081BECD60000717F6E /* opening_hours_integration_tests_ios.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
|
@ -144,6 +351,18 @@
|
|||
670C61FE1AC351AC00C38A8C = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
E91738B21BECD02B00717F6E = {
|
||||
CreatedOnToolsVersion = 7.1;
|
||||
};
|
||||
E91738BF1BECD08500717F6E = {
|
||||
CreatedOnToolsVersion = 7.1;
|
||||
};
|
||||
E91738CE1BECD36E00717F6E = {
|
||||
CreatedOnToolsVersion = 7.1;
|
||||
};
|
||||
E91739071BECD60000717F6E = {
|
||||
CreatedOnToolsVersion = 7.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 670C61E21AC3511700C38A8C /* Build configuration list for PBXProject "opening_hours" */;
|
||||
|
@ -152,6 +371,7 @@
|
|||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 670C61DE1AC3511700C38A8C;
|
||||
productRefGroup = 670C61E81AC3511700C38A8C /* Products */;
|
||||
|
@ -160,16 +380,40 @@
|
|||
targets = (
|
||||
670C61E61AC3511700C38A8C /* opening_hours */,
|
||||
670C61FE1AC351AC00C38A8C /* opening_hours_test */,
|
||||
E91738B21BECD02B00717F6E /* opening_hours_supported_features_tests */,
|
||||
E91738BF1BECD08500717F6E /* opening_hours_integration_tests */,
|
||||
E91738CE1BECD36E00717F6E /* opening_hours_tests_ios */,
|
||||
E91739071BECD60000717F6E /* opening_hours_integration_tests_ios */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
E91738CD1BECD36E00717F6E /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91739061BECD60000717F6E /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91739211BECD62E00717F6E /* opening-count.lst in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
670C61E31AC3511700C38A8C /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
671C61FF1AE7AF4000076BD0 /* osm_time_range.cpp in Sources */,
|
||||
E91738941BECCB5400717F6E /* parse_opening_hours.cpp in Sources */,
|
||||
E91738921BECCB5400717F6E /* opening_hours.cpp in Sources */,
|
||||
E91738971BECCB5400717F6E /* rules_evaluation.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -177,8 +421,39 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
671C62021AE7AF4800076BD0 /* osm_time_range_tests.cpp in Sources */,
|
||||
671C62011AE7AF4400076BD0 /* osm_time_range.cpp in Sources */,
|
||||
E91738AE1BECCFAC00717F6E /* opening_hours_tests.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91738AF1BECD02B00717F6E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91738BA1BECD03B00717F6E /* opening_hours_supported_features_tests.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91738BC1BECD08500717F6E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91738C81BECD09700717F6E /* opening_hours_integration_tests.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91738CB1BECD36E00717F6E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E91739021BECD54300717F6E /* opening_hours_tests.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E91739041BECD60000717F6E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E917391F1BECD61400717F6E /* opening_hours_integration_tests.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -313,6 +588,124 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
E91738B81BECD02B00717F6E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E91738B91BECD02B00717F6E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E91738C51BECD08500717F6E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E91738C61BECD08500717F6E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E91738FA1BECD36F00717F6E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = opening_hours_tests_ios/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "mail.ru.opening-hours-tests-ios";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E91738FB1BECD36F00717F6E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = opening_hours_tests_ios/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "mail.ru.opening-hours-tests-ios";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E917391D1BECD60000717F6E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = opening_hours_integration_tests_ios/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "mail.ru.opening-hours-integration-tests-ios";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E917391E1BECD60000717F6E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = opening_hours_integration_tests_ios/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "mail.ru.opening-hours-integration-tests-ios";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
|
@ -343,6 +736,42 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E91738B71BECD02B00717F6E /* Build configuration list for PBXNativeTarget "opening_hours_supported_features_tests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E91738B81BECD02B00717F6E /* Debug */,
|
||||
E91738B91BECD02B00717F6E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E91738C41BECD08500717F6E /* Build configuration list for PBXNativeTarget "opening_hours_integration_tests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E91738C51BECD08500717F6E /* Debug */,
|
||||
E91738C61BECD08500717F6E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E91738F91BECD36F00717F6E /* Build configuration list for PBXNativeTarget "opening_hours_tests_ios" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E91738FA1BECD36F00717F6E /* Debug */,
|
||||
E91738FB1BECD36F00717F6E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E917391C1BECD60000717F6E /* Build configuration list for PBXNativeTarget "opening_hours_integration_tests_ios" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E917391D1BECD60000717F6E /* Debug */,
|
||||
E917391E1BECD60000717F6E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 670C61DF1AC3511700C38A8C /* Project object */;
|
||||
|
|
47
xcode/opening_hours/opening_hours_tests_ios/Info.plist
Normal file
47
xcode/opening_hours/opening_hours_tests_ios/Info.plist
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
Loading…
Add table
Reference in a new issue