From 0c7e72d719bdea3b7e9cae8ad46e50ebe1b672ba Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Wed, 28 Jan 2009 15:00:07 +0100 Subject: [PATCH] Moved WEEK class to own file. Renamed to Week and adapted to I2n code style. Adapted all client code. Added Week::is_valid(). Made constructor more exception safe. --- src/Makefile.am | 5 +- src/cron.cpp | 11 +- src/cron.hpp | 10 +- src/timefunc.cpp | 206 ----------------------------- src/timefunc.hxx | 126 +------------------ src/week.cpp | 362 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/week.hpp | 132 +++++++++++++++++++ test/test_cron.cpp | 2 +- 8 files changed, 510 insertions(+), 344 deletions(-) create mode 100644 src/week.cpp create mode 100644 src/week.hpp diff --git a/src/Makefile.am b/src/Makefile.am index b0aaecf..5542c9a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,12 +4,13 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ @LIBICONV_CFLAGS@ $(all_inclu # the library search path. lib_LTLIBRARIES = libi2ncommon.la -include_HEADERS = containerfunc.hpp cron.hpp daemonfunc.hpp filefunc.hxx \ +include_HEADERS = week.hpp containerfunc.hpp cron.hpp daemonfunc.hpp filefunc.hxx \ i2n_configdata.hpp i2n_configfile.hpp insocketstream.hxx ip_type.hxx ipfunc.hxx \ log_macros.hpp logfunc.hpp logread.hxx oftmpstream.hxx pidfile.hpp pipestream.hxx \ pointer_func.hpp signalfunc.hpp source_track_basics.hpp stringfunc.hxx timefunc.hxx \ tracefunc.hpp userfunc.hpp -libi2ncommon_la_SOURCES = containerfunc.cpp cron.cpp daemonfunc.cpp \ + +libi2ncommon_la_SOURCES = week.cpp containerfunc.cpp cron.cpp daemonfunc.cpp \ filefunc.cpp i2n_configfile.cpp ipfunc.cpp logfunc.cpp logread.cpp oftmpstream.cpp \ pidfile.cpp pointer_func.cpp signalfunc.cpp source_track_basics.cpp stringfunc.cpp \ timefunc.cpp tracefunc.cpp userfunc.cpp diff --git a/src/cron.cpp b/src/cron.cpp index f77d905..b0f954c 100644 --- a/src/cron.cpp +++ b/src/cron.cpp @@ -11,8 +11,8 @@ #include #include -namespace I2n -{ +namespace I2n { +namespace Time { /** * Constructor @@ -131,7 +131,7 @@ time_t WeekCron::get_next_point(const time_t calc_from, const int daysec, const localtime_r(&calc_from,&ft); // take care of the weekday - ft.tm_mday+=Week.days_till_set(static_cast(ft.tm_wday)); + ft.tm_mday+=Week.days_till_set(static_cast(ft.tm_wday)); ft.tm_hour=0; ft.tm_min=0; @@ -167,7 +167,7 @@ time_t WeekCron::get_lastnow_point(const time_t calc_from, const int daysec, con localtime_r(&calc_from,&ft); // take care of the weekday - ft.tm_mday-=Week.days_since_set(static_cast(ft.tm_wday)); + ft.tm_mday-=Week.days_since_set(static_cast(ft.tm_wday)); ft.tm_hour=0; ft.tm_min=0; @@ -188,4 +188,5 @@ time_t WeekCron::get_lastnow_point(const time_t calc_from, const int daysec, con return target; } -} \ No newline at end of file +} +} diff --git a/src/cron.hpp b/src/cron.hpp index 9d6e254..b634e3f 100644 --- a/src/cron.hpp +++ b/src/cron.hpp @@ -11,10 +11,10 @@ #define __CRON_HPP #include -#include +#include -namespace I2n -{ +namespace I2n { +namespace Time { /// Time points and intervals repeating each week /** @@ -31,7 +31,7 @@ class WeekCron /// Repeat event every xxx seconds in the half-open interval of #Begin and #End. -1 is disabled int Every; /// Stores the active days this WeekCron is valid for - WEEK Week; + I2n::Time::Week Week; time_t get_next_point(const time_t calc_from, const int daysec, const bool todaycheck); time_t get_lastnow_point(const time_t calc_from, const int daysec, const bool todaycheck); @@ -43,9 +43,9 @@ class WeekCron bool is_sane() const; time_t get_next_run(time_t calc_from=0); - }; } +} #endif diff --git a/src/timefunc.cpp b/src/timefunc.cpp index 56bfcc8..b6cca0b 100644 --- a/src/timefunc.cpp +++ b/src/timefunc.cpp @@ -166,212 +166,6 @@ std::string output_hour_minute(int hour, int minute, bool h_for_00) return out.str(); } -void WEEK::set(const std::string& daystring) -{ - int len=daystring.length(); - for (int p=0; p < len; p++) - { - char nr[2]; - nr[0]=daystring[p]; - nr[1]=0; - istringstream c(nr); - int wnr=-1; - if (!(c >> wnr) || wnr<0 || wnr >6) - throw range_error("illegal weekday >"+string(nr)+"< in "+daystring); - - days.set(wnr); - } -} - -/** - @brief returns the number of days till the next weekday which is set - @param start weekday to start checking - @note returns 0 if the start-day is set -*/ -int WEEK::days_till_set(WEEKDAY start) -{ - if (none_set()) - return -1; - - for (unsigned int days=0; days < 8; days++) - { - unsigned int check=start+days; - if (check > 6) - check-=7; - if (is_set(static_cast(check))) - return days; - } - - throw logic_error("can't find next weekday"); - - // fake - return -1; -} - -/** - @brief returns the number of days since the previous weekday which is set - @param start weekday to start checking - @note returns 0 if the start-day is set -*/ -int WEEK::days_since_set(WEEKDAY start) -{ - if (none_set()) - return -1; - - for (unsigned int days=0; days < 8; days++) - { - int check=start-days; - if (check < 0) - check+=7; - if (is_set(static_cast(check))) - return days; - } - - throw logic_error("can't find next weekday"); - - // fake - return -1; -} - -std::string WEEK::get_daystring() const -{ - ostringstream out; - for (int i = 0; i < 7; i++) - if (days[i]) - out << i; - - return out.str(); -} - -std::string WEEK::get_displaystring() const -{ - string weekdays_str; - - // From Monday to Saturday - int j; - for (int i = 1; i < 7; i++) - { - if (days[i]) - { - if (!weekdays_str.empty()) - weekdays_str += ", "; - - weekdays_str += get_day_display(static_cast(i)); - - // check if we can group two or more days - j = i; - while (days[j] && j < 7) - j++; - j--; - - // Sunday end of week? j -> 7 - if (j-i > 0 && j == 6 && days[0]) - j++; - - if (j-i > 1) - { - if (j == 7) - weekdays_str += "-" + get_day_display(SU); - else - weekdays_str += "-" + get_day_display(static_cast(j)); - - i = j; - } - } - } - - // special: sunday - if (days[0] && j != 7) - { - if (!weekdays_str.empty()) - weekdays_str += ", "; - - weekdays_str += get_day_display(SU); - } - - return weekdays_str; -} - -std::string WEEK::get_netfilterstring() const -{ - string out; - for (int i = 0; i < 7; i++) - if (days[i]) - { - if (!out.empty()) - out+=","; - out+=get_english_display(static_cast(i));; - } - - return out; -} - -std::string WEEK::get_day_display(WEEKDAY day) -{ - string weekday_str; - - switch (day) { - case MO: - weekday_str = i18n("Mon"); - break; - case TU: - weekday_str = i18n("Tue"); - break; - case WE: - weekday_str = i18n("Wed"); - break; - case TH: - weekday_str = i18n("Thu"); - break; - case FR: - weekday_str = i18n("Fri"); - break; - case SA: - weekday_str = i18n("Sat"); - break; - case SU: - weekday_str = i18n("Sun"); - break; - default: - break; - } - - return weekday_str; -} - -std::string WEEK::get_english_display(WEEKDAY day) -{ - string weekday_str; - - switch (day) { - case MO: - weekday_str = "Mon"; - break; - case TU: - weekday_str = "Tue"; - break; - case WE: - weekday_str = "Wed"; - break; - case TH: - weekday_str = "Thu"; - break; - case FR: - weekday_str = "Fri"; - break; - case SA: - weekday_str = "Sat"; - break; - case SU: - weekday_str = "Sun"; - break; - default: - break; - } - - return weekday_str; -} - string get_month_name(unsigned char month) { string rtn; diff --git a/src/timefunc.hxx b/src/timefunc.hxx index ddb86db..f5ccd32 100644 --- a/src/timefunc.hxx +++ b/src/timefunc.hxx @@ -11,9 +11,9 @@ #define __TIMEFUNC_HXX #include -#include #include +#include double prec_time(void); @@ -33,130 +33,6 @@ inline std::string output_hour_minute_from_seconds(int seconds) std::string get_month_name(unsigned char month); - -/** - * @brief represents some days of a week. - * - */ -class WEEK -{ - private: - std::bitset<7> days; - - public: - enum WEEKDAY { SU=0, MO=1, TU=2, WE=3, TH=4, FR=5, SA=6 }; - - // throws out_of_range if illegal week - WEEK(const std::string& daystring) - { set(daystring); } - - WEEK(const std::bitset<7> &_days) - : days(_days) - { } - - WEEK() - { } - - void clear() - { days.reset(); } - - operator std::bitset<7>() const - { return days; } - - void set(const std::string& daystring); - void set(WEEKDAY d, bool value=true) - { days[d]=value; } - - bool get(WEEKDAY d) const { return days[d]; } - bool is_set(WEEKDAY d) const { return days[d]; } - - bool all_set() const - { return (days.count()==7); } - bool none_set() const - { return days.none(); } - - int days_till_set(WEEKDAY day); - int days_since_set(WEEKDAY day); - - std::string get_daystring() const; - std::string get_displaystring() const; - std::string get_netfilterstring() const; - - static std::string get_day_display(WEEKDAY day); - static std::string get_english_display(WEEKDAY day); - - // some operators for convenience: - - WEEK& operator&=(const WEEK& rhs) - { - days &= rhs.days; - return *this; - } - - WEEK& operator|=(const WEEK& rhs) - { - days|= rhs.days; - return *this; - } - - WEEK& operator^=(const WEEK& rhs) - { - days^= rhs.days; - return *this; - } - - bool operator==(const WEEK& rhs) - { - return days == rhs.days; - } - - bool operator!=(const WEEK& rhs) - { - return days != rhs.days; - } - -}; // eo class WEEK - - -/** - * @brief delivers a week containing the days which are in both weeks. - * @param lhs first week. - * @param rhs second week. - * @return week which has only those days which are in both weeks. - */ -inline WEEK operator&(const WEEK& lhs, const WEEK& rhs) -{ - WEEK result(lhs); - return result &= rhs; -} // eo operator&(const WEEK&,const WEEK&) - - -/** - * @brief delivers a week containing the days which are at least in one of both weeks. - * @param lhs first week. - * @param rhs second week. - * @return week which has only those days which are at least in one of both weeks. - */ -inline WEEK operator|(const WEEK& lhs, const WEEK& rhs) -{ - WEEK result(lhs); - return result |= rhs; -} // eo operator&(const WEEK&,const WEEK&) - - -/** - * @brief delivers a week containing the days which are in only one of both weeks. - * @param lhs first week. - * @param rhs second week. - * @return week which has only those days which are in only one of both weeks. - */ -inline WEEK operator^(const WEEK& lhs, const WEEK& rhs) -{ - WEEK result(lhs); - return result ^= rhs; -} // eo operator&(const WEEK&,const WEEK&) - - /** * @brief structure representing a single (half-open) interval. */ diff --git a/src/week.cpp b/src/week.cpp new file mode 100644 index 0000000..608459a --- /dev/null +++ b/src/week.cpp @@ -0,0 +1,362 @@ +#include + +#include +#include + +#include + +using namespace std; + +namespace I2n { +namespace Time { + +/** + * Constructor + * @param daystring Active days as string. 0 is Sunday. Call is_sane() afterwards. + */ +Week::Week(const std::string& daystring) +{ + IsValid = set(daystring); +} + +/** + * Constructor + * @param days Active days as bitset. 0 is Sunday + */ +Week::Week(const std::bitset<7> &days) + : Days(days) + , IsValid(true) +{ +} + +/** + * Default constructor + */ +Week::Week() + : IsValid(true) +{ +} + +/** + * Check if this Week object is valid, f.e. after set(). + * @return True if valid, false otherwise + */ +bool Week::is_valid() const +{ + return IsValid; +} + +/** + * Clear all active days + */ +void Week::clear() +{ + Days.reset(); + IsValid = true; +} + +/** + * Set active days as string. Clears unset values. + * Active days will remain untouched if there's an error + * which you can query via is_valid(). + * @param daystring Active days as string + * @return True if all is fine, false otherwise + */ +bool Week::set(const std::string& daystring) +{ + bitset<7> new_days; + IsValid = true; + + string::size_type len=daystring.length(); + for (string::size_type p=0; p < len; p++) + { + char nr[2]; + nr[0]=daystring[p]; + nr[1]=0; + istringstream c(nr); + int wnr=-1; + if (!(c >> wnr) || wnr<0 || wnr >6) + { + IsValid = false; + return IsValid; + } + + new_days.set(wnr); + } + // Atomic switch-over + Days = new_days; + + return IsValid; +} + +/** + * Set or disable one weekday. + * @param day Day to modify + * @param value True for active, false to disable + * @return True if all is fine, false otherwise + */ +bool Week::set(const WeekDay day, bool value) +{ + if (day < 0 || day >= _WeekDay_END) + { + IsValid = false; + return IsValid; + } + + Days[day]=value; + return IsValid; +} + +/** + * Check if a particular day is active + * @param d Day to check + * @return True if day is active, false otherwise + */ +bool Week::get(WeekDay day) const +{ + return Days[day]; +} + +/** + * Check if a particular day is active + * @param d Day to check + * @return True if day is active, false otherwise + */ +bool Week::is_set(WeekDay day) const +{ + return Days[day]; +} + +/** + * Check if all days are active + * @return True if all days are active, false otherwise + */ +bool Week::all_set() const +{ + return (Days.count()==7); +} + +/** + * Check if no days is active + * @return True if no day is active, false otherwise + */ +bool Week::none_set() const +{ + return Days.none(); +} + +/** + @brief returns the number of days till the next weekday which is set + @param start weekday to start checking + @note returns 0 if the start-day is set +*/ +int Week::days_till_set(WeekDay start) +{ + if (none_set()) + return -1; + + for (unsigned int days=0; days < 8; days++) + { + unsigned int check=start+days; + if (check > 6) + check-=7; + if (is_set(static_cast(check))) + return days; + } + + throw logic_error("can't find next weekday"); + + // fake + return -1; +} + +/** + @brief returns the number of days since the previous weekday which is set + @param start weekday to start checking + @note returns 0 if the start-day is set +*/ +int Week::days_since_set(WeekDay start) +{ + if (none_set()) + return -1; + + for (unsigned int days=0; days < 8; days++) + { + int check=start-days; + if (check < 0) + check+=7; + if (is_set(static_cast(check))) + return days; + } + + throw logic_error("can't find next weekday"); + + // fake + return -1; +} + +/** + * Get days as number string compatible for set() like "345". + * @return Days as string + */ +std::string Week::get_daystring() const +{ + ostringstream out; + + for (int i = 0; i < 7; i++) + if (Days[i]) + out << i; + + return out.str(); +} + +/** + * Get days as string presentable to the user + * @return Days as string + */ +std::string Week::get_displaystring() const +{ + string weekdays_str; + + // From Monday to Saturday + int j; + for (int i = 1; i < 7; i++) + { + if (Days[i]) + { + if (!weekdays_str.empty()) + weekdays_str += ", "; + + weekdays_str += get_day_display(static_cast(i)); + + // check if we can group two or more days + j = i; + while (Days[j] && j < 7) + j++; + j--; + + // Sunday end of week? j -> 7 + if (j-i > 0 && j == 6 && Days[0]) + j++; + + if (j-i > 1) + { + if (j == 7) + weekdays_str += "-" + get_day_display(Su); + else + weekdays_str += "-" + get_day_display(static_cast(j)); + + i = j; + } + } + } + + // special: sunday + if (Days[0] && j != 7) + { + if (!weekdays_str.empty()) + weekdays_str += ", "; + + weekdays_str += get_day_display(Su); + } + + return weekdays_str; +} + +/** + * Get days as string suitable for netfilter rules + * @return + */ +std::string Week::get_netfilterstring() const +{ + string out; + + for (int i = 0; i < 7; i++) + if (Days[i]) + { + if (!out.empty()) + out+=","; + out+=get_english_display(static_cast(i));; + } + + return out; +} + +/** + * Convert WeekDay to readable string + * @param day WeekDay to convert + * @return Weekday as string + */ +std::string Week::get_day_display(WeekDay day) +{ + string weekday_str; + + switch (day) { + case Mo: + weekday_str = i18n("Mon"); + break; + case Tu: + weekday_str = i18n("Tue"); + break; + case We: + weekday_str = i18n("Wed"); + break; + case Th: + weekday_str = i18n("Thu"); + break; + case Fr: + weekday_str = i18n("Fri"); + break; + case Sa: + weekday_str = i18n("Sat"); + break; + case Su: + weekday_str = i18n("Sun"); + break; + default: + break; + } + + return weekday_str; +} + +/** + * Convert WeekDay to readable string without i18n + * @param day WeekDay to convert + * @return WeekDay as string in English + */ +std::string Week::get_english_display(WeekDay day) +{ + string weekday_str; + + switch (day) { + case Mo: + weekday_str = "Mon"; + break; + case Tu: + weekday_str = "Tue"; + break; + case We: + weekday_str = "Wed"; + break; + case Th: + weekday_str = "Thu"; + break; + case Fr: + weekday_str = "Fri"; + break; + case Sa: + weekday_str = "Sat"; + break; + case Su: + weekday_str = "Sun"; + break; + default: + break; + } + + return weekday_str; +} + +} +} diff --git a/src/week.hpp b/src/week.hpp new file mode 100644 index 0000000..9be554f --- /dev/null +++ b/src/week.hpp @@ -0,0 +1,132 @@ +/** @file + * @brief time related functions. Week module + * + * @copyright Copyright © 2001-2009 by Intra2net AG + * @license commercial + * @contact info@intra2net.com + * + */ + +#include +#include + +namespace I2n { +namespace Time { + +/** + * @brief represents some days of a week. + * + */ +class Week +{ + private: + /// Bitset storing the active days. Zero is Sunday. + std::bitset<7> Days; + /// Flag to indicate if this Week is valid + bool IsValid; + + public: + enum WeekDay { Su=0, Mo=1, Tu=2, We=3, Th=4, Fr=5, Sa=6, _WeekDay_END=7 }; + + Week(); + Week(const std::string& daystring); + Week(const std::bitset<7> &_days); + + bool is_valid() const; + + void clear(); + + operator std::bitset<7>() const + { return Days; } + + bool set(const std::string& daystring); + bool set(const WeekDay day, bool value=true); + + bool get(WeekDay day) const; + bool is_set(WeekDay day) const; + + bool all_set() const; + bool none_set() const; + + int days_till_set(WeekDay day); + int days_since_set(WeekDay day); + + std::string get_daystring() const; + std::string get_displaystring() const; + std::string get_netfilterstring() const; + + static std::string get_day_display(WeekDay day); + static std::string get_english_display(WeekDay day); + + // some operators for convenience: + + Week& operator&=(const Week& rhs) + { + Days &= rhs.Days; + return *this; + } + + Week& operator|=(const Week& rhs) + { + Days |= rhs.Days; + return *this; + } + + Week& operator^=(const Week& rhs) + { + Days ^= rhs.Days; + return *this; + } + + bool operator==(const Week& rhs) + { + return Days == rhs.Days; + } + + bool operator!=(const Week& rhs) + { + return Days != rhs.Days; + } +}; + + +/** + * @brief delivers a week containing the days which are in both weeks. + * @param lhs first week. + * @param rhs second week. + * @return week which has only those days which are in both weeks. + */ +inline Week operator&(const Week& lhs, const Week& rhs) +{ + I2n::Time::Week result(lhs); + return result &= rhs; +} + + +/** + * @brief delivers a week containing the days which are at least in one of both weeks. + * @param lhs first week. + * @param rhs second week. + * @return week which has only those days which are at least in one of both weeks. + */ +inline Week operator|(const Week& lhs, const Week& rhs) +{ + I2n::Time::Week result(lhs); + return result |= rhs; +} + + +/** + * @brief delivers a week containing the days which are in only one of both weeks. + * @param lhs first week. + * @param rhs second week. + * @return week which has only those days which are in only one of both weeks. + */ +inline Week operator^(const Week& lhs, const Week& rhs) +{ + I2n::Time::Week result(lhs); + return result ^= rhs; +} + +} +} diff --git a/test/test_cron.cpp b/test/test_cron.cpp index 70703ad..c567ee2 100644 --- a/test/test_cron.cpp +++ b/test/test_cron.cpp @@ -18,7 +18,7 @@ #include using namespace std; -using namespace I2n; +using namespace I2n::Time; using namespace CppUnit; class TestCronFunc : public TestFixture -- 1.7.1