Home Page Downloads Contact Us

Free Open Source Artificial Intelligence C++ Parts

aiParts Open Source Project  

Home Page
Open Source
Contact
Free Downloads
Releases and Credits
Software Status
License
v0.9.3 README File
About rrproj
assigning people and/or equipment to projects
High-Hope Technique
History of the AI
View Source Files
and how they are organized
Making Programs
Development Notes
Using aiParts
Your Application
Support and Services

aiParts Source File

//**********************************************************************
//  aipTime.cpp  -  function bodies for aipTime.h
//
//  Copyright (c)  2008  Brian Marshall
//
//  See the license at end of this file.
//
//  Developers/Contributers:
//    [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
//  08/07/09  [BRM] fixed a few bugs, improved the structure
//  08/02/03  [BRM] began development
//
//----------------------------------------------------------------------

#include "aipTime.h"

#include <stdio.h>
#include <stdlib.h>

            // for debugging...
// #include 
// using namespace std;

//======================================================================
//  Global Functions
//
//----------------------------------------------------------------------
//  set a string from days-since-Sunday - ex: "Mon" from 1

const char * aip_str_day (long imon) {

  if (imon < 0 || imon > 6) return aip_Empty_Str;

  return aip_Day_Abbrv[imon-1];

}

//----------------------------------------------------------------------
//  return the month-number: 1 for "Jan", 2 for "feb", etc.
//  or return zero if x is not valid

long aip_i_month (const char* x) {

  if (x[0] == 'J' || x[0] == 'j') {
    if (x[1] == 'A' || x[1] == 'a') {
      if (x[2] == 'N' || x[2] == 'n') return 1;
    } else {
      if (x[1] == 'U' || x[1] == 'u') {
        if (x[2] == 'N' || x[2] == 'n') return 6;
        if (x[2] == 'L' || x[2] == 'l') return 7;
      }
    }
  } else if (x[0] == 'F' || x[0] == 'f') {
    if (x[1] == 'E' || x[1] == 'e') {
      if (x[2] == 'B' || x[2] == 'b') return 2;
    }
  } else if (x[0] == 'M' || x[0] == 'm') {
    if (x[1] == 'A' || x[1] == 'a') {
      if (x[2] == 'R' || x[2] == 'r') return 3;
      if (x[2] == 'Y' || x[2] == 'y') return 5;
    }
  } else if (x[0] == 'A' || x[0] == 'a') {
    if (x[1] == 'P' || x[1] == 'p') {
      if (x[2] == 'R' || x[2] == 'r') return 4;
    } else if (x[1] == 'U' || x[1] == 'u') {
      if (x[2] == 'G' || x[2] == 'g') return 8;
    }
  } else if (x[0] == 'S' || x[0] == 's') {
    if (x[1] == 'E' || x[1] == 'e') {
      if (x[2] == 'P' || x[2] == 'p') return 9;
    }
  } else if (x[0] == 'O' || x[0] == 'o') {
    if (x[1] == 'C' || x[1] == 'c') {
      if (x[2] == 'T' || x[2] == 't') return 10;
    }
  } else if (x[0] == 'N' || x[0] == 'n') {
    if (x[1] == 'O' || x[1] == 'o') {
      if (x[2] == 'V' || x[2] == 'v') return 11;
    }
  } else if (x[0] == 'D' || x[0] == 'd') {
    if (x[1] == 'E' || x[1] == 'e') {
      if (x[2] == 'C' || x[2] == 'c') return 12;
    }
  }

  return 0;

}
 
//----------------------------------------------------------------------
//  set a string from a month number - ex: "Jan" from 1

const char * aip_str_month (long imon) {

  if (imon < 1 || imon > 12) return aip_Empty_Str;

  return aip_Month_Abbrv[imon-1];

}

//----------------------------------------------------------------------
//  Return true if yr is a leap year

int aip_is_leap_year (long yr) {

  if (yr%4 == 0 && (yr%100 != 0 || yr%400 == 0) ) return 1;

  return 0;

}

//----------------------------------------------------------------------
//  Return the number of days in the month and year in ts.

long aip_days_in_month (long yr, long mo) {

  if (mo < 1 || mo > 12) return 0;

  long dim = aip_Days_In_Month[mo];

  if (mo == 2 && aip_is_leap_year(yr)) dim = 29;

  return dim;

}

