/* The software in this package is distributed under the GNU General Public License version 2 (with a special exception described below). A copy of GNU General Public License (GPL) is included in this distribution, in the file COPYING.GPL. As a special exception, if other files instantiate templates or use macros or inline functions from this file, or you compile this file and link it with other works to produce a work based on this file, this file does not by itself cause the resulting work to be covered by the GNU General Public License. However the source code for this file must still be made available in accordance with section (3) of the GNU General Public License. This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License. */ #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); unsigned int wnr=7; if (!(c >> wnr) || 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 >= _WeekDay_END) { IsValid = false; return IsValid; } Days.set(static_cast(day), value); return IsValid; } /** * Check if a particular day is active * @param day Day to check * @return True if day is active, false otherwise */ bool Week::get(WeekDay day) const { return Days.test(static_cast(day)); } /** * Check if a particular day is active * @param day Day to check * @return True if day is active, false otherwise */ bool Week::is_set(WeekDay day) const { return Days.test(static_cast(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 */ unsigned int Week::days_till_set(WeekDay start) const { if (none_set()) return 0; 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 0; //lint !e527 } /** @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 */ unsigned int Week::days_since_set(WeekDay start) const { if (none_set()) return 0; for (unsigned int days=0; days < 8; days++) { int check=start-static_cast(days); if (check < 0) check+=7; if (is_set(static_cast(check))) return days; } throw logic_error("can't find next weekday"); // fake return 0; //lint !e527 } /** * Get days as number string compatible for set() like "345". * @return Days as string */ std::string Week::get_daystring() const { ostringstream out; for (unsigned 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; // We want to display from Monday to Sunday so reorder // the bitset and make monday bit 0 and sunday bit 6. bitset<7> reordered = Days >> 1; reordered.set(6, Days[0]); for (unsigned int i = 0; i < 7; ++i) { // day active? if (!reordered.test(i)) continue; if (!weekdays_str.empty()) weekdays_str += ", "; // get day string (revert the reorder) weekdays_str += get_day_display(i == 6 ? Su : static_cast(i+1)); // check if we can group two or more days unsigned int group_days = i; while (group_days < 6 && reordered.test(group_days+1)) group_days++; // Were we able to group two or more days? if (group_days > i+1) { i = group_days; weekdays_str += "-" + get_day_display(i == 6 ? Su : static_cast(i+1)); } } /*lint --e(850) */ return weekdays_str; } /** * Get days as string suitable for netfilter rules * @return */ std::string Week::get_netfilterstring() const { string out; for (unsigned 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; } //lint !e788: Don't complain about unused _WeekDay_END 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; } //lint !e788: Don't complain about unused _WeekDay_END return weekday_str; } } }