Update version annunciator to follow new variable.
[asdcplib.git] / src / KM_util.cpp
index f80e4c7fd0c2a87a4ba30ce2bb3ee2ad3a865416..43b00a4211ccd0cfe3c9f81425719eb8a087ade8 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2006, John Hurst
+Copyright (c) 2005-2009, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -34,11 +34,21 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <KM_memio.h>
 #include <KM_fileio.h>
 #include <KM_log.h>
+#include <KM_tai.h>
 #include <ctype.h>
 #include <list>
 #include <map>
 #include <string>
 
+#define CONFIG_RANDOM_UUID
+
+const char*
+Kumu::Version()
+{
+  return PACKAGE_VERSION;
+}
+
+
 //------------------------------------------------------------------------------------------
 
 // Result_t Internals
@@ -67,8 +77,7 @@ Kumu::Result_t::Find(int v)
        return *s_ResultMap[i].result;
     }
 
-  DefaultLogSink().Error("Unknown result code: %ld\n", v);
-  return RESULT_FAIL;
+  return RESULT_UNKNOWN;
 }
 
 //
@@ -365,6 +374,38 @@ Kumu::hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* conv_size)
   return 0;
 }
 
+#ifdef CONFIG_RANDOM_UUID
+
+// convert a memory region to a NULL-terminated hexadecimal string
+//
+static const char*
+bin2hex_rand(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
+{
+  if ( bin_buf == 0
+       || str_buf == 0
+       || ((bin_len * 2) + 1) > str_len )
+    return 0;
+
+  char* p = str_buf;
+  Kumu::mem_ptr<byte_t> rand_buf = new byte_t[bin_len];
+  Kumu::FortunaRNG RNG;
+  RNG.FillRandom(rand_buf, bin_len);
+
+  for ( ui32_t i = 0; i < bin_len; i++ )
+    {
+      *p = (bin_buf[i] >> 4) & 0x0f;
+      *p += *p < 10 ? 0x30 : (( ((rand_buf[i] & 0x01) == 0) ? 0x61 : 0x41 ) - 10);
+      p++;
+
+      *p = bin_buf[i] & 0x0f;
+      *p += *p < 10 ? 0x30 : (( (((rand_buf[i] >> 1) & 0x01) == 0) ? 0x61 : 0x41 ) - 10);
+      p++;
+    }
+
+  *p = '\0';
+  return str_buf;
+}
+#endif
 
 // convert a memory region to a NULL-terminated hexadecimal string
 //
@@ -376,6 +417,12 @@ Kumu::bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_l
        || ((bin_len * 2) + 1) > str_len )
     return 0;
 
+#ifdef CONFIG_RANDOM_UUID
+  const char* use_random_uuid  = getenv("KM_USE_RANDOM_UUID");
+  if ( use_random_uuid != 0 && use_random_uuid[0] != 0 && use_random_uuid[0] != '0' )
+    return bin2hex_rand(bin_buf, bin_len, str_buf, str_len);
+#endif
+
   char* p = str_buf;
 
   for ( ui32_t i = 0; i < bin_len; i++ )
@@ -713,64 +760,80 @@ Kumu::Timestamp::AddHours(i32_t hours)
 
 #include <time.h>
 
-#define TIMESTAMP_TO_TM(ts, t) \
-  (t)->tm_year = (ts).Year - 1900;   /* year - 1900 */ \
-  (t)->tm_mon  = (ts).Month - 1;     /* month of year (0 - 11) */ \
-  (t)->tm_mday = (ts).Day;           /* day of month (1 - 31) */ \
-  (t)->tm_hour = (ts).Hour;          /* hours (0 - 23) */ \
-  (t)->tm_min  = (ts).Minute;        /* minutes (0 - 59) */ \
-  (t)->tm_sec  = (ts).Second;        /* seconds (0 - 60) */
-
-#define TM_TO_TIMESTAMP(t, ts) \
-  (ts).Year   = (t)->tm_year + 1900;    /* year - 1900 */ \
-  (ts).Month  = (t)->tm_mon + 1;     /* month of year (0 - 11) */ \
-  (ts).Day    = (t)->tm_mday;    /* day of month (1 - 31) */ \
-  (ts).Hour   = (t)->tm_hour;    /* hours (0 - 23) */ \
-  (ts).Minute = (t)->tm_min;     /* minutes (0 - 59) */ \
-  (ts).Second = (t)->tm_sec;     /* seconds (0 - 60) */
+#define TIMESTAMP_TO_CALTIME(ts, ct)                                  \
+  (ct)->date.year  = (ts).Year;    /* year */                         \
+  (ct)->date.month = (ts).Month;   /* month of year (1 - 12) */               \
+  (ct)->date.day   = (ts).Day;     /* day of month (1 - 31) */        \
+  (ct)->hour       = (ts).Hour;    /* hours (0 - 23) */                       \
+  (ct)->minute     = (ts).Minute;  /* minutes (0 - 59) */             \
+  (ct)->second     = (ts).Second;  /* seconds (0 - 60) */             \
+  (ct)->offset     = 0;
+
+#define CALTIME_TO_TIMESTAMP(ct, ts)                                  \
+  assert((ct)->offset == 0);                                          \
+  (ts).Year   = (ct)->date.year;    /* year */                        \
+  (ts).Month  = (ct)->date.month;   /* month of year (1 - 12) */       \
+  (ts).Day    = (ct)->date.day;     /* day of month (1 - 31) */               \
+  (ts).Hour   = (ct)->hour;         /* hours (0 - 23) */              \
+  (ts).Minute = (ct)->minute;       /* minutes (0 - 59) */            \
+  (ts).Second = (ct)->second;       /* seconds (0 - 60) */
+
 
 //
 Kumu::Timestamp::Timestamp() :
