18a74396f5194079f782c0ed944cb6b8d509e906
[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 <assert.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38
39 #ifdef ICAL_NO_LIBICAL
40 #define icalerror_set_errno(x)
41 #define  icalerror_check_arg_rv(x,y)
42 #define  icalerror_check_arg_re(x,y,z)
43 #else
44 #include "icalerror.h"
45 #include "icalmemory.h"
46 #endif
47
48
49
50
51 /* From Seth Alves,  <alves@hungry.com>   */
52 struct icaldurationtype icaldurationtype_from_int(int t)
53 {
54         struct icaldurationtype dur;
55         int used = 0;
56
57         dur = icaldurationtype_null_duration();
58
59         if(t < 0){
60             dur.is_neg = 1;
61             t = -t;
62         }
63
64         dur.weeks = (t - used) / (60 * 60 * 24 * 7);
65         used += dur.weeks * (60 * 60 * 24 * 7);
66         dur.days = (t - used) / (60 * 60 * 24);
67         used += dur.days * (60 * 60 * 24);
68         dur.hours = (t - used) / (60 * 60);
69         used += dur.hours * (60 * 60);
70         dur.minutes = (t - used) / (60);
71         used += dur.minutes * (60);
72         dur.seconds = (t - used);
73  
74         return dur;
75 }
76
77 #ifndef ICAL_NO_LIBICAL
78 #include "icalvalue.h"
79 struct icaldurationtype icaldurationtype_from_string(const char* str)
80 {
81
82     int i;
83     int begin_flag = 0;
84     int time_flag = 0;
85     int date_flag = 0;
86     int week_flag = 0;
87     int digits=-1;
88     int scan_size = -1;
89     int size = strlen(str);
90     char p;
91     struct icaldurationtype d;
92
93     memset(&d, 0, sizeof(struct icaldurationtype));
94
95     for(i=0;i != size;i++){
96         p = str[i];
97         
98         switch(p) 
99             {
100             case '-': {
101                 if(i != 0 || begin_flag == 1) goto error;
102
103                 d.is_neg = 1;
104                 break;
105             }
106
107             case 'P': {
108                 if (i != 0 && i !=1 ) goto error;
109                 begin_flag = 1;
110                 break;
111             }
112
113             case 'T': {
114                 time_flag = 1;
115                 break;
116             }
117
118             case '0':
119             case '1':
120             case '2':
121             case '3':
122             case '4':
123             case '5':
124             case '6':
125             case '7':
126             case '8':
127             case '9':
128                 { 
129                     
130                     /* HACK. Skip any more digits if the l;ast one
131                        read has not been assigned */
132                     if(digits != -1){
133                         break;
134                     }
135
136                     if (begin_flag == 0) goto error;
137                     /* Get all of the digits, not one at a time */
138                     scan_size = sscanf((char*)(str+i),"%d",&digits);
139                     if(scan_size == 0) goto error;
140                     break;
141                 }
142
143             case 'H': { 
144                 if (time_flag == 0||week_flag == 1||d.hours !=0||digits ==-1) 
145                     goto error;
146                 d.hours = digits; digits = -1;
147                 break;
148             }
149             case 'M': {
150                 if (time_flag == 0||week_flag==1||d.minutes != 0||digits ==-1) 
151                     goto error;
152                 d.minutes = digits; digits = -1;            
153                 break;
154             }
155             case 'S': {
156                 if (time_flag == 0||week_flag==1||d.seconds!=0||digits ==-1) 
157                     goto error;
158                 d.seconds = digits; digits = -1;            
159                 break;
160             }
161             case 'W': {
162                 if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1) 
163                     goto error;
164                 week_flag = 1;  
165                 d.weeks = digits; digits = -1;      
166                 break;
167             }
168             case 'D': {
169                 if (time_flag==1||week_flag==1||d.days!=0||digits ==-1) 
170                     goto error;
171                 date_flag = 1;
172                 d.days = digits; digits = -1;       
173                 break;
174             }
175             default: {
176                 goto error;
177             }
178
179             }
180     }
181
182     return d;
183         
184
185  error:
186     icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
187     memset(&d, 0, sizeof(struct icaldurationtype));
188     return d;
189
190 }
191
192 #define TMP_BUF_SIZE 1024
193 void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size, 
194                              char* sep, unsigned int value) {
195
196     char temp[TMP_BUF_SIZE];
197
198     sprintf(temp,"%d",value);
199
200     icalmemory_append_string(buf, buf_ptr, buf_size, temp);
201     icalmemory_append_string(buf, buf_ptr, buf_size, sep);
202     
203 }
204
205 char* icaldurationtype_as_ical_string(struct icaldurationtype d) 
206 {
207
208     char *buf, *output_line;
209     size_t buf_size = 256;
210     char* buf_ptr = 0;
211     int seconds;
212
213     buf = (char*)icalmemory_new_buffer(buf_size);
214     buf_ptr = buf;
215     
216
217     seconds = icaldurationtype_as_int(d);
218
219     if(seconds !=0){
220         
221         if(d.is_neg == 1){
222             icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-'); 
223         }
224
225         icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P');
226     
227         if (d.weeks != 0 ) {
228             append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks);
229         }
230         
231         if (d.days != 0 ) {
232             append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days);
233         }
234         
235         if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) {
236             
237             icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T");
238             
239             if (d.hours != 0 ) {
240                 append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours);
241             }
242             if (d.minutes != 0 ) {
243                 append_duration_segment(&buf, &buf_ptr, &buf_size, "M", 
244                                         d.minutes);
245             }
246             if (d.seconds != 0 ) {
247                 append_duration_segment(&buf, &buf_ptr, &buf_size, "S", 
248                                         d.seconds);
249             }
250             
251         }
252     } else {
253         icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PTS0");
254     }
255  
256     output_line = icalmemory_tmp_copy(buf);
257     icalmemory_free_buffer(buf);
258
259     return output_line;
260     
261 }
262
263 #endif
264
265
266 /* From Russel Steinthal */
267 int icaldurationtype_as_int(struct icaldurationtype dur)
268 {
269     return (int)( (dur.seconds +
270                    (60 * dur.minutes) +
271                    (60 * 60 * dur.hours) +
272                    (60 * 60 * 24 * dur.days) +
273                    (60 * 60 * 24 * 7 * dur.weeks))
274                   * (dur.is_neg==1? -1 : 1) ) ;
275
276
277 struct icaldurationtype icaldurationtype_null_duration()
278 {
279     struct icaldurationtype d;
280     
281     memset(&d,0,sizeof(struct icaldurationtype));
282     
283     return d;
284 }
285
286 int icaldurationtype_is_null_duration(struct icaldurationtype d)
287 {
288     if(icaldurationtype_as_int(d) == 0){
289         return 1;
290     } else {
291         return 0;
292     }
293 }
294
295
296
297 struct icaltimetype  icaltime_add(struct icaltimetype t,
298                                   struct icaldurationtype  d)
299 {
300     int dt = icaldurationtype_as_int(d);
301     
302     t.second += dt;
303     
304     t = icaltime_normalize(t);
305     
306     return t;
307 }
308
309 struct icaldurationtype  icaltime_subtract(struct icaltimetype t1,
310                                            struct icaltimetype t2)
311 {
312
313     time_t t1t = icaltime_as_timet(t1);
314     time_t t2t = icaltime_as_timet(t2);
315
316     return icaldurationtype_from_int(t1t-t2t);
317
318
319 }
320