Back to index

lightning-sunbird  0.9+nobinonly
icalduration.c
Go to the documentation of this file.
00001 /* -*- Mode: C -*-
00002   ======================================================================
00003   FILE: icaltime.c
00004   CREATOR: eric 02 June 2000
00005   
00006   $Id: icalduration.c,v 1.19 2005/02/15 17:38:58 acampi Exp $
00007   $Locker:  $
00008     
00009  (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
00010 
00011  This program is free software; you can redistribute it and/or modify
00012  it under the terms of either: 
00013 
00014     The LGPL as published by the Free Software Foundation, version
00015     2.1, available at: http://www.fsf.org/copyleft/lesser.html
00016 
00017   Or:
00018 
00019     The Mozilla Public License Version 1.0. You may obtain a copy of
00020     the License at http://www.mozilla.org/MPL/
00021 
00022  The Original Code is eric. The Initial Developer of the Original
00023  Code is Eric Busboom
00024 
00025 
00026  ======================================================================*/
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include "icalduration.h"
00033 
00034 #include <assert.h>
00035 #include <string.h>
00036 #include <stdlib.h>
00037 #include <stdio.h>
00038 
00039 #include "icalerror.h"
00040 #include "icalmemory.h"
00041 #include "icalvalue.h"
00042 
00043 #ifdef WIN32
00044 #define snprintf _snprintf
00045 #endif
00046 
00047 
00048 /* From Seth Alves,  <alves@hungry.com>   */
00049 struct icaldurationtype icaldurationtype_from_int(int t)
00050 {
00051     struct icaldurationtype dur;
00052     int used = 0;
00053 
00054     dur = icaldurationtype_null_duration();
00055 
00056     if(t < 0){
00057        dur.is_neg = 1;
00058        t = -t;
00059     }
00060 
00061     if (t % (60 * 60 * 24 * 7) == 0) {
00062        dur.weeks = t / (60 * 60 * 24 * 7);
00063     } else {
00064        used += dur.weeks * (60 * 60 * 24 * 7);
00065        dur.days = (t - used) / (60 * 60 * 24);
00066        used += dur.days * (60 * 60 * 24);
00067        dur.hours = (t - used) / (60 * 60);
00068        used += dur.hours * (60 * 60);
00069        dur.minutes = (t - used) / (60);
00070        used += dur.minutes * (60);
00071        dur.seconds = (t - used);
00072     }
00073  
00074     return dur;
00075 }
00076 
00077 struct icaldurationtype icaldurationtype_from_string(const char* str)
00078 {
00079 
00080     int i;
00081     int begin_flag = 0;
00082     int time_flag = 0;
00083     int date_flag = 0;
00084     int week_flag = 0;
00085     int digits=-1;
00086     int scan_size = -1;
00087     int size = strlen(str);
00088     char p;
00089     struct icaldurationtype d;
00090 
00091     memset(&d, 0, sizeof(struct icaldurationtype));
00092 
00093     for(i=0;i != size;i++){
00094        p = str[i];
00095        
00096        switch(p) 
00097            {
00098            case '-': {
00099               if(i != 0 || begin_flag == 1) goto error;
00100 
00101               d.is_neg = 1;
00102               break;
00103            }
00104 
00105            case 'P': {
00106               if (i != 0 && i !=1 ) goto error;
00107               begin_flag = 1;
00108               break;
00109            }
00110 
00111            case 'T': {
00112               time_flag = 1;
00113               break;
00114            }
00115 
00116            case '0':
00117            case '1':
00118            case '2':
00119            case '3':
00120            case '4':
00121            case '5':
00122            case '6':
00123            case '7':
00124            case '8':
00125            case '9':
00126               { 
00127                   
00128                   /* HACK. Skip any more digits if the l;ast one
00129                        read has not been assigned */
00130                   if(digits != -1){
00131                      break;
00132                   }
00133 
00134                   if (begin_flag == 0) goto error;
00135                   /* Get all of the digits, not one at a time */
00136                   scan_size = sscanf(&str[i],"%d",&digits);
00137                   if(scan_size == 0) goto error;
00138                   break;
00139               }
00140 
00141            case 'H': {      
00142               if (time_flag == 0||week_flag == 1||d.hours !=0||digits ==-1) 
00143                   goto error;
00144               d.hours = digits; digits = -1;
00145               break;
00146            }
00147            case 'M': {
00148               if (time_flag == 0||week_flag==1||d.minutes != 0||digits ==-1) 
00149                   goto error;
00150               d.minutes = digits; digits = -1;       
00151               break;
00152            }
00153            case 'S': {
00154               if (time_flag == 0||week_flag==1||d.seconds!=0||digits ==-1) 
00155                   goto error;
00156               d.seconds = digits; digits = -1;       
00157               break;
00158            }
00159            case 'W': {
00160               if (time_flag==1||date_flag==1||d.weeks!=0||digits ==-1) 
00161                   goto error;
00162               week_flag = 1;       
00163               d.weeks = digits; digits = -1;         
00164               break;
00165            }
00166            case 'D': {
00167               if (time_flag==1||week_flag==1||d.days!=0||digits ==-1) 
00168                   goto error;
00169               date_flag = 1;
00170               d.days = digits; digits = -1;          
00171               break;
00172            }
00173            default: {
00174               goto error;
00175            }
00176 
00177            }
00178     }
00179 
00180     return d;
00181        
00182 
00183  error:
00184     icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
00185     return icaldurationtype_bad_duration();
00186 }
00187 
00188 static
00189 void append_duration_segment(char** buf, char** buf_ptr, size_t* buf_size, 
00190                           char* sep, unsigned int value) {
00191 
00192     char temp[32];
00193 
00194     snprintf(temp,sizeof(temp),"%d",value);
00195 
00196     icalmemory_append_string(buf, buf_ptr, buf_size, temp);
00197     icalmemory_append_string(buf, buf_ptr, buf_size, sep);
00198     
00199 }
00200 
00201 char* icaldurationtype_as_ical_string(struct icaldurationtype d) 
00202 {
00203 
00204     char *buf, *output_line;
00205     size_t buf_size = 256;
00206     char* buf_ptr = 0;
00207     int seconds;
00208 
00209     buf = (char*)icalmemory_new_buffer(buf_size);
00210     buf_ptr = buf;
00211     
00212 
00213     seconds = icaldurationtype_as_int(d);
00214 
00215     if(seconds !=0){
00216        
00217        if(d.is_neg == 1){
00218            icalmemory_append_char(&buf, &buf_ptr, &buf_size, '-'); 
00219        }
00220 
00221        icalmemory_append_char(&buf, &buf_ptr, &buf_size, 'P');
00222     
00223        if (d.weeks != 0 ) {
00224            append_duration_segment(&buf, &buf_ptr, &buf_size, "W", d.weeks);
00225        }
00226        
00227        if (d.days != 0 ) {
00228            append_duration_segment(&buf, &buf_ptr, &buf_size, "D", d.days);
00229        }
00230        
00231        if (d.hours != 0 || d.minutes != 0 || d.seconds != 0) {
00232            
00233            icalmemory_append_string(&buf, &buf_ptr, &buf_size, "T");
00234            
00235            if (d.hours != 0 ) {
00236               append_duration_segment(&buf, &buf_ptr, &buf_size, "H", d.hours);
00237            }
00238            if (d.minutes != 0 ) {
00239               append_duration_segment(&buf, &buf_ptr, &buf_size, "M", 
00240                                    d.minutes);
00241            }
00242            if (d.seconds != 0 ) {
00243               append_duration_segment(&buf, &buf_ptr, &buf_size, "S", 
00244                                    d.seconds);
00245            }
00246            
00247        }
00248     } else {
00249        icalmemory_append_string(&buf, &buf_ptr, &buf_size, "PT0S");
00250     }
00251  
00252     output_line = icalmemory_tmp_copy(buf);
00253     icalmemory_free_buffer(buf);
00254 
00255     return output_line;
00256     
00257 }
00258 
00259 
00260 /* From Russel Steinthal */
00261 int icaldurationtype_as_int(struct icaldurationtype dur)
00262 {
00263     return (int)( (dur.seconds +
00264                  (60 * dur.minutes) +
00265                  (60 * 60 * dur.hours) +
00266                  (60 * 60 * 24 * dur.days) +
00267                  (60 * 60 * 24 * 7 * dur.weeks))
00268                 * (dur.is_neg==1? -1 : 1) ) ;
00269 } 
00270 
00271 struct icaldurationtype icaldurationtype_null_duration(void)
00272 {
00273     struct icaldurationtype d;
00274     
00275     memset(&d,0,sizeof(struct icaldurationtype));
00276     
00277     return d;
00278 }
00279 
00280 int icaldurationtype_is_null_duration(struct icaldurationtype d)
00281 {
00282     if(icaldurationtype_as_int(d) == 0){
00283        return 1;
00284     } else {
00285        return 0;
00286     }
00287 }
00288 
00289 /* in icalvalue_new_from_string_with_error, we should not call
00290    icaldurationtype_is_null_duration() to see if there is an error
00291    condition. Null duration is perfectly valid for an alarm.
00292    We cannot depend on the caller to check icalerrno either,
00293    following the philosophy of unix errno. we set the is_neg
00294    to -1 to indicate that this is a bad duration.
00295 */
00296 struct icaldurationtype icaldurationtype_bad_duration()
00297 {
00298     struct icaldurationtype d;
00299     memset(&d,0,sizeof(struct icaldurationtype));
00300     d.is_neg = -1;
00301     return d;
00302 }
00303 
00304 int icaldurationtype_is_bad_duration(struct icaldurationtype d)
00305 {
00306     return (d.is_neg == -1);
00307 }
00308 
00309 
00310 struct icaltimetype  icaltime_add(struct icaltimetype t,
00311                               struct icaldurationtype  d)
00312 {
00313     if (!d.is_neg) {
00314         t.second += d.seconds;
00315         t.minute += d.minutes;
00316         t.hour += d.hours;
00317         t.day += d.days;
00318         t.day += d.weeks * 7;
00319     } else {
00320         t.second -= d.seconds;
00321         t.minute -= d.minutes;
00322         t.hour -= d.hours;
00323         t.day -= d.days;
00324         t.day -= d.weeks * 7;
00325     }
00326     
00327     t = icaltime_normalize(t);
00328     
00329     return t;
00330 }
00331 
00332 struct icaldurationtype  icaltime_subtract(struct icaltimetype t1,
00333                                       struct icaltimetype t2)
00334 {
00335 
00336     time_t t1t = icaltime_as_timet(t1);
00337     time_t t2t = icaltime_as_timet(t2);
00338 
00339     return icaldurationtype_from_int((int)(t1t-t2t));
00340 
00341 
00342 }
00343