-  Year(0), Month(0),  Day(0), Hour(0), Minute(0), Second(0)
+  Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
 {
-  time_t t_now = time(0);
-  struct tm*  now = gmtime(&t_now);
-  TM_TO_TIMESTAMP(now, *this);
+  Kumu::TAI::tai now;
+  Kumu::TAI::caltime ct;
+  now.now();
+  ct = now;
+  CALTIME_TO_TIMESTAMP(&ct, *this)
 }
 
 //
 bool
 Kumu::Timestamp::operator<(const Timestamp& rhs) const
 {
-  struct tm lhtm, rhtm;
-  TIMESTAMP_TO_TM(*this, &lhtm);
-  TIMESTAMP_TO_TM(rhs, &rhtm);
-  return ( timegm(&lhtm) < timegm(&rhtm) );
+  Kumu::TAI::caltime lh_ct, rh_ct;
+  TIMESTAMP_TO_CALTIME(*this, &lh_ct)
+  TIMESTAMP_TO_CALTIME(rhs, &rh_ct)
+
+  Kumu::TAI::tai lh_tai, rh_tai;
+  lh_tai = lh_ct;
+  rh_tai = rh_ct;
+
+  return ( lh_tai.x < rh_tai.x );
 }
 
 //
 bool
 Kumu::Timestamp::operator>(const Timestamp& rhs) const
 {
-  struct tm lhtm, rhtm;
-  TIMESTAMP_TO_TM(*this, &lhtm);
-  TIMESTAMP_TO_TM(rhs, &rhtm);
-  return ( timegm(&lhtm) > timegm(&rhtm) );
+  Kumu::TAI::caltime lh_ct, rh_ct;
+  TIMESTAMP_TO_CALTIME(*this, &lh_ct)
+  TIMESTAMP_TO_CALTIME(rhs, &rh_ct)
+
+  Kumu::TAI::tai lh_tai, rh_tai;
+  lh_tai = lh_ct;
+  rh_tai = rh_ct;
+
+  return ( lh_tai.x > rh_tai.x );
 }
 
 //
 void
 Kumu::Timestamp::AddDays(i32_t days)
 {
-  struct tm current;
+  Kumu::TAI::caltime ct;
+  Kumu::TAI::tai t;
 
   if ( days != 0 )
     {
-      TIMESTAMP_TO_TM(*this, &current);
-      time_t adj_time = timegm(&current);
-      adj_time += 86400 * days;
-      struct tm*  now = gmtime(&adj_time);
-      TM_TO_TIMESTAMP(now, *this);
+      TIMESTAMP_TO_CALTIME(*this, &ct)
+      t = ct;
+      t.add_days(days);
+      ct = t;
+      CALTIME_TO_TIMESTAMP(&ct, *this)
     }
 }
 
@@ -778,22 +841,23 @@ Kumu::Timestamp::AddDays(i32_t days)
 void
 Kumu::Timestamp::AddHours(i32_t hours)
 {
-  struct tm current;
+  Kumu::TAI::caltime ct;
+  Kumu::TAI::tai t;
 
   if ( hours != 0 )
     {
-      TIMESTAMP_TO_TM(*this, &current);
-      time_t adj_time = timegm(&current);
-      adj_time += 3600 * hours;
-      struct tm*  now = gmtime(&adj_time);
-      TM_TO_TIMESTAMP(now, *this);
+      TIMESTAMP_TO_CALTIME(*this, &ct)
+      t = ct;
+      t.add_hours(hours);
+      ct = t;
+      CALTIME_TO_TIMESTAMP(&ct, *this)
     }
 }
 
 #endif // KM_WIN32
 
 
-Kumu::Timestamp::Timestamp(const Timestamp& rhs)
+Kumu::Timestamp::Timestamp(const Timestamp& rhs) : IArchive()
 {
   Year   = rhs.Year;
   Month  = rhs.Month;
@@ -925,7 +989,7 @@ Kumu::Timestamp::DecodeString(const char* datestr)
          ui32_t TZ_mm = atoi(datestr + 23);
       
          if ( TZ_mm != 0 )
-           DefaultLogSink().Warn("Ignoring minutes in timezone offset: %u\n", TZ_mm);
+           Kumu::DefaultLogSink().Warn("Ignoring minutes in timezone offset: %u\n", TZ_mm);
          
          if ( TZ_hh > 12 )
            return false;
@@ -937,8 +1001,8 @@ Kumu::Timestamp::DecodeString(const char* datestr)
 
   if ( datestr[char_count] != 0 )
     {
-      DefaultLogSink().Error("Unexpected extra characters in string: %s (%ld)\n",
-                            datestr, char_count);
+      Kumu::DefaultLogSink().Error("Unexpected extra characters in string: %s (%ld)\n",
+                                  datestr, char_count);
       return false;
     }
 
@@ -950,11 +1014,12 @@ Kumu::Timestamp::DecodeString(const char* datestr)
     return false;
   SYSTIME_TO_TIMESTAMP(&st, *this);
 #else
-  struct tm stm;
-  TIMESTAMP_TO_TM(TmpStamp, &stm);
-  if ( timegm(&stm) == 0 )
-    return false;
-  TM_TO_TIMESTAMP(&stm, *this);
+  Kumu::TAI::tai t;
+  Kumu::TAI::caltime ct;
+  TIMESTAMP_TO_CALTIME(TmpStamp, &ct);
+  t = ct; // back and forth to tai to normalize offset
+  ct = t;
+  CALTIME_TO_TIMESTAMP(&ct, *this)
 #endif
 
   return true;