//======================================================================
//  aipTime
//
//----------------------------------------------------------------------
//  Construct from components

aipTime::aipTime (long a_year, long a_mon, long a_day,
                               long a_hour, long a_min, long a_sec) {

  set (a_year, a_mon, a_day, a_hour, a_min, a_sec);

}

//----------------------------------------------------------------------
//  Construct from components packed into two longs (second is optional)
//
//  in the optional second argument, seconds is optional - 
//  43045 is 4:30:45, 430 is 4:30 am, 1630 is 4:30 pm

aipTime::aipTime (long yyyymmdd, long hhmmss) {

  set (yyyymmdd, hhmmss);

}

//----------------------------------------------------------------------
//  set from components  
//
//  Note: all constructors and other set functions call this function
//        which attempts to prevent Daylight Savings Time from
//        causing problems.

void aipTime::set (long a_year, long a_mon, long a_day, 
                                long a_hour, long a_min, long a_sec) {

  if (a_year <   30) a_year += 100;  // 2-digit year after 2000
  if (a_year < 1000) a_year += 1900; // convert 2-digit year to 4-digit

  if (a_year < 1800 || a_year > 2300 ||
      a_mon  < 1    || a_mon  > 12   ||
      a_day  < 1    || a_day  > 31   ||
      a_hour < 0    || a_hour > 23   ||
      a_min  < 0    || a_min  > 59   ||
      a_sec  < 0    || a_sec  > 59) return;

  struct tm ts;                            // broken-down time

  ts.tm_sec   = a_sec;
  ts.tm_min   = a_min;
  ts.tm_hour  = a_hour;
  ts.tm_mday  = a_day;
  ts.tm_mon   = a_mon - 1;
  ts.tm_year  = a_year - 1900;

  set_daylight_savings_time (&ts);

  m_time = mktime (&ts);

}

//----------------------------------------------------------------------
//  set from components packed into two longs (second is optional)
//
//  430 is 4:30 am, 1630 is 4:30 pm

void aipTime::set  (long yyyymmdd, long hhmm) {

  long xyear, xmon, xday, xhour, xmin;

  long x = yyyymmdd;
  xyear = x / 10000;
  x -=  (xyear * 10000);

  if (xyear <  30) xyear += 100;    // 2-digit year after 2000
  if (xyear < 200) xyear += 1900;   // convert 2-digit year to 4-digit

  xmon = x / 100;
  x -=  (xmon * 100);

  xday = x;

  x = hhmm;

  if (x > 0) {

    xhour = x / 100;
    x -= (xhour * 100);

    xmin = x;

  } else {

    xhour = xmin = 0;

  }

  set (xyear, xmon, xday, xhour, xmin, 0);

}

//----------------------------------------------------------------------
//  set from another instance of aipTime

void aipTime::set (const aipTime& x) {

  m_time = x.tt_time();

}

//----------------------------------------------------------------------
//  set from a string like: "17 Feb 1998" or "17/02/2008 16:30:45"
//      or insert-format: "2008-02-17"
//
//  seconds is optional;  hours, minutes, seconds are optional

