/* ** OSSP tai - Time Handling ** Copyright (c) 2002 Ralf S. Engelschall ** Copyright (c) 2002 The OSSP Project ** Copyright (c) 2002 Cable & Wireless Deutschland ** ** This file is part of OSSP tai, a time handling library ** which can be found at http://www.ossp.org/pkg/lib/tai/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** tm.c: API implementation */ #include #include #include #include #include #include "tai.h" #include "tai_p.h" tai_rc_t tai_create(tai_t **ptai) { tai_t *tai; tai_rc_t rv; if ((tai = (tai_t *)malloc(sizeof(tai_t))) == NULL) return TAI_ERR_SYS; if ((rv = tai_import(tai, TAI_TYPE_TIMET, 0)) != TAI_OK) { free(tai); return rv; } *ptai = tai; return TAI_OK; } tai_rc_t tai_destroy(tai_t *tai) { if (tai == NULL) return TAI_ERR_ARG; if (tai->tai_zone != NULL) free(tai->tai_zone); free(tai); return TAI_OK; } tai_rc_t tai_import(tai_t *tai, tai_type_t type, ...) { va_list ap; if (tai == NULL) return TAI_ERR_ARG; va_start(ap, type); if (type == TAI_TYPE_TIMET) { /* import from time_t */ #ifdef HAVE_GMTIME_R struct tm stmbuf; #endif struct tm *stm; time_t t; t = (time_t)va_arg(ap, long); #ifdef HAVE_GMTIME_R stm = gmtime_r(&t, &stmbuf); #else stm = gmtime(&t); #endif tai->tai_sec = stm->tm_sec; tai->tai_min = stm->tm_min; tai->tai_hour = stm->tm_hour; tai->tai_mday = stm->tm_mday; tai->tai_mon = stm->tm_mon; tai->tai_year = stm->tm_year; tai->tai_wday = stm->tm_wday; tai->tai_yday = stm->tm_yday; tai->tai_isdst = stm->tm_isdst; tai->tai_gmtoff = stm->tm_gmtoff; if (stm->tm_zone == NULL) tai->tai_zone = strdup(""); else tai->tai_zone = strdup(stm->tm_zone); } else if (type == TAI_TYPE_STRUCTTM) { /* import from struct tm */ struct tm *stm; stm = (struct tm *)va_arg(ap, void *); #define TM_ISRANGE(var,field,min,max) \ (var->tm_##field >= (min) && var->tm_##field <= (max)) if (!TM_ISRANGE(stm,sec,0,61) || !TM_ISRANGE(stm,min,0,59) || !TM_ISRANGE(stm,hour,0,23) || !TM_ISRANGE(stm,mday,1,31) || !TM_ISRANGE(stm,mon,0,11) || !TM_ISRANGE(stm,wday,0,6) || !TM_ISRANGE(stm,yday,0,365) || !TM_ISRANGE(stm,isdst,0,1)) return TAI_ERR_ARG; tai->tai_sec = stm->tm_sec; tai->tai_min = stm->tm_min; tai->tai_hour = stm->tm_hour; tai->tai_mday = stm->tm_mday; tai->tai_mon = stm->tm_mon; tai->tai_year = stm->tm_year; tai->tai_wday = stm->tm_wday; tai->tai_yday = stm->tm_yday; tai->tai_isdst = stm->tm_isdst; tai->tai_gmtoff = stm->tm_gmtoff; if (stm->tm_zone == NULL) tai->tai_zone = strdup(""); else tai->tai_zone = strdup(stm->tm_zone); } else return TAI_ERR_IMP; /* FIXME */ va_end(ap); return TAI_OK; } tai_rc_t tai_export(tai_t *tai, tai_type_t type, ...) { va_list ap; if (tai == NULL) return TAI_ERR_ARG; va_start(ap, type); if (type == TAI_TYPE_TIMET) { time_t *pt; struct tm stmbuf; struct tm *stm; #ifndef HAVE_TIMEGM time_t t; #endif pt = (time_t *)va_arg(ap, void *); stm = &stmbuf; stm->tm_sec = tai->tai_sec; stm->tm_min = tai->tai_min; stm->tm_hour = tai->tai_hour; stm->tm_mday = tai->tai_mday; stm->tm_mon = tai->tai_mon; stm->tm_year = tai->tai_year; stm->tm_wday = tai->tai_wday; stm->tm_yday = tai->tai_yday; stm->tm_isdst = tai->tai_isdst; stm->tm_gmtoff = tai->tai_gmtoff; stm->tm_zone = tai->tai_zone; #ifdef HAVE_TIMEGM /* non-standard timegm(3) makes our life easy */ *pt = timegm(stm); #else /* standard mktime(3) calculated relative to local timezone, so we have to post-adjust result */ *pt = mktime(stm); t = 12*60*60*2; /* max offset of 12 hours plus safety */ *pt += (mktime(localtime(&t)) - mktime(gmtime(&t))); #endif } else if (type == TAI_TYPE_STRUCTTM) { struct tm *stm; stm = (struct tm *)va_arg(ap, void *); stm->tm_sec = tai->tai_sec; stm->tm_min = tai->tai_min; stm->tm_hour = tai->tai_hour; stm->tm_mday = tai->tai_mday; stm->tm_mon = tai->tai_mon; stm->tm_year = tai->tai_year; stm->tm_wday = tai->tai_wday; stm->tm_yday = tai->tai_yday; stm->tm_isdst = tai->tai_isdst; stm->tm_gmtoff = tai->tai_gmtoff; stm->tm_zone = strdup(tai->tai_zone); } else return TAI_ERR_IMP; /* FIXME */ va_end(ap); return TAI_OK; } tai_rc_t tai_format(tai_t *tai, char *buf_ptr, size_t buf_len, const char *fmt) { struct tm stm; tai_rc_t rv; if (tai == NULL || buf_ptr == NULL || buf_len == 0 || fmt == NULL) return TAI_ERR_ARG; if ((rv = tai_export(tai, TAI_TYPE_STRUCTTM, &stm)) != TAI_OK) return rv; if (tai_format_int(buf_ptr, buf_len, fmt, &stm) == 0) return TAI_ERR_FMT; return TAI_OK; } tai_rc_t tai_parse(tai_t *tai, const char *buf_ptr, size_t buf_len, const char *fmt) { struct tm stm; char *cp; char *cp2; tai_rc_t rv; if (tai == NULL || buf_ptr == NULL || buf_len == 0 || fmt == NULL) return TAI_ERR_ARG; if ((cp = malloc(buf_len+1)) == NULL) return TAI_ERR_SYS; memmove(cp, buf_ptr, buf_len); cp[buf_len] = '\0'; memset(&stm, 0, sizeof(struct tm)); cp2 = tai_parse_int(cp, fmt, &stm); free(cp); if (cp2 == NULL) return TAI_ERR_PRS; if ((rv = tai_import(tai, TAI_TYPE_STRUCTTM, &stm)) != TAI_OK) return rv; return TAI_OK; } tai_rc_t tai_op(tai_t *tai, tai_op_t op, ...) { va_list ap; if (tai == NULL) return TAI_ERR_ARG; va_start(ap, op); va_end(ap); return TAI_ERR_IMP; }