//Editor-Info: -*- C++ -*-
//
//Subject: OVOPS Library, class OTime
//
//File: otime.cpp
//
//Version: $Revision: 1.3 $
//
//Date: $Date: 1998/07/13 09:13:57 $
//
//Organisation:
//      Telecom Finland, 
//      Lappeenranta University of Technology
// 
//Author:
//      Panu Puro
//
//Description:
//      Implementations of member functions of the otime class.
//
//Copyright:
//      The following copyright and permission notice outlines the rights and
//      restrictions covering most parts of the core distribution of the OVOPS
//      System from Telecom Finland. Other parts have additional or different
//      copyrights and permissions; see the individual source files.
//      
//      Copyright 1994 by Telecom Finland
//      
//Licence:
//      Permission to use, copy, modify, distribute, and sell this software and
//      its documentation for any purpose is hereby granted without fee,
//      provided that the above copyright notice appear in all copies and that
//      both that copyright notice and this permission notice appear in
//      supporting documentation, and that the name of Telecom Finland not be
//      used in advertising or publicity pertaining to distribution of the
//      software without specific, written prior permission. Telecom Finland
//      makes no representations about the suitability of this software for any
//      purpose. It is provided "as is" without express or implied warranty.
//
//History:
//
// SF Revision   1997/05/05  12:00:00  justus
// Added < operators.
//
// Revision 2.1  1994/11/01  11:01:57  asopanen
// Function 'operator > (const double other) const' returns ~0 only
// when both secs and usecs are greater than other's. Now the
// function returns ~0 only when secs are greater OR secs are equal
// and usecs are greater than other's.
//
// Revision 2.0  1994/07/07  10:21:13  pmp
// OVOPS Version 1.0
//

#include "otime.h"

//
//Constructor: OTime
//
//Parameters:
//      long seconds, 
//      long micros
//
//Description:
//      The constructor takes an initial time and normalizes it
//      into its internal variables. 
//
//      The parameter seconds is an initial time, and micros is an 
//      initial time, default zero.
//
OTime :: OTime (long seconds, long micros) 
{
    tv_sec = seconds + micros/1000000;
    tv_usec = micros%1000000;
}


//
//Constructor: OTime
//
//Parameters:
//      OTime &other
//
//Description:
//      The copy constructor of the class.
//
//      The parameter other is an initial time in OTime.
//
OTime :: OTime (const OTime &other)
{
    *this = other;
}


//
//Operator: =
//
//Member-Of: OTime
//
//Parameters:
//      OTime &rhs
//
//Return:
//      OTime &
//
//Description:
//      The assigment operator copies the given time in an OTime type 
//      variable to itself.
//
//      The paramter rhs is another time that is copied.
//
//      Returns a reference to itself.
//
OTime &OTime :: operator = (const OTime &rhs)
{
    tv_sec = rhs.tv_sec;
    tv_usec = rhs.tv_usec;
    return *this;
}



//
//Operator: = 
//
//Member-Of: OTime
//
//Parameters:
//      double other
//
//Return:
//      OTime &
//
//Description:
//      The assigment operator copies the given time in a double type
//      variable to itself. Note that precision can produce some
//      problem when handling very large or small numbers.
//
//      Returns a reference to itself.
//
OTime &OTime :: operator = (const double other)
{
    tv_sec = (long)other;
    tv_usec = (long)((other - (long)other)*1000000);
    return *this;
}


//
//Operator: -
//
//Member-Of: OTime
//
//Parameters:
//      OTime &other
//
//Return:
//      OTime 
//
//Description:
//      return value = this - other
//
OTime OTime :: operator - (const OTime &other) const
{
    OTime result (tv_sec - other.tv_sec,
                  tv_usec - other.tv_usec);
    // normalize
    while (result.tv_usec < 0) {
	result.tv_usec += 1000000;
	result.tv_sec--;
    }
    return result;
}


//
//Operator: +
//
//Member-Of: OTime
//
//Parameters:
//      OTime &other
//
//Return:
//      OTime
//
//Description:
//      return value = this + other
//
//      Note that the result of addition may overflow in case when
//      both two time values are relatively large.
//
OTime OTime :: operator + (const OTime &other) const
{
    OTime result (tv_sec + other.tv_sec + (tv_usec + other.tv_usec)/1000000,
                  (tv_usec + other.tv_usec)%1000000);
    return result;
}