void aipTime::set (const char *x) {

  long xyear, xmon, xday, xhour, xmin, xsec, z;
  char buf[31];

  xyear = xmon = xday = 0;
  xhour = xmin = xsec = 0;

  while (x && *x) {

    x = aip_get_str(x, 30, buf);

    if (x) {

      if (buf[0] >= '0' && buf[0] <= '9') {

        z = atol(buf);
        if (z <= 0) { x=0; break; }

        if (z > 31) {                          // must be year
          if (xyear) { x=0; break; }  // already have a year
          xyear = z;
        } else if (!xday  && !xmon  && !xyear) {   // first component
          xday = z;  //                    assume dmy
        } else if ( xday  && !xmon  && !xyear) {   // month or year
          xmon = z;  // if day is first,   assume dmy
        } else if ( xmon  && !xday  && !xyear) {   // day   or year
          xday = z;  // if month is first, assume mdy
        } else if ( xyear && !xday  && !xmon)  {   // day   or month
          xmon = z;  // if year is first,  assume ymd
        } else if ( xday  &&  xmon  && !xyear) {
          xyear = z;
        } else if ( xday  &&  xyear && !xmon)  {
          xmon = z;
        } else if ( xmon  &&  xyear && !xday)  {
          xday = z;
        } else if (!xhour) {
          xhour = z;
        } else if (!xmin) {
          xmin = z;
        } else if (!xsec) {
          xsec = z;
        } else {
          x=0; break;           // have all numeric components
        }

      } else {    // am or pm or month

        for (int i=0; i<3; i++) {
          if (buf[i] >= 'a' && buf[i] <= 'z') buf[i] -= ('a' - 'A');
        }

        if ( (buf[0] == 'A' || buf[0] == 'P') && buf[1] == 'M') {
          if (!xmin) { x=0; break; }
          if (buf[0] == 'P' && xhour <= 12) xhour += 12;
          break;  // nothing follows am or pm
        }   // end of block for when string is am or pm

        if (xmon) { x=0; break; }  // already have a month
        xmon = aip_i_month(buf);
        if (xmon < 1 || xmon > 12) { x=0; break; }

      }   // end of block for a string of letters

    }   // end of block for successfully getting a string

  }   // end of loop through date/time components

  if (x) { 
    set (xyear, xmon, xday, xhour, xmin, xsec);
  } else {
    set(0,0,0,0,0,0);
  }

}

//----------------------------------------------------------------------
//  compare functions

int aipTime::eq (const aipTime& x) const {
  if ( difftime (m_time,x.tt_time()) == 0.0 ) return 1;
  return 0;
}

int aipTime::ne (const aipTime& x) const {
  if ( difftime (m_time,x.tt_time()) != 0.0 ) return 1;
  return 0;
}

int aipTime::lt (const aipTime& x) const {
  if ( difftime(m_time,x.tt_time()) < 0.0 ) return 1;
  return 0;
}

int aipTime::gt (const aipTime& x) const {
  if ( difftime(m_time,x.tt_time()) > 0.0 ) return 1;
  return 0;
}

int aipTime::le (const aipTime& x) const {
  if ( difftime(m_time,x.tt_time()) <= 0.0 ) return 1;
  return 0;
}

int aipTime::ge (const aipTime& x) const {
  if ( difftime(m_time,x.tt_time()) >= 0.0 ) return 1;
  return 0;
}


//----------------------------------------------------------------------
//  Set ts->tm_isdst from the other components

void aipTime::set_daylight_savings_time (struct tm *ts) const {

  long start_mon, start_day, end_mon, end_day;  // Jan = 1

  if (ts->tm_year <= 105) {                        // 2005 and earlier
    start_mon = 4;  start_day =  3;  end_mon = 10;  end_day = 30;
  } else if (ts->tm_year == 106) {                 // 2006
    start_mon = 4;  start_day =  2;  end_mon = 10;  end_day = 29;
  } else if (ts->tm_year == 107) {                 // 2007
    start_mon = 3;  start_day = 11;  end_mon = 11;  end_day =  4;
  } else if (ts->tm_year == 108) {                 // 2008
    start_mon = 3;  start_day =  9;  end_mon = 11;  end_day =  2;
  } else if (ts->tm_year == 109) {                 // 2009
    start_mon = 3;  start_day =  8;  end_mon = 11;  end_day =  1;
  } else if (ts->tm_year >= 110) {                 // 2010 and later
    start_mon = 3;  start_day = 14;  end_mon = 11;  end_day =  7;
  } 

  long mon = ts->tm_mon + 1;
  long day = ts->tm_mday;
  long hr  = ts->tm_hour;

  if ( ( (mon  > start_mon) ||
         (mon == start_mon && day  > start_day) ||
         (mon == start_mon && day == start_day && hr >= 2) ) &&
       ( (mon  < end_mon) ||
         (mon == end_mon && day < end_day) ||
         (mon == end_mon && day == end_day && hr < 2) ) ) {
    ts->tm_isdst = 1;
  } else {
    ts->tm_isdst = 0;
  }

}

//----------------------------------------------------------------------
//  Add seconds to this date

void aipTime::add_seconds (long num) {

  if (!is_valid()) return;

  struct tm ts = *(localtime(&m_time));

  ts.tm_sec += num;

  m_time = mktime (&ts);   // mktime will renormalize the date

}

