356809f22ead5d62f673dd08796d917c05d046db
[claws.git] / src / plugins / vcalendar / libical / libical / icalduration.c
1 /* -*- Mode: C -*-
2   ======================================================================
3   FILE: icaltime.c
4   CREATOR: eric 02 June 2000
5   
6   $Id$
7   $Locker$
8     
9  (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
10
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of either: 
13
14     The LGPL as published by the Free Software Foundation, version
15     2.1, available at: http://www.fsf.org/copyleft/lesser.html
16
17   Or:
18
19     The Mozilla Public License Version 1.0. You may obtain a copy of
20     the License at http://www.mozilla.org/MPL/
21
22  The Original Code is eric. The Initial Developer of the Original
23  Code is Eric Busboom
24
25
26  ======================================================================*/
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include "icalduration.h"
33
34 #include <glib.h>
35
36 #include <assert.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40
41 #ifdef ICAL_NO_LIBICAL
42 #define icalerror_set_errno(x)
43 #define  icalerror_check_arg_rv(x,y)
44 #define  icalerror_check_arg_re(x,y,z)
45 #else
46 #include "icalerror.h"
47 #include "icalmemory.h"
48 #endif
49
50
51
52
53 /* From Seth Alves,  <alves@hungry.com>   */
54 struct icaldurationtype icaldurationtype_from_int(int t)
55 {
56         struct icaldurationtype dur;
57         int used = 0;
58
59         dur = icaldurationtype_null_duration();
60
61         if(t < 0){
62             dur.is_neg = 1;
63             t = -t;
64         }
65
66         dur.weeks = (t - used) / (60 * 60 * 24 * 7);
67         used += dur.weeks * (60 * 60 * 24 * 7);
68         dur.days = (t - used) / (60 * 60 * 24);
69         used += dur.days * (60 * 60 * 24);
70         dur.hours = (t - used) / (60 * 60);
71         used += dur.hours * (60 * 60);
72         dur.minutes = (t - used) / (60);
73         used += dur.minutes * (60);
74         dur.seconds = (t - used);
75  
76         return dur;
77 }
78
79 #ifndef ICAL_NO_LIBICAL
80 #include "icalvalue.h"
81 struct icaldurationtype icaldurationtype_from_string(const char* str)
82 {
83
84     int i;
85     int begin_flag = 0;
86     int time_flag = 0;
87     int date_flag = 0;
88     int week_flag = 0;
89     int digits=-1;
90     int scan_size = -1;
91     int size = strlen(str);
92     char p;
93     struct icaldurationtype d;
94
95     memset(&d, 0, sizeof(struct icaldurationtype));
96
97     for(i=0;i != size;i++){
98         p = str[i];
99         
100         switch(p) 
101             {
102             case '-': {
103                 if(i != 0 || begin_flag == 1) goto error;
104
105                 d.is_neg = 1;
106                 break;
107             }
108
109             case 'P': {
110                 if (i != 0 && i !=1 ) goto error;
111                 begin_flag = 1;
112                 break;
113             }
114
115             case 'T': {
116                 time_flag = 1;
117                 break;
118             }
119
120             case '0':
121             case '1':
122             case '2':
123             case '3':
124             case '4':
125             case '5':
126             case '6':
127             case '7':
128             case '8':
129             case '9':
130                 { 
131                     
132                     /* HACK. Skip any more digits if the l;ast one
133                        read has not been assigned */
134                     if(digits != -1){
135                         break;
136                     }
137
138                     if (begin_flag == 0) goto error;
139                     /* Get all of the digits, not one at a time */
140                     scan_size = sscanf((char*)(str+i),"%d",&digits);
141                     if(scan_size == 0) goto error;
142                     break;
143                 }
144
145             case 'H': { 
146                 if (time_flag == 0||week_flag == 1||d.hours !=0||digits ==-1) 
147                     goto error;
148                 d.hours = digits; digits = -1;
149                 break;
150             }
151             case 'M': {
152                 if (time_flag == 0||week_flag==1||d.minutes != 0||digits ==-1) 
153                     goto error;
154                 d.minutes = digits; digits = -1;            
155                 break;
156             }
157             case 'S': {
158                 if (time_flag == 0||week_flag==1||d.seconds!=0||digits ==-1) 
159                     goto error;
160                 d.seconds = digits; digits = -1;            
161                 break;
162             }
163             case 'W': {
164                 if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1) 
165                     goto error;
166                 week_flag = 1;  
167                 d.weeks = digits; digits = -1;      
168                 break;
169             }
170             case 'D': {
171                 if (time_flag==1||week_flag==1||d.days!=0||digits ==-1) 
172                     goto error;
173                 date_flag = 1;
174                 d.days = digits; digits = -1;       
175                 break;
176             }
177             default: {
178                 goto error;
179             }
180
181             }
182     }
183
184     return d;
185         
186
187  error:
188     icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
189     memset(&d, 0, sizeof(struct icaldurationtype));
190     return d;
191
192 }
193
194 #define TMP_BUF_SIZE 1024
195 void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size, 
196                              char* sep, unsigned int value) {
197
198     char temp[TMP_BUF_SIZE];
199
200     sprintf(temp,"%d",value);
201
202     icalmemory_append_string(buf, buf_ptr, buf_size, temp);
203     icalmemory_append_string(buf, buf_ptr, buf_size, sep);
204     
205 }
206
207 char* icaldurationtype_as_ical_string(struct icaldurationtype d) 
208 {
209
210     char *buf, *output_line;
211     size_t buf_size = 256;
212     char* buf_ptr = 0;
213     int seconds;
214
215     buf = (char*)icalmemory_new_buffer(buf_size);
216     buf_ptr = buf;
217     
218
219     seconds = icaldurationtype_as_int(d);
220
221     if(seconds !=0){
222         
223         if(d.is_neg == 1){
224             icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-'); 
225         }
226
227         icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P');
228     
229         if (d.weeks != 0 ) {
230             append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks);
231         }
232         
233         if (d.days != 0 ) {
234             append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days);
235         }
236         
237         if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) {
238             
239             icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T");
240             
241             if (d.hours != 0 ) {
242                 append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours);
243             }
244             if (d.minutes != 0 ) {
245                 append_duration_segment(&buf, &buf_ptr, &buf_size, "M", 
246                                         d.minutes);
247             }
248             if (d.seconds != 0 ) {
249                 append_duration_segment(&buf, &buf_ptr, &buf_size, "S", 
250                                         d.seconds);
251             }
252             
253         }
254     } else {
255         icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PTS0");
256     }
257  
258     output_line = icalmemory_tmp_copy(buf);
259     icalmemory_free_buffer(buf);
260
261     return output_line;
262     
263 }
264
265 #endif
266
267
268 /* From Russel Steinthal */
269 int icaldurationtype_as_int(struct icaldurationtype dur)
270 {
271     return (int)( (dur.seconds +
272                    (60 * dur.minutes) +
273                    (60 * 60 * dur.hours) +
274                    (60 * 60 * 24 * dur.days) +
275                    (60 * 60 * 24 * 7 * dur.weeks))
276                   * (dur.is_neg==1? -1 : 1) ) ;
277
278
279 struct icaldurationtype icaldurationtype_null_duration()
280 {
281     struct icaldurationtype d;
282     
283     memset(&d,0,sizeof(struct icaldurationtype));
284     
285     return d;
286 }
287
288 int icaldurationtype_is_null_duration(struct icaldurationtype d)
289 {
290     if(icaldurationtype_as_int(d) == 0){
291         return 1;
292     } else {
293         return 0;
294     }
295 }
296
297
298
299 struct icaltimetype  icaltime_add(struct icaltimetype t,
300                                   struct icaldurationtype  d)
301 {
302     int dt = icaldurationtype_as_int(d);
303     
304 #ifdef G_OS_WIN32
305         GTimeZone *zone;
306         GDateTime *dtm;
307
308         if (t.is_utc == 1)
309                 zone = g_time_zone_new_utc();
310         else
311                 zone = g_time_zone_new_local();
312
313         dtm = g_date_time_new(
314                                 zone,
315                                 t.year,
316                                 t.month,
317                                 t.day,
318                                 t.hour,
319                                 t.minute,
320                                 t.second);
321
322         GDateTime *d2 = g_date_time_add_seconds(dtm, dt);
323
324         t.year = g_date_time_get_year(d2);
325         t.month = g_date_time_get_month(d2);
326         t.day = g_date_time_get_day_of_month(d2);
327         t.hour = g_date_time_get_hour(d2);
328         t.minute = g_date_time_get_minute(d2);
329         t.second = g_date_time_get_second(d2);
330
331         g_date_time_unref(dtm);
332         g_date_time_unref(d2);
333         g_time_zone_unref(zone);
334 #else
335     t.second += dt;
336     
337     t = icaltime_normalize(t);
338 #endif
339
340     return t;
341 }
342
343 struct icaldurationtype  icaltime_subtract(struct icaltimetype t1,
344                                            struct icaltimetype t2)
345 {
346
347     time_t t1t = icaltime_as_timet(t1);
348     time_t t2t = icaltime_as_timet(t2);
349
350     return icaldurationtype_from_int(t1t-t2t);
351
352
353 }
354