//
//Operator: +
//
//Member-Of: OTime
//
//Parameters:
//      double other
//
//Return:
//      OTime
//
//Description:
//      return value = this + other
//
OTime OTime :: operator + (const double other) const
{
    long usecs = (long)((other - (long)other)*1000000);    
    OTime result (tv_sec + (long)other 
                  + (tv_usec + usecs)/1000000,
                  (tv_usec + usecs)%1000000);
    return result;
}


//
//Operator: <=
//
//Member-Of: OTime
//
//Parameters:
//      OTime &other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if this time is less or equal than
//      the other time. Otherwise, returns zero.
//
int OTime :: operator <= (const OTime &other) const
{
    if ((tv_sec > other.tv_sec) ||
        ((tv_sec == other.tv_sec) && (tv_usec > other.tv_usec))) {
        return 0;
    }
    return ~0;
}


//
//Operator: >=
//
//Member-Of: OTime
//
//Parameters:
//      OTime &other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if this time is greater or equal than
//      the other time. Otherwise, returns zero.
//
int OTime :: operator >= (const OTime &other) const
{
    return (*this <= other) ? (*this == other) ? ~0 : 0 : ~0;
}


//
//Operator: <
//
//Member-Of: OTime
//
//Parameters:
//      OTime &other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if this time is less than
//      the other time. Otherwise, returns zero.
//
int OTime :: operator < (const OTime &other) const
{
    if ((tv_sec > other.tv_sec) || 
        ((tv_sec == other.tv_sec) && tv_usec >= other.tv_usec)) {
        return 0;
    }
    return ~0;
}


//
//Operator: <
//
//Member-Of: OTime
//
//Parameters:
//      double other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if this time is less than
//      the other time. Otherwise, returns zero.
//
int OTime :: operator < (const double other) const
{
    if ((tv_sec < (long)other) || ((tv_sec == (long)other) 
        && (tv_usec < (long)((other - (long)other)*1000000)))) {
        return ~0;
    }
    return 0;
}


//
//Operator: >
//
//Member-Of: OTime
//
//Parameters:
//      OTime &other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if this time is greater than
//      the other time. Otherwise, returns zero.
//
int OTime :: operator > (const OTime &other) const
{
    if ((tv_sec <= other.tv_sec) || 
        ((tv_sec == other.tv_sec) && tv_usec <= other.tv_usec)) {
        return 0;
    }
    return ~0;
}


//
//Operator: >
//
//Member-Of: OTime
//
//Parameters:
//      double other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if this time is greater or equal than
//      the other time. Otherwise, returns zero.
//
int OTime :: operator > (const double other) const
{
    if ((tv_sec > (long)other) || ((tv_sec == (long)other) 
        && (tv_usec > (long)((other - (long)other)*1000000)))) {
        return ~0;
    }
    return 0;
}


//
//Operator: ==
//
//Member-Of: OTime
//
//Parameters:
//      OTime &other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if the times are not equal. Otherwise,
//      returns zero.
//
int OTime :: operator == (const OTime &other) const
{
    return ((tv_sec == other.tv_sec) 
            && (tv_usec == other.tv_usec)) ? ~0 : 0; 
}

int OTime :: operator != (const OTime &other) const
{
    return !(*this == other);
}


//
//Operator: ==
//
//Member-Of: OTime
//
//Parameters:
//      double other
//
//Return:
//      int
//
//Description:
//      Compares this time and the time given as parameter.
//      Returns non-zero value if the times are not equal. Otherwise,
//      returns zero.
//
int OTime :: operator == (const double other) const
{
    return ((tv_sec == (long)other) 
            && (tv_usec == (long)((other - (long)other)*1000000))) 
            ? ~0 : 0;
}

int OTime :: operator != (const double other) const
{
    return !(*this == other);
}

//
//Constructor: OTime
//
//Description:
//      A default constructor. Time is initialized to zero.
//
OTime :: OTime (void) 
{
    tv_sec = tv_usec = 0;
}


//
//Function: getSeconds
//
//Member-Of: OTime
//
//Return:
//      long
//
//Description:
//      Returns time in seconds.
//
long OTime :: getSeconds (void) const
{
    return tv_sec + tv_usec/1000000;
}


//
//Function: getMicros
//
//Member-Of: OTime
//
//Return:
//      long
//
//Description:
//      Returns time in micro seconds (only micro second part, not
//      the whole time). 
//
long OTime :: getMicros (void) const
{
    return tv_usec%1000000;
}