//----------------------------------------------------------------------
//  Add hours to this date

void aipTime::add_hours (long num) {

  if (!is_valid()) return;

  struct tm ts = *(localtime(&m_time));

  ts.tm_hour += num;

  m_time = mktime (&ts);   // mktime will renormalize the date

}

//----------------------------------------------------------------------
//  Add days to this date

void aipTime::add_days (long num) {

  if (!is_valid()) return;

  struct tm ts = *(localtime(&m_time));

  ts.tm_mday += num;

  m_time = mktime (&ts);   // mktime will renormalize the date

}

//----------------------------------------------------------------------
//  return the number of days since Sunday

long aipTime::days_since_sunday () const {

  struct tm *ts = localtime (&m_time);

  return ts->tm_wday;

}

//----------------------------------------------------------------------
//  return the number of days since January 1

long aipTime::days_since_jan1   () const {

  struct tm *ts = localtime (&m_time);

  return ts->tm_yday;

}

//----------------------------------------------------------------------
//  return the number of seconds since x

long aipTime::seconds_since (const aipTime& x) const {

  long nsec = (long)difftime (m_time, x.tt_time());

  return nsec;

}

//----------------------------------------------------------------------
//  return the number of minutes since x

long aipTime::minutes_since (const aipTime& x) const {

  return (seconds_since(x) / 60);

}

//----------------------------------------------------------------------
//  return the number of hours since x

long aipTime::hours_since (const aipTime& x) const {

  return (seconds_since(x) / (60 * 60));

}

//----------------------------------------------------------------------
//  return the number of days since x

long aipTime::days_since (const aipTime& x) const {

  return (seconds_since(x) / (60 * 60 * 24));

}

//----------------------------------------------------------------------
//  set the whole days, hours, minutes and seconds since x

void aipTime::time_since (const aipTime& x,
                          long *pdays, long *phrs, 
                          long *pmins, long *psecs) const {

  long nsec = seconds_since(x);

  const long sec_per_min = 60;
  const long sec_per_hr  = 60 * 60;
  const long sec_per_day = 60 * 60 * 24;

  long days = 0;
  if (nsec >= sec_per_day) {
    days = nsec / sec_per_day;
    nsec -= (days * sec_per_day);
  }

  long hrs = 0;
  if (nsec >= sec_per_hr) {
    hrs = nsec / sec_per_hr;
    nsec -= (hrs * sec_per_hr);
  }

  long mins = 0;
  if (nsec >= sec_per_min) {
    mins = nsec / sec_per_min;
    nsec -= (mins * sec_per_min);
  }

  if (pdays) *pdays = days;
  if (phrs)  *phrs  = hrs;
  if (pmins) *pmins = mins;
  if (psecs) *psecs = nsec;

}

//----------------------------------------------------------------------
//  return the difference in hours after x

long aipTime::hours_after (const aipTime& x) const {

  long yr, mon, day, hr;

  get (&yr, &mon, &day, &hr);
  aipTime a(yr, mon, day, hr, 0, 0);

  x.get (&yr, &mon, &day, &hr);
  aipTime b(yr, mon, day, hr, 0, 0);

  return a.hours_since(b);

}

//----------------------------------------------------------------------
//  return the difference in days after x

long aipTime::days_after (const aipTime& x) const {

  long yr, mon, day;

  get (&yr, &mon, &day);
  aipTime a(yr, mon, day, 0, 0, 0);

  x.get (&yr, &mon, &day);
  aipTime b(yr, mon, day, 0, 0, 0);

  return a.days_since(b);

}

//----------------------------------------------------------------------
//  get components for non-null pointers - return zero on failure

