1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "calDuration.h"
7 #include "calBaseCID.h"
8
9 #include "nsComponentManagerUtils.h"
10 #include "nsServiceManagerUtils.h"
11
12 #include "nsIClassInfoImpl.h"
13
14 #include "calUtils.h"
15
16 #define SECONDS_PER_WEEK 604800
17 #define SECONDS_PER_DAY 86400
18 #define SECONDS_PER_HOUR 3600
19 #define SECONDS_PER_MINUTE 60
20
21 NS_IMPL_CLASSINFO(calDuration, nullptr, 0, CAL_DURATION_CID)
NS_IMPL_ISUPPORTS_CI(calDuration,calIDuration,calIDurationLibical)22 NS_IMPL_ISUPPORTS_CI(calDuration, calIDuration, calIDurationLibical)
23
24 calDuration::calDuration() : mImmutable(false) { Reset(); }
25
calDuration(const calDuration & cdt)26 calDuration::calDuration(const calDuration& cdt) {
27 mDuration.is_neg = cdt.mDuration.is_neg;
28 mDuration.weeks = cdt.mDuration.weeks;
29 mDuration.days = cdt.mDuration.days;
30 mDuration.hours = cdt.mDuration.hours;
31 mDuration.minutes = cdt.mDuration.minutes;
32 mDuration.seconds = cdt.mDuration.seconds;
33
34 // copies are always mutable
35 mImmutable = false;
36 }
37
calDuration(const struct icaldurationtype * const aDurationPtr)38 calDuration::calDuration(const struct icaldurationtype* const aDurationPtr)
39 : mImmutable(false) {
40 FromIcalDuration(aDurationPtr);
41 }
42
43 NS_IMETHODIMP
GetIcalDuration(JS::MutableHandleValue)44 calDuration::GetIcalDuration(JS::MutableHandleValue) {
45 return NS_ERROR_NOT_IMPLEMENTED;
46 }
47
48 NS_IMETHODIMP
SetIcalDuration(JS::HandleValue)49 calDuration::SetIcalDuration(JS::HandleValue) {
50 return NS_ERROR_NOT_IMPLEMENTED;
51 }
52
53 NS_IMETHODIMP
GetIsMutable(bool * aResult)54 calDuration::GetIsMutable(bool* aResult) {
55 NS_ENSURE_ARG_POINTER(aResult);
56
57 *aResult = !mImmutable;
58 return NS_OK;
59 }
60
61 NS_IMETHODIMP
MakeImmutable()62 calDuration::MakeImmutable() {
63 mImmutable = true;
64 return NS_OK;
65 }
66
67 NS_IMETHODIMP
Clone(calIDuration ** aResult)68 calDuration::Clone(calIDuration** aResult) {
69 calDuration* cdt = new calDuration(*this);
70 if (!cdt) return NS_ERROR_OUT_OF_MEMORY;
71
72 NS_ADDREF(*aResult = cdt);
73 return NS_OK;
74 }
75
76 NS_IMETHODIMP
Reset()77 calDuration::Reset() {
78 if (mImmutable) return NS_ERROR_FAILURE;
79
80 mDuration.is_neg = 0;
81 mDuration.weeks = 0;
82 mDuration.days = 0;
83 mDuration.hours = 0;
84 mDuration.minutes = 0;
85 mDuration.seconds = 0;
86
87 return NS_OK;
88 }
89
GetIsNegative(bool * _retval)90 NS_IMETHODIMP calDuration::GetIsNegative(bool* _retval) {
91 *_retval = mDuration.is_neg;
92 return NS_OK;
93 }
SetIsNegative(bool aValue)94 NS_IMETHODIMP calDuration::SetIsNegative(bool aValue) {
95 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
96 mDuration.is_neg = aValue;
97 return NS_OK;
98 }
99
GetWeeks(int16_t * _retval)100 NS_IMETHODIMP calDuration::GetWeeks(int16_t* _retval) {
101 *_retval = (int16_t)mDuration.weeks;
102 return NS_OK;
103 }
SetWeeks(int16_t aValue)104 NS_IMETHODIMP calDuration::SetWeeks(int16_t aValue) {
105 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
106 mDuration.weeks = aValue;
107 return NS_OK;
108 }
109
GetDays(int16_t * _retval)110 NS_IMETHODIMP calDuration::GetDays(int16_t* _retval) {
111 *_retval = (int16_t)mDuration.days;
112 return NS_OK;
113 }
SetDays(int16_t aValue)114 NS_IMETHODIMP calDuration::SetDays(int16_t aValue) {
115 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
116 mDuration.days = aValue;
117 return NS_OK;
118 }
119
GetHours(int16_t * _retval)120 NS_IMETHODIMP calDuration::GetHours(int16_t* _retval) {
121 *_retval = (int16_t)mDuration.hours;
122 return NS_OK;
123 }
SetHours(int16_t aValue)124 NS_IMETHODIMP calDuration::SetHours(int16_t aValue) {
125 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
126 mDuration.hours = aValue;
127 return NS_OK;
128 }
129
GetMinutes(int16_t * _retval)130 NS_IMETHODIMP calDuration::GetMinutes(int16_t* _retval) {
131 *_retval = (int16_t)mDuration.minutes;
132 return NS_OK;
133 }
SetMinutes(int16_t aValue)134 NS_IMETHODIMP calDuration::SetMinutes(int16_t aValue) {
135 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
136 mDuration.minutes = aValue;
137 return NS_OK;
138 }
139
GetSeconds(int16_t * _retval)140 NS_IMETHODIMP calDuration::GetSeconds(int16_t* _retval) {
141 *_retval = (int16_t)mDuration.seconds;
142 return NS_OK;
143 }
SetSeconds(int16_t aValue)144 NS_IMETHODIMP calDuration::SetSeconds(int16_t aValue) {
145 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
146 mDuration.seconds = aValue;
147 return NS_OK;
148 }
149
GetInSeconds(int32_t * _retval)150 NS_IMETHODIMP calDuration::GetInSeconds(int32_t* _retval) {
151 int32_t retval =
152 (((int32_t)((int16_t)mDuration.weeks * SECONDS_PER_WEEK)) +
153 ((int32_t)((int16_t)mDuration.days * SECONDS_PER_DAY)) +
154 ((int32_t)((int16_t)mDuration.hours * SECONDS_PER_HOUR)) +
155 ((int32_t)((int16_t)mDuration.minutes * SECONDS_PER_MINUTE)) +
156 ((int32_t)((int16_t)mDuration.seconds)));
157 if (mDuration.is_neg) retval = -retval;
158 *_retval = retval;
159
160 return NS_OK;
161 }
SetInSeconds(int32_t aValue)162 NS_IMETHODIMP calDuration::SetInSeconds(int32_t aValue) {
163 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
164
165 mDuration.is_neg = (aValue < 0);
166 if (mDuration.is_neg) aValue = -aValue;
167
168 // set weeks exOR days/hours/...
169 mDuration.weeks =
170 ((aValue % SECONDS_PER_WEEK) == 0 ? aValue / SECONDS_PER_WEEK : 0);
171 aValue -= (mDuration.weeks * SECONDS_PER_WEEK);
172
173 mDuration.days = aValue / SECONDS_PER_DAY;
174 aValue -= (mDuration.days * SECONDS_PER_DAY);
175
176 mDuration.hours = aValue / SECONDS_PER_HOUR;
177 aValue -= (mDuration.hours * SECONDS_PER_HOUR);
178
179 mDuration.minutes = aValue / SECONDS_PER_MINUTE;
180 aValue -= (mDuration.minutes * SECONDS_PER_MINUTE);
181
182 mDuration.seconds = aValue;
183
184 return NS_OK;
185 }
186
AddDuration(calIDuration * aDuration)187 NS_IMETHODIMP calDuration::AddDuration(calIDuration* aDuration) {
188 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
189
190 nsresult rv;
191 nsCOMPtr<calIDurationLibical> icaldur = do_QueryInterface(aDuration, &rv);
192 NS_ENSURE_SUCCESS(rv, rv);
193
194 struct icaldurationtype idt;
195 icaldur->ToIcalDuration(&idt);
196
197 // Calculate the new absolute value of the duration
198 // For two negative durations, the abs. value will increase,
199 // so use + in that case.
200 // Of course, also use + when both durations are positive.
201 if (idt.is_neg == mDuration.is_neg) {
202 mDuration.weeks += idt.weeks;
203 mDuration.days += idt.days;
204 mDuration.hours += idt.hours;
205 mDuration.minutes += idt.minutes;
206 mDuration.seconds += idt.seconds;
207 } else {
208 mDuration.weeks -= idt.weeks;
209 mDuration.days -= idt.days;
210 mDuration.hours -= idt.hours;
211 mDuration.minutes -= idt.minutes;
212 mDuration.seconds -= idt.seconds;
213 }
214
215 Normalize();
216
217 return NS_OK;
218 }
219
220 NS_IMETHODIMP
Normalize()221 calDuration::Normalize() {
222 if (mImmutable) return NS_ERROR_CALENDAR_IMMUTABLE;
223
224 int32_t totalInSeconds;
225 GetInSeconds(&totalInSeconds);
226 SetInSeconds(totalInSeconds);
227
228 return NS_OK;
229 }
230
231 NS_IMETHODIMP
ToString(nsACString & aResult)232 calDuration::ToString(nsACString& aResult) { return GetIcalString(aResult); }
233
NS_IMETHODIMP_(void)234 NS_IMETHODIMP_(void)
235 calDuration::ToIcalDuration(struct icaldurationtype* icald) {
236 icald->is_neg = mDuration.is_neg;
237 icald->weeks = mDuration.weeks;
238 icald->days = mDuration.days;
239 icald->hours = mDuration.hours;
240 icald->minutes = mDuration.minutes;
241 icald->seconds = mDuration.seconds;
242 return;
243 }
244
FromIcalDuration(const struct icaldurationtype * const icald)245 void calDuration::FromIcalDuration(const struct icaldurationtype* const icald) {
246 mDuration.is_neg = icald->is_neg;
247 mDuration.weeks = icald->weeks;
248 mDuration.days = icald->days;
249 mDuration.hours = icald->hours;
250 mDuration.minutes = icald->minutes;
251 mDuration.seconds = icald->seconds;
252 return;
253 }
254
255 NS_IMETHODIMP
GetIcalString(nsACString & aResult)256 calDuration::GetIcalString(nsACString& aResult) {
257 // note that ics is owned by libical, so we don't need to free
258 const char* ics = icaldurationtype_as_ical_string(mDuration);
259
260 if (ics) {
261 aResult.Assign(ics);
262 return NS_OK;
263 }
264
265 return NS_ERROR_OUT_OF_MEMORY;
266 }
267
268 NS_IMETHODIMP
SetIcalString(const nsACString & aIcalString)269 calDuration::SetIcalString(const nsACString& aIcalString) {
270 mDuration =
271 icaldurationtype_from_string(PromiseFlatCString(aIcalString).get());
272 return NS_OK;
273 }
274
275 NS_IMETHODIMP
Compare(calIDuration * aOther,int32_t * aResult)276 calDuration::Compare(calIDuration* aOther, int32_t* aResult) {
277 int32_t thisInSeconds, otherInSeconds;
278
279 // cast to void because these calls can't fail
280 (void)GetInSeconds(&thisInSeconds);
281 (void)aOther->GetInSeconds(&otherInSeconds);
282
283 if (thisInSeconds < otherInSeconds) {
284 *aResult = -1;
285 } else if (thisInSeconds > otherInSeconds) {
286 *aResult = 1;
287 } else {
288 *aResult = 0;
289 }
290
291 return NS_OK;
292 }
293