#ifndef __DWC_TIMO_C
#define __DWC_TIMO_C

/*--------------------------------------------------------------------------
 *  Copyright (c) 2001-2004 Igor Daniloff. 
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at this directory.
 *------------------------------------------------------------------------*/
 
#ifndef lint
static const char rcsid[] = "$Id: dwc_timo.c,v 1.41 2005/09/21 09:20:44 asv Exp $";
#endif

#include <time.h>
#include "dwc_macro.h"
#include "dwc_timo.h"
#if defined(__UNIX_DW)
#include "dwc_lib.h"
#endif /* UNIX */
#if defined(__WIN32_DW)
#include "dw_winlib.h"
#endif /* WIN32 */

static DWC_systimeout_t get_current_time( void );
static DWC_timeout_t    get_diff_time( DWC_systimeout_t start, DWC_systimeout_t stop );

/* -------------------------------------------------------------------- */
static DWC_timeout_t get_diff_time( DWC_systimeout_t start, DWC_systimeout_t stop )
{    
    DWC_systimeout_t dif;    
#if defined(__UNIX_DW)    
    dif.tv_sec = stop.tv_sec - start.tv_sec; 
    dif.tv_usec = stop.tv_usec - start.tv_usec;
    if( dif.tv_usec < 0 ) 
    {                    
        --dif.tv_sec;                           
        dif.tv_usec += 1000000;               
    }
#endif /* UNIX */
#if defined(__WIN32_DW)    
    dif = stop - start;
#endif /* WIN32 */
    return system_to_timeout( dif );
}

/* -------------------------------------------------------------------- */
static DWC_systimeout_t get_current_time( void )
{
#if defined(__UNIX_DW)    
    DWC_systimeout_t  stime;
    
    if( gettimeofday( &stime, NULL ) < 0 )
    {
        stime.tv_sec = time( NULL );
        stime.tv_usec = 0L;
    }
    return stime;
#endif /* UNIX */
#if defined(__WIN32_DW)  
    return GetTickCount();
#endif /* WIN32 */
}

/* -------------------------------------------------------------------- */
DWC_systimeout_t start_timeout( DWC_timeout_t timo )
{
    DWC_systimeout_t nt;

    if( timo == INFINITE_TIMEOUT )        
    {
#if defined(__UNIX_DW)    
        nt.tv_sec = 0L;
        nt.tv_usec = 0L;
        return nt;
#endif /* UNIX */        
#if defined(__WIN32_DW)
        nt = 0;  
        return nt;
#endif /* WIN32 */
    }
    return get_current_time();
}

/* -------------------------------------------------------------------- */
DWC_timeout_t stop_timeout( DWC_timeout_t timo, DWC_systimeout_t start )
{
    DWC_systimeout_t    stop;    
    DWC_timeout_t       dift;

    if( timo == INFINITE_TIMEOUT )        
    {
        return timo;
    }
    stop = get_current_time();
    dift = get_diff_time( start, stop );
    if( (dift < NOWAIT_TIMEOUT)
        ||
        (dift >= timo) )
    {
        return EXPIRED_TIMEOUT;
    }        
    return timo - dift;
}

/* -------------------------------------------------------------------- */
DWC_timeout_t timeval_to_timeout( struct timeval timev )
{
    DWC_timeout_t  to;
    
    to = timev.tv_usec / 1000;
    to += timev.tv_sec * 1000;
    return to;
}

/* -------------------------------------------------------------------- */
struct timeval* timeout_to_timeval( DWC_timeout_t timeout, struct timeval* timev_ptr )
{
    EXIT_IF_1PARAM( !timev_ptr, "dwlib: time:", return NULL );   
    if( timeout == INFINITE_TIMEOUT )
    {
        return NULL;
    }
    if( timeout == NOWAIT_TIMEOUT )
    {
        timev_ptr->tv_sec = 0L;
        timev_ptr->tv_usec = 0L;
    }    
    else 
    {
        timev_ptr->tv_sec = timeout / 1000;
        timev_ptr->tv_usec = (timeout % 1000) * 1000;
    }
    return timev_ptr;
}

/* -------------------------------------------------------------------- */
DWC_timeout_t system_to_timeout( DWC_systimeout_t stimo )
{
#if defined(__WIN32_DW)
    return stimo;
#endif /* WIN32 */
#if defined(__UNIX_DW)    
    return timeval_to_timeout( stimo );
#endif /* UNIX */
}

/* -------------------------------------------------------------------- */
DWC_systimeout_t* timeout_to_system( DWC_timeout_t timo, DWC_systimeout_t* stimo_ptr )
{
    EXIT_IF_1PARAM( !stimo_ptr, "dwlib: time:", return NULL );    
#if defined(__WIN32_DW)
    if( timo == INFINITE_TIMEOUT )
    {
        *stimo_ptr = INFINITE;
    }    
    else if( timo == NOWAIT_TIMEOUT )
    {
        *stimo_ptr  = 0;
    }    
    else 
    {
        *stimo_ptr = timo;
    }
    return stimo_ptr;
#endif /* WIN32 */
#if defined(__UNIX_DW)    
    return timeout_to_timeval( timo, stimo_ptr );
#endif /* UNIX */
}

#endif /* __DWC_TIMO_C */