int aipTime::get (long *a_year, long *a_mon, long *a_day, 
                  long *a_hour, long *a_min, long *a_sec,
                  char *s_mon,  char *s_weekday) const {

  if (!is_valid()) {
    if (a_year)   *a_year = 0;
    if (a_mon)    *a_mon  = 0;
    if (a_day)    *a_day  = 0;
    if (a_hour)   *a_hour = 0;
    if (a_min)    *a_min  = 0;
    if (a_sec)    *a_sec  = 0;
    if (s_mon)     s_mon[0]     = '\0';
    if (s_weekday) s_weekday[0] = '\0';
    return 0;
  }

  struct tm *ts = localtime (&m_time);

  if (a_year) *a_year = ts->tm_year + 1900;
  if (a_mon)  *a_mon  = ts->tm_mon + 1;
  if (a_day)  *a_day  = ts->tm_mday;
  if (a_hour) *a_hour = ts->tm_hour;
  if (a_min)  *a_min  = ts->tm_min;
  if (a_sec)  *a_sec  = ts->tm_sec;

  if (s_mon)     aip_strncpy(s_mon, aip_Month_Abbrv[ts->tm_mon], 3);

  if (s_weekday) aip_strncpy(s_weekday, 
                             aip_Day_Abbrv[ts->tm_wday], 3);

  return 1;

}

//----------------------------------------------------------------------
//  write the date to dstr - ex: "17/Jan/2008"

void aipTime::dd_mon_yyyy (char *dstr) const {

  if (!dstr) return;

  long dyear, dmon, dday;

  if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }

  const char *smon = aip_str_month(dmon);

  sprintf (dstr, "%02ld/%s/%ld", dday, smon, dyear);

}

//----------------------------------------------------------------------
//  write the date to dstr - ex: "17/Jan/2008_16:30"

void aipTime::dd_mon_yyyy_hh_mm (char *dstr) const {

  if (!dstr) return;

  long dyear, dmon, dday, dhour, dmin;

  if ( ! get(&dyear,&dmon,&dday,&dhour,&dmin) ) { *dstr='\0'; return; }

  const char *smon = aip_str_month(dmon);

  sprintf (dstr, "%02ld/%s/%ld_%02ld:%02ld", 
                  dday, smon, dyear, dhour, dmin);

}

//----------------------------------------------------------------------
//  write the date to dstr - ex: "01/17/08"

void aipTime::dd_mm_yy (char *dstr) const {

  if (!dstr) return;

  long dyear, dmon, dday;

  if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }

  sprintf (dstr, "%02ld/%02ld/%02ld", dday, dmon, dyear%100);

}

//----------------------------------------------------------------------
//  write the date to dstr - ex: "01/17/2008"

void aipTime::dd_mm_yyyy (char *dstr) const {

  if (!dstr) return;

  long dyear, dmon, dday;

  if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }

  sprintf (dstr, "%02ld/%02ld/%4ld", dday, dmon, dyear);

}

//----------------------------------------------------------------------
//  write the date to dstr (insert-format) - ex: "2008-01-17"

void aipTime::yyyy_mm_dd (char *dstr) const {

  if (!dstr) return;

  long dyear, dmon, dday;

  if ( ! get(&dyear,&dmon,&dday) ) { *dstr='\0'; return; }

  sprintf (dstr, "%04ld-%02ld-%2ld", dyear, dmon, dday);

}

//----------------------------------------------------------------------
//  return the date as a long

long aipTime::yyyymmdd () const {

  long dyear, dmon, dday;

  if ( ! get(&dyear,&dmon,&dday) ) return 0;

  return ( dyear*10000 + dmon*100 + dday );

}

//----------------------------------------------------------------------
//  return the hhmm as a long

long aipTime::hhmm () const {

  long dyear, dmon, dday, dhour, dmin;

  if ( ! get(&dyear,&dmon,&dday,&dhour,&dmin) ) return 0;

  return ( dhour*100 + dmin );

}

//======================================================================
//  aipTimeOfDay
//
//----------------------------------------------------------------------
//  set from components

void aipTimeOfDay::set (long a_hour, long a_min) {

  m_hour    = a_hour;
  m_minute  = a_min;

  if (m_hour < 0 || m_hour > 23 ||
      m_minute < 0 || m_minute > 59) reset();

}

//----------------------------------------------------------------------
//  set from another instance of aipTimeOfDay

void aipTimeOfDay::set (const aipTimeOfDay& x) {

  set (x.hour(), x.minute());
  if (!is_valid()) reset();

}

//----------------------------------------------------------------------
//  set from a string - ex: "16:30" or "4:30 pm"

