changed doc only to make doxygen happier and get less warnings during build
[libi2ncommon] / src / week.cpp
CommitLineData
0e23f538
TJ
1/*
2The software in this package is distributed under the GNU General
3Public License version 2 (with a special exception described below).
4
5A copy of GNU General Public License (GPL) is included in this distribution,
6in the file COPYING.GPL.
7
8As a special exception, if other files instantiate templates or use macros
9or inline functions from this file, or you compile this file and link it
10with other works to produce a work based on this file, this file
11does not by itself cause the resulting work to be covered
12by the GNU General Public License.
13
14However the source code for this file must still be made available
15in accordance with section (3) of the GNU General Public License.
16
17This exception does not invalidate any other reasons why a work based
18on this file might be covered by the GNU General Public License.
19*/
0c7e72d7
TJ
20#include <week.hpp>
21
22#include <sstream>
23#include <stdexcept>
24
25#include <i18n.h>
26
27using namespace std;
28
29namespace I2n {
30namespace Time {
31
32/**
33 * Constructor
34 * @param daystring Active days as string. 0 is Sunday. Call is_sane() afterwards.
35 */
36Week::Week(const std::string& daystring)
37{
38 IsValid = set(daystring);
39}
40
41/**
42 * Constructor
43 * @param days Active days as bitset. 0 is Sunday
44 */
45Week::Week(const std::bitset<7> &days)
46 : Days(days)
47 , IsValid(true)
48{
49}
50
51/**
52 * Default constructor
53 */
54Week::Week()
55 : IsValid(true)
56{
57}
58
59/**
60 * Check if this Week object is valid, f.e. after set().
61 * @return True if valid, false otherwise
62 */
63bool Week::is_valid() const
64{
65 return IsValid;
66}
67
68/**
69 * Clear all active days
70 */
71void Week::clear()
72{
8047e088 73 Days.reset();
0c7e72d7
TJ
74 IsValid = true;
75}
76
77/**
78 * Set active days as string. Clears unset values.
79 * Active days will remain untouched if there's an error
80 * which you can query via is_valid().
81 * @param daystring Active days as string
82 * @return True if all is fine, false otherwise
83 */
84bool Week::set(const std::string& daystring)
85{
86 bitset<7> new_days;
87 IsValid = true;
88
89 string::size_type len=daystring.length();
90 for (string::size_type p=0; p < len; p++)
91 {
92 char nr[2];
93 nr[0]=daystring[p];
94 nr[1]=0;
95 istringstream c(nr);
12963590
TJ
96 unsigned int wnr=7;
97 if (!(c >> wnr) || wnr > 6)
0c7e72d7
TJ
98 {
99 IsValid = false;
100 return IsValid;
101 }
102
8047e088 103 new_days.set(wnr);
0c7e72d7
TJ
104 }
105 // Atomic switch-over
106 Days = new_days;
107
108 return IsValid;
109}
110
111/**
112 * Set or disable one weekday.
113 * @param day Day to modify
114 * @param value True for active, false to disable
115 * @return True if all is fine, false otherwise
116 */
117bool Week::set(const WeekDay day, bool value)
118{
12963590 119 if (day >= _WeekDay_END)
0c7e72d7
TJ
120 {
121 IsValid = false;
122 return IsValid;
123 }
124
8047e088 125 Days.set(static_cast<size_t>(day), value);
12963590 126
0c7e72d7
TJ
127 return IsValid;
128}
129
130/**
131 * Check if a particular day is active
3438e43a 132 * @param day Day to check
0c7e72d7
TJ
133 * @return True if day is active, false otherwise
134 */
135bool Week::get(WeekDay day) const
136{
12963590 137 return Days.test(static_cast<size_t>(day));
0c7e72d7
TJ
138}
139
140/**
141 * Check if a particular day is active
3438e43a 142 * @param day Day to check
0c7e72d7
TJ
143 * @return True if day is active, false otherwise
144 */
145bool Week::is_set(WeekDay day) const
146{
12963590 147 return Days.test(static_cast<size_t>(day));
0c7e72d7
TJ
148}
149
150/**
151 * Check if all days are active
152 * @return True if all days are active, false otherwise
153 */
154bool Week::all_set() const
155{
156 return (Days.count()==7);
157}
158
159/**
160 * Check if no days is active
161 * @return True if no day is active, false otherwise
162 */
163bool Week::none_set() const
164{
165 return Days.none();
166}
167
168/**
169 @brief returns the number of days till the next weekday which is set
170 @param start weekday to start checking
171 @note returns 0 if the start-day is set
172*/
12963590 173unsigned int Week::days_till_set(WeekDay start) const
0c7e72d7
TJ
174{
175 if (none_set())
12963590 176 return 0;
0c7e72d7
TJ
177
178 for (unsigned int days=0; days < 8; days++)
179 {
180 unsigned int check=start+days;
181 if (check > 6)
182 check-=7;
183 if (is_set(static_cast<WeekDay>(check)))
184 return days;
185 }
186
187 throw logic_error("can't find next weekday");
188
189 // fake
12963590 190 return 0; //lint !e527
0c7e72d7
TJ
191}
192
193/**
194 @brief returns the number of days since the previous weekday which is set
195 @param start weekday to start checking
196 @note returns 0 if the start-day is set
197*/
12963590 198unsigned int Week::days_since_set(WeekDay start) const
0c7e72d7
TJ
199{
200 if (none_set())
12963590 201 return 0;
0c7e72d7
TJ
202
203 for (unsigned int days=0; days < 8; days++)
204 {
12963590 205 int check=start-static_cast<int>(days);
0c7e72d7
TJ
206 if (check < 0)
207 check+=7;
208 if (is_set(static_cast<WeekDay>(check)))
209 return days;
210 }
211
212 throw logic_error("can't find next weekday");
213
214 // fake
12963590 215 return 0; //lint !e527
0c7e72d7
TJ
216}
217
218/**
219 * Get days as number string compatible for set() like "345".
220 * @return Days as string
221 */
222std::string Week::get_daystring() const
223{
224 ostringstream out;
225
12963590 226 for (unsigned int i = 0; i < 7; i++)
0c7e72d7
TJ
227 if (Days[i])
228 out << i;
229
230 return out.str();
231}
232
233/**
234 * Get days as string presentable to the user
235 * @return Days as string
236 */
237std::string Week::get_displaystring() const
238{
239 string weekdays_str;
240
8047e088
TJ
241 // We want to display from Monday to Sunday so reorder
242 // the bitset and make monday bit 0 and sunday bit 6.
243 bitset<7> reordered = Days >> 1;
244 reordered.set(6, Days[0]);
0c7e72d7 245
8047e088 246 for (unsigned int i = 0; i < 7; ++i)
0c7e72d7 247 {
8047e088
TJ
248 // day active?
249 if (!reordered.test(i))
250 continue;
251
0c7e72d7
TJ
252 if (!weekdays_str.empty())
253 weekdays_str += ", ";
254
8047e088
TJ
255 // get day string (revert the reorder)
256 weekdays_str += get_day_display(i == 6 ? Su : static_cast<WeekDay>(i+1));
257
258 // check if we can group two or more days
259 unsigned int group_days = i;
260 while (group_days < 6 && reordered.test(group_days+1))
261 group_days++;
262
263 // Were we able to group two or more days?
264 if (group_days > i+1)
265 {
266 i = group_days;
267 weekdays_str += "-" + get_day_display(i == 6 ? Su : static_cast<WeekDay>(i+1));
268 }
269 } /*lint --e(850) */
0c7e72d7
TJ
270
271 return weekdays_str;
272}
273
274/**
275 * Get days as string suitable for netfilter rules
276 * @return
277 */
278std::string Week::get_netfilterstring() const
279{
280 string out;
281
12963590 282 for (unsigned int i = 0; i < 7; i++)
0c7e72d7
TJ
283 if (Days[i])
284 {
285 if (!out.empty())
286 out+=",";
287 out+=get_english_display(static_cast<WeekDay>(i));;
288 }
289
290 return out;
291}
292
293/**
294 * Convert WeekDay to readable string
295 * @param day WeekDay to convert
296 * @return Weekday as string
297 */
298std::string Week::get_day_display(WeekDay day)
299{
300 string weekday_str;
301
12963590
TJ
302 switch (day)
303 {
0c7e72d7
TJ
304 case Mo:
305 weekday_str = i18n("Mon");
306 break;
307 case Tu:
308 weekday_str = i18n("Tue");
309 break;
310 case We:
311 weekday_str = i18n("Wed");
312 break;
313 case Th:
314 weekday_str = i18n("Thu");
315 break;
316 case Fr:
317 weekday_str = i18n("Fri");
318 break;
319 case Sa:
320 weekday_str = i18n("Sat");
321 break;
322 case Su:
323 weekday_str = i18n("Sun");
324 break;
325 default:
326 break;
12963590 327 } //lint !e788: Don't complain about unused _WeekDay_END
0c7e72d7
TJ
328
329 return weekday_str;
330}
331
332/**
333 * Convert WeekDay to readable string without i18n
334 * @param day WeekDay to convert
335 * @return WeekDay as string in English
336 */
337std::string Week::get_english_display(WeekDay day)
338{
339 string weekday_str;
340
12963590
TJ
341 switch (day)
342 {
0c7e72d7
TJ
343 case Mo:
344 weekday_str = "Mon";
345 break;
346 case Tu:
347 weekday_str = "Tue";
348 break;
349 case We:
350 weekday_str = "Wed";
351 break;
352 case Th:
353 weekday_str = "Thu";
354 break;
355 case Fr:
356 weekday_str = "Fri";
357 break;
358 case Sa:
359 weekday_str = "Sat";
360 break;
361 case Su:
362 weekday_str = "Sun";
363 break;
364 default:
365 break;
12963590 366 } //lint !e788: Don't complain about unused _WeekDay_END
0c7e72d7
TJ
367
368 return weekday_str;
369}
370
371}
372}