ossp-pkg/tai/tai_lib.c
1.2
/*
** OSSP tai - Time Handling
** Copyright (c) 2002 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 2002 The OSSP Project <http://www.ossp.org/>
** Copyright (c) 2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
**
** 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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include "tai.h"
#include "tai_p.h"
struct tai_st {
int tai_sec; /* seconds after the minute [0-61] */
int tai_min; /* minutes after the hour [0-59] */
int tai_hour; /* hours since midnight [0-23] */
int tai_mday; /* day of the month [1-31] */
int tai_mon; /* months since January [0-11] */
int tai_year; /* years since 1900 */
int tai_wday; /* days since Sunday [0-6] */
int tai_yday; /* days since January 1 [0-365] */
int tai_isdst; /* Daylight Savings Time flag */
long tai_gmtoff; /* offset from CUT in seconds */
char *tai_zone; /* timezone abbreviation */
#if 0
int sign;
unsigned long long sec;
unsigned long nsec;
unsigned long asec;
#endif
};
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;
}