void aipTimeOfDay::set (const char *x) {

  long hr, min;
  char  ampm[2];     // only care whether first char is 'p' or 'P'

  if (x && *x) x = aip_get_val(x, 2, &hr);

  if (x && *x) x = aip_get_val(x, 2, &min);

  if (x && *x) x = aip_get_str(x, 1, ampm);
  if (x) {
    if (*ampm == 'p' || *ampm == 'P') {      // pm
      if (hr <= 12) hr += 12;  // convert to 24 hour clock
    }
  }

  if (hr == 24) hr = 0;

  set (hr, min);

}

//----------------------------------------------------------------------
//  compare functions

int aipTimeOfDay::eq (const aipTimeOfDay& x) const {
  return m_minute == x.minute() && m_hour == x.hour();
}

int aipTimeOfDay::ne (const aipTimeOfDay& x) const {
  return !eq(x);
}

int aipTimeOfDay::lt (const aipTimeOfDay& x) const {
  if (m_hour < x.hour()) return 1;
  if (m_hour == x.hour()) {
    if ( m_minute < x.minute()) return 1;
  }
  return 0;
}

int aipTimeOfDay::gt (const aipTimeOfDay& x) const {
  return !lt(x) && !eq(x);
}

int aipTimeOfDay::le (const aipTimeOfDay& x) const {
  return lt(x) || eq(x);
}

int aipTimeOfDay::ge (const aipTimeOfDay& x) const {
  return !lt(x);
}


//----------------------------------------------------------------------
//  add hours to this time-of-day

void aipTimeOfDay::add_hours   (long num) {

  m_hour += num;

  if (m_hour >= 24) m_hour %= 24;

}

//----------------------------------------------------------------------
//  add minutes to this time-of-day

void aipTimeOfDay::add_minutes (long num) {

  m_minute += num;

  if (m_minute >= 60) {
    long nhour = m_minute / 60;
    m_minute %= 60;
    if (nhour > 0) add_hours(nhour);
  }

}

//----------------------------------------------------------------------
//  return the number of hours since x

long aipTimeOfDay::hours_since (const aipTimeOfDay& x) {

  long nhour = m_hour - x.hour();

  return nhour;

}

//----------------------------------------------------------------------
//  return the number of minutes since x

long aipTimeOfDay::minutes_since (const aipTimeOfDay& x) {

  long nmin  = (m_minute - x.minute()) +
               (m_hour   - x.hour()) * 60;

  return nmin;

}

//----------------------------------------------------------------------
//  write the time-of-day to the pointer on a 24 hour clock
//
//  ex: "08:30"  "16:45"     writes 6 chars (with null)

void aipTimeOfDay::hh_mm (char *dstr) const {

  if (!dstr) return;

  sprintf (dstr, "%02d:%02d", m_hour, m_minute);

}

//----------------------------------------------------------------------
//  write the time-of-day with seconds to the pointer on a 24 hour clock
//
//  ex: "08:30:00"  "16:45:00   writes 9 chars (with null)

void aipTimeOfDay::hh_mm_ss (char *dstr) const {

  if (!dstr) return;

  sprintf (dstr, "%02d:%02d:00", m_hour, m_minute);

}

//----------------------------------------------------------------------
//  write the time-of-day to the pointer on a 12 hour clock
//
//  ex: "08:30 am"  "04:45 pm"     writes 9 chars (with null)

void aipTimeOfDay::hh_mm_12 (char *dstr) const {

  if (!dstr) return;

  int hr = m_hour;

  char ampm[3];
  if (hr > 12) {
    strcpy (ampm, "pm");
    hr -= 12;
  } else {
    strcpy (ampm, "am");
  }

  sprintf (dstr, "%02d:%02d %s", hr, m_minute, ampm);

}

//----------------------------------------------------------------------

//======================================================================
//                           License
//
//   Permission is hereby granted, free of charge, to any 
//   person obtaining a copy of this software and associated 
//   documentation files (the "Software"), to deal in the Software 
//   without restriction, including without limitation the rights 
//   to use, copy, modify, merge, publish, distribute, sublicense, 
//   and/or sell copies of the Software, and to permit persons to 
//   whom the Software is furnished to do so, subject to the 
//   following conditions:
//
//   The copyright notice and this license shall be included in all 
//   copies or substantial portions of the Software.
//
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
//   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
//   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
//   NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
//   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
//   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
//   OTHER DEALINGS IN THE SOFTWARE.
//
//
//**********************************************************************