cpl_time.c

Go to the documentation of this file.
00001 /*
00002  * $Id: cpl_time.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  *
00023  * History:
00024  * -------
00025  * 2003-06-24: file imported from tmrec (bogdan)
00026  * 2003-xx-xx: file Created (daniel)
00027  */
00028 
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <time.h>
00032 
00033 #include "../../mem/mem.h"
00034 #include "cpl_time.h"
00035 
00036 
00037 /************************ imported from "utils.h"  ***************************/
00038 
00039 static inline int strz2int(char *_bp)
00040 {
00041    int _v;
00042    char *_p;
00043    if(!_bp)
00044       return 0;
00045    _v = 0;
00046    _p = _bp;
00047    while(*_p && *_p>='0' && *_p<='9')
00048    {
00049       _v += *_p - '0';
00050       _p++;
00051    }
00052    return _v;
00053 }
00054 
00055 
00056 static inline char* trim(char* _s)
00057 {
00058    int len;
00059    char* end;
00060 
00061         /* Null pointer, there is nothing to do */
00062    if (!_s) return _s;
00063 
00064         /* Remove spaces and tabs from the beginning of string */
00065    while ((*_s == ' ') || (*_s == '\t')) _s++;
00066 
00067    len = strlen(_s);
00068 
00069         end = _s + len - 1;
00070 
00071         /* Remove trailing spaces and tabs */
00072    while ((*end == ' ') || (*end == '\t')) end--;
00073    if (end != (_s + len - 1)) {
00074       *(end+1) = '\0';
00075    }
00076 
00077    return _s;
00078 }
00079 
00080 
00081 
00082 
00083 /************************ imported from "ac_tm.c"  ***************************/
00084 
00085 /* #define USE_YWEEK_U     // Sunday system
00086  * #define USE_YWEEK_V     // ISO 8601
00087  */
00088 #ifndef USE_YWEEK_U
00089 #ifndef USE_YWEEK_V
00090 #ifndef USE_YWEEK_W
00091 #define USE_YWEEK_W     /* Monday system */.
00092 #endif
00093 #endif
00094 #endif
00095 
00096 #ifdef USE_YWEEK_U
00097 #define SUN_WEEK(t)  (int)(((t)->tm_yday + 7 - \
00098             ((t)->tm_wday)) / 7)
00099 #else
00100 #define MON_WEEK(t)  (int)(((t)->tm_yday + 7 - \
00101             ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
00102 #endif
00103 
00104 #define ac_get_wday_yr(t) (int)((t)->tm_yday/7)
00105 #define ac_get_wday_mr(t) (int)(((t)->tm_mday-1)/7)
00106 
00107 ac_tm_p ac_tm_new(void)
00108 {
00109    ac_tm_p _atp = NULL;
00110    _atp = (ac_tm_p)pkg_malloc(sizeof(ac_tm_t));
00111    if(!_atp)
00112       return NULL;
00113    memset(_atp, 0, sizeof(ac_tm_t));
00114    
00115    return _atp;
00116 }
00117 
00118 int ac_tm_fill(ac_tm_p _atp, struct tm* _tm)
00119 {
00120    if(!_atp || !_tm)
00121       return -1;
00122    _atp->t.tm_sec = _tm->tm_sec;       /* seconds */
00123    _atp->t.tm_min = _tm->tm_min;       /* minutes */
00124    _atp->t.tm_hour = _tm->tm_hour;     /* hours */
00125    _atp->t.tm_mday = _tm->tm_mday;     /* day of the month */
00126    _atp->t.tm_mon = _tm->tm_mon;       /* month */
00127    _atp->t.tm_year = _tm->tm_year;     /* year */
00128    _atp->t.tm_wday = _tm->tm_wday;     /* day of the week */
00129    _atp->t.tm_yday = _tm->tm_yday;     /* day in the year */
00130    _atp->t.tm_isdst = _tm->tm_isdst;   /* daylight saving time */
00131    
00132    _atp->mweek = ac_get_mweek(_tm);
00133    _atp->yweek = ac_get_yweek(_tm);
00134    _atp->ywday = ac_get_wday_yr(_tm);
00135    _atp->mwday = ac_get_wday_mr(_tm);
00136    return 0;
00137 }
00138 
00139 int ac_tm_set_time(ac_tm_p _atp, time_t _t)
00140 {
00141    if(!_atp)
00142       return -1;
00143    _atp->time = _t;
00144    return ac_tm_fill(_atp, localtime(&_t));
00145 }
00146 
00147 int ac_get_mweek(struct tm* _tm)
00148 {
00149    if(!_tm)
00150       return -1;
00151 #ifdef USE_YWEEK_U
00152    return ((_tm->tm_mday-1)/7 + (7-_tm->tm_wday+(_tm->tm_mday-1)%7)/7);
00153 #else
00154    return ((_tm->tm_mday-1)/7 + (7-(6+_tm->tm_wday)%7+(_tm->tm_mday-1)%7)/7);
00155 #endif
00156 }
00157 
00158 int ac_get_yweek(struct tm* _tm)
00159 {
00160    int week = -1;
00161 #ifdef USE_YWEEK_V
00162    int days;
00163 #endif
00164    
00165    if(!_tm)
00166       return -1;
00167    
00168 #ifdef USE_YWEEK_U
00169    week = SUN_WEEK(_tm);
00170 #else
00171    week = MON_WEEK(_tm);
00172 #endif
00173 
00174 #ifdef USE_YWEEK_V
00175    days = ((_tm->tm_yday + 7 - (_tm->tm_wday ? _tm->tm_wday-1 : 6)) % 7);
00176 
00177    if(days >= 4) 
00178       week++;
00179    else 
00180       if(week == 0) 
00181          week = 53;
00182 #endif
00183    return week;
00184 }
00185 
00186 int ac_get_wkst(void)
00187 {
00188 #ifdef USE_YWEEK_U
00189    return 0;
00190 #else
00191    return 1;
00192 #endif
00193 }
00194 
00195 int ac_tm_reset(ac_tm_p _atp)
00196 {
00197    if(!_atp)
00198       return -1;
00199    memset(_atp, 0, sizeof(ac_tm_t));
00200    return 0;
00201 }
00202 
00203 int ac_tm_free(ac_tm_p _atp)
00204 {
00205    if(!_atp)
00206       return -1;
00207    if(_atp->mv)
00208       pkg_free(_atp->mv);
00209    /*pkg_free(_atp);*/
00210    return 0;
00211 }
00212 
00213 ac_maxval_p ac_get_maxval(ac_tm_p _atp)
00214 {
00215    struct tm _tm;
00216    int _v;
00217    ac_maxval_p _amp = NULL;
00218 
00219    if(!_atp)
00220       return NULL;
00221    _amp = (ac_maxval_p)pkg_malloc(sizeof(ac_maxval_t));
00222    if(!_amp)
00223       return NULL;
00224    
00225    /* the number of the days in the year */
00226    _amp->yday = 365 + is_leap_year(_atp->t.tm_year+1900);
00227 
00228    /* the number of the days in the month */
00229    switch(_atp->t.tm_mon)
00230    {
00231       case 1:
00232          if(_amp->yday == 366)
00233             _amp->mday = 29;
00234          else
00235             _amp->mday = 28;
00236       break;
00237       case 3: case 5: case 8: case 10:
00238          _amp->mday = 30;
00239       break;
00240       default:
00241          _amp->mday = 31;
00242    }
00243    
00244    /* maximum occurrences of a week day in the year */
00245    memset(&_tm, 0, sizeof(struct tm));
00246    _tm.tm_year = _atp->t.tm_year;
00247    _tm.tm_mon = 11;
00248    _tm.tm_mday = 31;
00249    mktime(&_tm);
00250    _v = 0;
00251    if(_atp->t.tm_wday > _tm.tm_wday)
00252       _v = _atp->t.tm_wday - _tm.tm_wday + 1;
00253    else
00254       _v = _tm.tm_wday - _atp->t.tm_wday;
00255    _amp->ywday = (int)((_tm.tm_yday-_v)/7) + 1;
00256    
00257    /* maximum number of weeks in the year */
00258    _amp->yweek = ac_get_yweek(&_tm) + 1;
00259    
00260    /* maximum number of the week day in the month */
00261    _amp->mwday=(int)((_amp->mday-1-(_amp->mday-_atp->t.tm_mday)%7)/7)+1;
00262    
00263    /* maximum number of weeks in the month */
00264    _v = (_atp->t.tm_wday + (_amp->mday - _atp->t.tm_mday)%7)%7;
00265 #ifdef USE_YWEEK_U
00266    _amp->mweek = (int)((_amp->mday-1)/7+(7-_v+(_amp->mday-1)%7)/7)+1;
00267 #else
00268    _amp->mweek = (int)((_amp->mday-1)/7+(7-(6+_v)%7+(_amp->mday-1)%7)/7)+1;
00269 #endif
00270 
00271    _atp->mv = _amp;
00272    return _amp;
00273 }
00274 
00275 int ac_print(ac_tm_p _atp)
00276 {
00277    static char *_wdays[] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"}; 
00278    if(!_atp)
00279    {
00280       printf("\n(null)\n");
00281       return -1;
00282    }
00283    
00284    printf("\nSys time: %d\nTime: %02d:%02d:%02d\n", (int)_atp->time,
00285             _atp->t.tm_hour, _atp->t.tm_min, _atp->t.tm_sec);
00286    printf("Date: %s, %04d-%02d-%02d\n", _wdays[_atp->t.tm_wday],
00287             _atp->t.tm_year+1900, _atp->t.tm_mon+1, _atp->t.tm_mday);
00288    printf("Year day: %d\nYear week-day: %d\nYear week: %d\n", _atp->t.tm_yday,
00289          _atp->ywday, _atp->yweek);
00290    printf("Month week: %d\nMonth week-day: %d\n", _atp->mweek, _atp->mwday);
00291    if(_atp->mv)
00292    {
00293       printf("Max ydays: %d\nMax yweeks: %d\nMax yweekday: %d\n",
00294             _atp->mv->yday, _atp->mv->yweek, _atp->mv->ywday);;
00295       printf("Max mdays: %d\nMax mweeks: %d\nMax mweekday: %d\n",
00296             _atp->mv->mday, _atp->mv->mweek, _atp->mv->mwday);;
00297    }
00298    return 0;
00299 }
00300 
00301 
00302 
00303 
00304 
00305 /************************ imported from "tmrec.c"  ***************************/
00306 
00307 #define _D(c) ((c) -'0')
00308 
00309 tr_byxxx_p tr_byxxx_new(void)
00310 {
00311    tr_byxxx_p _bxp = NULL;
00312    _bxp = (tr_byxxx_p)pkg_malloc(sizeof(tr_byxxx_t));
00313    if(!_bxp)
00314       return NULL;
00315    memset(_bxp, 0, sizeof(tr_byxxx_t));
00316    return _bxp;
00317 }
00318 
00319 int tr_byxxx_init(tr_byxxx_p _bxp, int _nr)
00320 {
00321    if(!_bxp)
00322       return -1;
00323    _bxp->nr = _nr;
00324    _bxp->xxx = (int*)pkg_malloc(_nr*sizeof(int));
00325    if(!_bxp->xxx)
00326       return -1;
00327    _bxp->req = (int*)pkg_malloc(_nr*sizeof(int));
00328    if(!_bxp->req)
00329    {
00330       pkg_free(_bxp->xxx);
00331       return -1;
00332    }
00333    
00334    memset(_bxp->xxx, 0, _nr*sizeof(int));
00335    memset(_bxp->req, 0, _nr*sizeof(int));
00336    
00337    return 0;
00338 }
00339 
00340 
00341 int tr_byxxx_free(tr_byxxx_p _bxp)
00342 {
00343    if(!_bxp)
00344       return -1;
00345    if(_bxp->xxx)
00346       pkg_free(_bxp->xxx);
00347    if(_bxp->req)
00348       pkg_free(_bxp->req);
00349    pkg_free(_bxp);
00350    return 0;
00351 }
00352 
00353 tmrec_p tmrec_new(void)
00354 {
00355    tmrec_p _trp = NULL;
00356    _trp = (tmrec_p)pkg_malloc(sizeof(tmrec_t));
00357    if(!_trp)
00358       return NULL;
00359    memset(_trp, 0, sizeof(tmrec_t));
00360    localtime_r(&_trp->dtstart,&(_trp->ts));
00361    return _trp;
00362 }
00363 
00364 int tmrec_free(tmrec_p _trp)
00365 {
00366    if(!_trp)
00367       return -1;
00368    
00369    tr_byxxx_free(_trp->byday);
00370    tr_byxxx_free(_trp->bymday);
00371    tr_byxxx_free(_trp->byyday);
00372    tr_byxxx_free(_trp->bymonth);
00373    tr_byxxx_free(_trp->byweekno);
00374 
00375    /*pkg_free(_trp);*/
00376    return 0;
00377 }
00378 
00379 int tr_parse_dtstart(tmrec_p _trp, char *_in)
00380 {
00381    if(!_trp || !_in)
00382       return -1;
00383    _trp->dtstart = ic_parse_datetime(_in, &(_trp->ts));
00384    return (_trp->dtstart==0)?-1:0;
00385 }
00386 
00387 int tr_parse_dtend(tmrec_p _trp, char *_in)
00388 {
00389    struct tm _tm;
00390    if(!_trp || !_in)
00391       return -1;
00392    _trp->dtend = ic_parse_datetime(_in,&_tm);
00393    return (_trp->dtend==0)?-1:0;
00394 }
00395 
00396 int tr_parse_duration(tmrec_p _trp, char *_in)
00397 {
00398    if(!_trp || !_in)
00399       return -1;
00400    _trp->duration = ic_parse_duration(_in);
00401    return (_trp->duration==0)?-1:0;
00402 }
00403 
00404 int tr_parse_until(tmrec_p _trp, char *_in)
00405 {
00406    struct tm _tm;
00407    if(!_trp || !_in)
00408       return -1;
00409    _trp->until = ic_parse_datetime(_in, &_tm);
00410    return (_trp->until==0)?-1:0;
00411 }
00412 
00413 int tr_parse_freq(tmrec_p _trp, char *_in)
00414 {
00415    if(!_trp || !_in)
00416       return -1;
00417    if(!strcasecmp(_in, "daily"))
00418    {
00419       _trp->freq = FREQ_DAILY;
00420       return 0;
00421    }
00422    if(!strcasecmp(_in, "weekly"))
00423    {
00424       _trp->freq = FREQ_WEEKLY;
00425       return 0;
00426    }
00427    if(!strcasecmp(_in, "monthly"))
00428    {
00429       _trp->freq = FREQ_MONTHLY;
00430       return 0;
00431    }
00432    if(!strcasecmp(_in, "yearly"))
00433    {
00434       _trp->freq = FREQ_YEARLY;
00435       return 0;
00436    }
00437 
00438    _trp->freq = FREQ_NOFREQ;
00439    return 0;
00440 }
00441 
00442 int tr_parse_interval(tmrec_p _trp, char *_in)
00443 {
00444    if(!_trp || !_in)
00445       return -1;
00446    _trp->interval = strz2int(_in);
00447    return 0;
00448 }
00449 
00450 int tr_parse_byday(tmrec_p _trp, char *_in)
00451 {
00452    if(!_trp || !_in)
00453       return -1;
00454    _trp->byday = ic_parse_byday(_in); 
00455    return 0;
00456 }
00457 
00458 int tr_parse_bymday(tmrec_p _trp, char *_in)
00459 {
00460    if(!_trp || !_in)
00461       return -1;
00462    _trp->bymday = ic_parse_byxxx(_in); 
00463    return 0;
00464 }
00465 
00466 int tr_parse_byyday(tmrec_p _trp, char *_in)
00467 {
00468    if(!_trp || !_in)
00469       return -1;
00470    _trp->byyday = ic_parse_byxxx(_in); 
00471    return 0;
00472 }
00473 
00474 int tr_parse_bymonth(tmrec_p _trp, char *_in)
00475 {
00476    if(!_trp || !_in)
00477       return -1;
00478    _trp->bymonth = ic_parse_byxxx(_in); 
00479    return 0;
00480 }
00481 
00482 int tr_parse_byweekno(tmrec_p _trp, char *_in)
00483 {
00484    if(!_trp || !_in)
00485       return -1;
00486    _trp->byweekno = ic_parse_byxxx(_in); 
00487    return 0;
00488 }
00489 
00490 int tr_parse_wkst(tmrec_p _trp, char *_in)
00491 {
00492    if(!_trp || !_in)
00493       return -1;
00494    _trp->wkst = ic_parse_wkst(_in);
00495    return 0;
00496 }
00497 
00498 int tr_print(tmrec_p _trp)
00499 {
00500    static char *_wdays[] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"}; 
00501    int i;
00502    
00503    if(!_trp)
00504    {
00505       printf("\n(null)\n");
00506       return -1;
00507    }
00508    printf("Recurrence definition\n-- start time ---\n");
00509    printf("Sys time: %d\n", (int)_trp->dtstart);
00510    printf("Time: %02d:%02d:%02d\n", _trp->ts.tm_hour, 
00511             _trp->ts.tm_min, _trp->ts.tm_sec);
00512    printf("Date: %s, %04d-%02d-%02d\n", _wdays[_trp->ts.tm_wday],
00513             _trp->ts.tm_year+1900, _trp->ts.tm_mon+1, _trp->ts.tm_mday);
00514    printf("---\n");
00515    printf("End time: %d\n", (int)_trp->dtend);
00516    printf("Duration: %d\n", (int)_trp->duration);
00517    printf("Until: %d\n", (int)_trp->until);
00518    printf("Freq: %d\n", (int)_trp->freq);
00519    printf("Interval: %d\n", (int)_trp->interval);
00520    if(_trp->byday)
00521    {
00522       printf("Byday: ");
00523       for(i=0; i<_trp->byday->nr; i++)
00524          printf(" %d%s", _trp->byday->req[i], _wdays[_trp->byday->xxx[i]]);
00525       printf("\n");
00526    }
00527    if(_trp->bymday)
00528    {
00529       printf("Bymday: %d:", _trp->bymday->nr);
00530       for(i=0; i<_trp->bymday->nr; i++)
00531          printf(" %d", _trp->bymday->xxx[i]*_trp->bymday->req[i]);
00532       printf("\n");
00533    }
00534    if(_trp->byyday)
00535    {
00536       printf("Byyday:");
00537       for(i=0; i<_trp->byyday->nr; i++)
00538          printf(" %d", _trp->byyday->xxx[i]*_trp->byyday->req[i]);
00539       printf("\n");
00540    }
00541    if(_trp->bymonth)
00542    {
00543       printf("Bymonth: %d:", _trp->bymonth->nr);
00544       for(i=0; i< _trp->bymonth->nr; i++)
00545          printf(" %d", _trp->bymonth->xxx[i]*_trp->bymonth->req[i]);
00546       printf("\n");
00547    }
00548    if(_trp->byweekno)
00549    {
00550       printf("Byweekno: ");
00551       for(i=0; i<_trp->byweekno->nr; i++)
00552          printf(" %d", _trp->byweekno->xxx[i]*_trp->byweekno->req[i]);
00553       printf("\n");
00554    }
00555    printf("Weekstart: %d\n", _trp->wkst);
00556    return 0;
00557 }
00558 
00559 time_t ic_parse_datetime(char *_in, struct tm *_tm)
00560 {
00561    if(!_in || !_tm || strlen(_in)!=15)
00562       return 0;
00563    
00564    memset(_tm, 0, sizeof(struct tm));
00565    _tm->tm_year = _D(_in[0])*1000 + _D(_in[1])*100 
00566          + _D(_in[2])*10 + _D(_in[3]) - 1900;
00567    _tm->tm_mon = _D(_in[4])*10 + _D(_in[5]) - 1;
00568    _tm->tm_mday = _D(_in[6])*10 + _D(_in[7]);
00569    _tm->tm_hour = _D(_in[9])*10 + _D(_in[10]);
00570    _tm->tm_min = _D(_in[11])*10 + _D(_in[12]);
00571    _tm->tm_sec = _D(_in[13])*10 + _D(_in[14]);
00572    _tm->tm_isdst = -1 /*daylight*/;
00573    return mktime(_tm);
00574 }
00575 
00576 time_t ic_parse_duration(char *_in)
00577 {
00578    time_t _t, _ft;
00579    char *_p;
00580    int _fl;
00581    
00582    if(!_in || (*_in!='+' && *_in!='-' && *_in!='P' && *_in!='p'))
00583       return 0;
00584    
00585    if(*_in == 'P' || *_in=='p')
00586       _p = _in+1;
00587    else
00588    {
00589       if(strlen(_in)<2 || (_in[1]!='P' && _in[1]!='p'))
00590          return 0;
00591       _p = _in+2;
00592    }
00593    
00594    _t = _ft = 0;
00595    _fl = 1;
00596    
00597    while(*_p)
00598    {
00599       switch(*_p)
00600       {
00601          case '0': case '1': case '2':
00602          case '3': case '4': case '5':
00603          case '6': case '7': case '8':
00604          case '9':
00605             _t = _t*10 + *_p - '0';
00606          break;
00607          
00608          case 'w':
00609          case 'W':
00610             if(!_fl)
00611                return 0;
00612             _ft += _t*7*24*3600;
00613             _t = 0;
00614          break;
00615          case 'd':
00616          case 'D':
00617             if(!_fl)
00618                return 0;
00619             _ft += _t*24*3600;
00620             _t = 0;
00621          break;
00622          case 'h':
00623          case 'H':
00624             if(_fl)
00625                return 0;
00626             _ft += _t*3600;
00627             _t = 0;
00628          break;
00629          case 'm':
00630          case 'M':
00631             if(_fl)
00632                return 0;
00633             _ft += _t*60;
00634             _t = 0;
00635          break;
00636          case 's':
00637          case 'S':
00638             if(_fl)
00639                return 0;
00640             _ft += _t;
00641             _t = 0;
00642          break;
00643          case 't':
00644          case 'T':
00645             if(!_fl)
00646                return 0;
00647             _fl = 0;
00648          break;
00649          default:
00650             return 0;
00651       }
00652       _p++;
00653    }
00654 
00655    return _ft;
00656 }
00657 
00658 tr_byxxx_p ic_parse_byday(char *_in)
00659 {
00660    tr_byxxx_p _bxp = NULL;
00661    int _nr, _s, _v;
00662    char *_p;
00663 
00664    if(!_in)
00665       return NULL;
00666    _bxp = tr_byxxx_new();
00667    if(!_bxp)
00668       return NULL;
00669    _p = _in;
00670    _nr = 1;
00671    while(*_p)
00672    {
00673       if(*_p == ',')
00674          _nr++;
00675       _p++;
00676    }
00677    if(tr_byxxx_init(_bxp, _nr) < 0)
00678    {
00679       tr_byxxx_free(_bxp);
00680       return NULL;
00681    }
00682    _p = _in;
00683    _nr = _v = 0;
00684    _s = 1;
00685    while(*_p && _nr < _bxp->nr)
00686    {
00687       switch(*_p)
00688       {
00689          case '0': case '1': case '2':
00690          case '3': case '4': case '5':
00691          case '6': case '7': case '8':
00692          case '9':
00693             _v = _v*10 + *_p - '0';
00694          break;
00695          
00696          case 's':
00697          case 'S':
00698             _p++;
00699             switch(*_p)
00700             {
00701                case 'a':
00702                case 'A':
00703                   _bxp->xxx[_nr] = WDAY_SA;
00704                   _bxp->req[_nr] = _s*_v;
00705                break;
00706                case 'u':
00707                case 'U':
00708                   _bxp->xxx[_nr] = WDAY_SU;
00709                   _bxp->req[_nr] = _s*_v;
00710                break;
00711                default:
00712                   goto error;
00713             }
00714             _s = 1;
00715             _v = 0;
00716          break;
00717          case 'm':
00718          case 'M':
00719             _p++;
00720             if(*_p!='o' && *_p!='O')
00721                goto error;
00722             _bxp->xxx[_nr] = WDAY_MO;
00723             _bxp->req[_nr] = _s*_v;
00724             _s = 1;
00725             _v = 0;
00726          break;
00727          case 't':
00728          case 'T':
00729             _p++;
00730             switch(*_p)
00731             {
00732                case 'h':
00733                case 'H':
00734                   _bxp->xxx[_nr] = WDAY_TH;
00735                   _bxp->req[_nr] = _s*_v;
00736                break;
00737                case 'u':
00738                case 'U':
00739                   _bxp->xxx[_nr] = WDAY_TU;
00740                   _bxp->req[_nr] = _s*_v;
00741                break;
00742                default:
00743                   goto error;
00744             }
00745             _s = 1;
00746             _v = 0;
00747          break;
00748          case 'w':
00749          case 'W':
00750             _p++;
00751             if(*_p!='e' && *_p!='E')
00752                goto error;
00753             _bxp->xxx[_nr] = WDAY_WE;
00754             _bxp->req[_nr] = _s*_v;
00755             _s = 1;
00756             _v = 0;
00757          break;
00758          case 'f':
00759          case 'F':
00760             _p++;
00761             if(*_p!='r' && *_p!='R')
00762                goto error;
00763             _bxp->xxx[_nr] = WDAY_FR;
00764             _bxp->req[_nr] = _s*_v;
00765             _s = 1;
00766             _v = 0;
00767          break;
00768          case '-':
00769             _s = -1;
00770          break;
00771          case '+':
00772          case ' ':
00773          case '\t':
00774          break;
00775          case ',':
00776             _nr++;
00777          break;
00778          default:
00779             goto error;
00780       }
00781       _p++;
00782    }
00783 
00784    return _bxp;
00785 
00786 error:
00787    tr_byxxx_free(_bxp);
00788    return NULL;
00789 }
00790 
00791 tr_byxxx_p ic_parse_byxxx(char *_in)
00792 {
00793    tr_byxxx_p _bxp = NULL;
00794    int _nr, _s, _v;
00795    char *_p;
00796 
00797    if(!_in)
00798       return NULL;
00799    _bxp = tr_byxxx_new();
00800    if(!_bxp)
00801       return NULL;
00802    _p = _in;
00803    _nr = 1;
00804    while(*_p)
00805    {
00806       if(*_p == ',')
00807          _nr++;
00808       _p++;
00809    }
00810    if(tr_byxxx_init(_bxp, _nr) < 0)
00811    {
00812       tr_byxxx_free(_bxp);
00813       return NULL;
00814    }
00815    _p = _in;
00816    _nr = _v = 0;
00817    _s = 1;
00818    while(*_p && _nr < _bxp->nr)
00819    {
00820       switch(*_p)
00821       {
00822          case '0': case '1': case '2':
00823          case '3': case '4': case '5':
00824          case '6': case '7': case '8':
00825          case '9':
00826             _v = _v*10 + *_p - '0';
00827          break;
00828          
00829          case '-':
00830             _s = -1;
00831          break;
00832          case '+':
00833          case ' ':
00834          case '\t':
00835          break;
00836          case ',':
00837             _bxp->xxx[_nr] = _v;
00838             _bxp->req[_nr] = _s;
00839             _s = 1;
00840             _v = 0;
00841             _nr++;
00842          break;
00843          default:
00844             goto error;
00845       }
00846       _p++;
00847    }
00848    if(_nr < _bxp->nr)
00849    {
00850       _bxp->xxx[_nr] = _v;
00851       _bxp->req[_nr] = _s;
00852    }
00853    return _bxp;
00854 
00855 error:
00856    tr_byxxx_free(_bxp);
00857    return NULL;
00858 }
00859 
00860 int ic_parse_wkst(char *_in)
00861 {
00862    if(!_in || strlen(_in)!=2)
00863       goto error;
00864    
00865    switch(_in[0])
00866    {
00867       case 's':
00868       case 'S':
00869          switch(_in[1])
00870          {
00871             case 'a':
00872             case 'A':
00873                return WDAY_SA;
00874             case 'u':
00875             case 'U':
00876                return WDAY_SU;
00877             default:
00878                goto error;
00879          }
00880       case 'm':
00881       case 'M':
00882          if(_in[1]!='o' && _in[1]!='O')
00883             goto error;
00884          return WDAY_MO;
00885       case 't':
00886       case 'T':
00887          switch(_in[1])
00888          {
00889             case 'h':
00890             case 'H':
00891                return WDAY_TH;
00892             case 'u':
00893             case 'U':
00894                return WDAY_TU;
00895             default:
00896                goto error;
00897          }
00898       case 'w':
00899       case 'W':
00900          if(_in[1]!='e' && _in[1]!='E')
00901             goto error;
00902          return WDAY_WE;
00903       case 'f':
00904       case 'F':
00905          if(_in[1]!='r' && _in[1]!='R')
00906             goto error;
00907          return WDAY_FR;
00908       break;
00909       default:
00910          goto error;
00911    }
00912    
00913 error:
00914 #ifdef USE_YWEEK_U
00915    return WDAY_SU;
00916 #else
00917    return WDAY_MO;
00918 #endif
00919 }
00920 
00921 
00922 
00923 
00924 
00925 
00926 /*********************** imported from "checktr.c"  **************************/
00927 
00928 #define REC_ERR    -1
00929 #define REC_MATCH   0
00930 #define REC_NOMATCH 1
00931 
00932 #define _IS_SET(x) (((x)>0)?1:0)
00933 
00934 /*** local headers ***/
00935 int get_min_interval(tmrec_p);
00936 int check_min_unit(tmrec_p, ac_tm_p, tr_res_p);
00937 int check_freq_interval(tmrec_p _trp, ac_tm_p _atp);
00938 int check_byxxx(tmrec_p, ac_tm_p);
00939 
00940 /**
00941  *
00942  * return 0/REC_MATCH - the time falls in
00943  *       -1/REC_ERR - error
00944  *        1/REC_NOMATCH - the time falls out
00945  */
00946 int check_tmrec(tmrec_p _trp, ac_tm_p _atp, tr_res_p _tsw)
00947 {
00948    if(!_trp || !_atp || (!_IS_SET(_trp->duration) && !_IS_SET(_trp->dtend)))
00949       return REC_ERR;
00950 
00951    /* it is before start date */
00952    if(_atp->time < _trp->dtstart)
00953       return REC_NOMATCH;
00954    
00955    /* compute the duration of the recurrence interval */
00956    if(!_IS_SET(_trp->duration))
00957       _trp->duration = _trp->dtend - _trp->dtstart;
00958    
00959    if(_atp->time <= _trp->dtstart+_trp->duration)
00960    {
00961       if(_tsw)
00962       {
00963          if(_tsw->flag & TSW_RSET)
00964          {
00965             if(_tsw->rest>_trp->dtstart+_trp->duration-_atp->time)
00966                _tsw->rest = _trp->dtstart+_trp->duration - _atp->time;
00967          }
00968          else
00969          {
00970             _tsw->flag |= TSW_RSET;
00971             _tsw->rest = _trp->dtstart+_trp->duration - _atp->time;
00972          }
00973       }
00974       return REC_MATCH;
00975    }
00976    
00977    /* after the bound of recurrence */
00978    if(_IS_SET(_trp->until) && _atp->time >= _trp->until + _trp->duration)
00979       return REC_NOMATCH;
00980    
00981    /* check if the instance of recurrence matches the 'interval' */
00982    if(check_freq_interval(_trp, _atp)!=REC_MATCH)
00983       return REC_NOMATCH;
00984 
00985    if(check_min_unit(_trp, _atp, _tsw)!=REC_MATCH)
00986       return REC_NOMATCH;
00987 
00988    if(check_byxxx(_trp, _atp)!=REC_MATCH)
00989       return REC_NOMATCH;
00990 
00991    return REC_MATCH;
00992 }
00993 
00994 
00995 int check_freq_interval(tmrec_p _trp, ac_tm_p _atp)
00996 {
00997    int _t0, _t1;
00998    struct tm _tm;
00999    if(!_trp || !_atp)
01000       return REC_ERR;
01001    
01002    if(!_IS_SET(_trp->freq))
01003       return REC_NOMATCH;
01004    
01005    if(!_IS_SET(_trp->interval) || _trp->interval==1)
01006       return REC_MATCH;
01007    
01008    switch(_trp->freq)
01009    {
01010       case FREQ_DAILY:
01011       case FREQ_WEEKLY:
01012          memset(&_tm, 0, sizeof(struct tm));
01013          _tm.tm_year = _trp->ts.tm_year;
01014          _tm.tm_mon = _trp->ts.tm_mon;
01015          _tm.tm_mday = _trp->ts.tm_mday;
01016          _t0 = (int)mktime(&_tm);
01017          memset(&_tm, 0, sizeof(struct tm));
01018          _tm.tm_year = _atp->t.tm_year;
01019          _tm.tm_mon = _atp->t.tm_mon;
01020          _tm.tm_mday = _atp->t.tm_mday;
01021          _t1 = (int)mktime(&_tm);
01022          if(_trp->freq == FREQ_DAILY)
01023             return (((_t1-_t0)/(24*3600))%_trp->interval==0)?
01024                REC_MATCH:REC_NOMATCH;
01025 #ifdef USE_YWEEK_U
01026          _t0 -= _trp->ts.tm_wday*24*3600;
01027          _t1 -= _atp->t.tm_wday*24*3600;
01028 #else
01029          _t0 -= ((_trp->ts.tm_wday+6)%7)*24*3600;
01030          _t1 -= ((_atp->t.tm_wday+6)%7)*24*3600;
01031 #endif
01032          return (((_t1-_t0)/(7*24*3600))%_trp->interval==0)?
01033                REC_MATCH:REC_NOMATCH;
01034       case FREQ_MONTHLY:
01035          _t0 = (_atp->t.tm_year-_trp->ts.tm_year)*12
01036                + _atp->t.tm_mon-_trp->ts.tm_mon;
01037          return (_t0%_trp->interval==0)?REC_MATCH:REC_NOMATCH;
01038       case FREQ_YEARLY:
01039          return ((_atp->t.tm_year-_trp->ts.tm_year)%_trp->interval==0)?
01040                REC_MATCH:REC_NOMATCH;
01041    }
01042    
01043    return REC_NOMATCH;
01044 }
01045 
01046 int get_min_interval(tmrec_p _trp)
01047 {
01048    if(!_trp)
01049       return FREQ_NOFREQ;
01050    
01051    if(_trp->freq == FREQ_DAILY || _trp->byday || _trp->bymday || _trp->byyday)
01052       return FREQ_DAILY;
01053    if(_trp->freq == FREQ_WEEKLY || _trp->byweekno) 
01054       return FREQ_WEEKLY;
01055    if(_trp->freq == FREQ_MONTHLY || _trp->bymonth)
01056       return FREQ_MONTHLY;
01057    if(_trp->freq == FREQ_YEARLY)
01058       return FREQ_YEARLY;
01059    
01060    return FREQ_NOFREQ;
01061 }
01062 
01063 int check_min_unit(tmrec_p _trp, ac_tm_p _atp, tr_res_p _tsw)
01064 {
01065    int _v0, _v1;
01066    if(!_trp || !_atp)
01067       return REC_ERR;
01068    switch(get_min_interval(_trp))
01069    {
01070       case FREQ_DAILY:
01071       break;
01072       case FREQ_WEEKLY:
01073          if(_trp->ts.tm_wday != _atp->t.tm_wday)
01074             return REC_NOMATCH;
01075       break;
01076       case FREQ_MONTHLY:
01077          if(_trp->ts.tm_mday != _atp->t.tm_mday)
01078             return REC_NOMATCH;
01079       break;
01080       case FREQ_YEARLY:
01081          if(_trp->ts.tm_mon != _atp->t.tm_mon 
01082                || _trp->ts.tm_mday != _atp->t.tm_mday)
01083             return REC_NOMATCH;
01084       break;
01085       default:
01086          return REC_NOMATCH;
01087    }
01088    _v0 = _trp->ts.tm_hour*3600 + _trp->ts.tm_min*60 + _trp->ts.tm_sec;
01089    _v1 = _atp->t.tm_hour*3600 + _atp->t.tm_min*60 + _atp->t.tm_sec;
01090    if(_v1 >= _v0 && _v1 < _v0 + _trp->duration)
01091    {
01092       if(_tsw)
01093       {
01094          if(_tsw->flag & TSW_RSET)
01095          {
01096             if(_tsw->rest>_v0+_trp->duration-_v1)
01097                _tsw->rest = _v0 + _trp->duration - _v1;
01098          }
01099          else
01100          {
01101             _tsw->flag |= TSW_RSET;
01102             _tsw->rest = _v0 + _trp->duration - _v1;
01103          }
01104       }
01105       return REC_MATCH;
01106    }
01107    
01108    return REC_NOMATCH;
01109 }
01110 
01111 int check_byxxx(tmrec_p _trp, ac_tm_p _atp)
01112 {
01113    int i;
01114    ac_maxval_p _amp = NULL;
01115    if(!_trp || !_atp)
01116       return REC_ERR;
01117    if(!_trp->byday && !_trp->bymday && !_trp->byyday && !_trp->bymonth 
01118          && !_trp->byweekno)
01119       return REC_MATCH;
01120    
01121    _amp = ac_get_maxval(_atp);
01122    if(!_amp)
01123       return REC_NOMATCH;
01124    
01125    if(_trp->bymonth)
01126    {
01127       for(i=0; i<_trp->bymonth->nr; i++)
01128       {
01129          if(_atp->t.tm_mon == 
01130                (_trp->bymonth->xxx[i]*_trp->bymonth->req[i]+12)%12)
01131             break;
01132       }
01133       if(i>=_trp->bymonth->nr)
01134          return REC_NOMATCH;
01135    }
01136    if(_trp->freq==FREQ_YEARLY && _trp->byweekno)
01137    {
01138       for(i=0; i<_trp->byweekno->nr; i++)
01139       {
01140          if(_atp->yweek == (_trp->byweekno->xxx[i]*_trp->byweekno->req[i]+
01141                      _amp->yweek)%_amp->yweek)
01142             break;
01143       }
01144       if(i>=_trp->byweekno->nr)
01145          return REC_NOMATCH;
01146    }
01147    if(_trp->byyday)
01148    {
01149       for(i=0; i<_trp->byyday->nr; i++)
01150       {
01151          if(_atp->t.tm_yday == (_trp->byyday->xxx[i]*_trp->byyday->req[i]+
01152                   _amp->yday)%_amp->yday)
01153             break;
01154       }
01155       if(i>=_trp->byyday->nr)
01156          return REC_NOMATCH;
01157    }
01158    if(_trp->bymday)
01159    {
01160       for(i=0; i<_trp->bymday->nr; i++)
01161       {
01162 #ifdef EXTRA_DEBUG
01163          DBG("Req:bymday: %d == %d\n", _atp->t.tm_mday,
01164             (_trp->bymday->xxx[i]*_trp->bymday->req[i]+
01165             _amp->mday)%_amp->mday + ((_trp->bymday->req[i]<0)?1:0));
01166 #endif
01167          if(_atp->t.tm_mday == (_trp->bymday->xxx[i]*_trp->bymday->req[i]+
01168                   _amp->mday)%_amp->mday + (_trp->bymday->req[i]<0)?1:0)
01169             break;
01170       }
01171       if(i>=_trp->bymday->nr)
01172          return REC_NOMATCH;
01173    }
01174    if(_trp->byday)
01175    {
01176       for(i=0; i<_trp->byday->nr; i++)
01177       {
01178          if(_trp->freq==FREQ_YEARLY)
01179          {
01180 #ifdef EXTRA_DEBUG
01181             DBG("Req:byday:y: %d==%d && %d==%d\n", _atp->t.tm_wday,
01182                _trp->byday->xxx[i], _atp->ywday+1, 
01183                (_trp->byday->req[i]+_amp->ywday)%_amp->ywday);
01184 #endif
01185             if(_atp->t.tm_wday == _trp->byday->xxx[i] &&
01186                   _atp->ywday+1 == (_trp->byday->req[i]+_amp->ywday)%
01187                   _amp->ywday)
01188                break;
01189          }
01190          else
01191          {
01192             if(_trp->freq==FREQ_MONTHLY)
01193             {
01194 #ifdef EXTRA_DEBUG
01195                DBG("Req:byday:m: %d==%d && %d==%d\n", _atp->t.tm_wday,
01196                   _trp->byday->xxx[i], _atp->mwday+1, 
01197                   (_trp->byday->req[i]+_amp->mwday)%_amp->mwday);
01198 #endif
01199                if(_atp->t.tm_wday == _trp->byday->xxx[i] &&
01200                      _atp->mwday+1==(_trp->byday->req[i]+
01201                      _amp->mwday)%_amp->mwday)
01202                   break;
01203             }
01204             else
01205             {
01206                if(_atp->t.tm_wday == _trp->byday->xxx[i])
01207                   break;
01208             }
01209          }
01210       }
01211       if(i>=_trp->byday->nr)
01212          return REC_NOMATCH;
01213    }
01214 
01215    return REC_MATCH;
01216 }
01217 
01218 

Generated on Mon May 21 18:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6