summaryrefslogtreecommitdiff
path: root/asdcplib/src/KM_util.cpp
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-01-14 23:54:53 +0000
committerCarl Hetherington <cth@carlh.net>2016-01-14 23:54:53 +0000
commita2374eb06a0f6d391d1d5ae04f50ce5e8076173a (patch)
treea3b83b31e739e7b5312a3a99e9a1c1446ff29bbb /asdcplib/src/KM_util.cpp
parent38ff2954f40131a12aa8a037b9fc6c4abd3894b9 (diff)
Use out-of-tree asdcplib-cth
Diffstat (limited to 'asdcplib/src/KM_util.cpp')
-rwxr-xr-xasdcplib/src/KM_util.cpp1141
1 files changed, 0 insertions, 1141 deletions
diff --git a/asdcplib/src/KM_util.cpp b/asdcplib/src/KM_util.cpp
deleted file mode 100755
index b1814840..00000000
--- a/asdcplib/src/KM_util.cpp
+++ /dev/null
@@ -1,1141 +0,0 @@
-/*
-Copyright (c) 2005-2012, John Hurst
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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.
-*/
- /*! \file KM_util.cpp
- \version $Id: KM_util.cpp,v 1.40 2012/02/22 19:20:33 jhurst Exp $
- \brief Utility functions
- */
-
-#include <KM_util.h>
-#include <KM_prng.h>
-#include <KM_memio.h>
-#include <KM_fileio.h>
-#include <KM_log.h>
-#include <KM_mutex.h>
-#include <ctype.h>
-#include <list>
-#include <map>
-#include <string>
-
-bool Kumu::libdcp_test = false;
-
-const char*
-Kumu::Version()
-{
- return PACKAGE_VERSION;
-}
-
-
-//------------------------------------------------------------------------------------------
-
-// Result_t Internals
-
-struct map_entry_t
-{
- int rcode;
- Kumu::Result_t* result;
-};
-
-
-// WIN32 does not init this in time for use with Result_t(...) below, so it is
-// now a pointer that Result_t(...) fills in when it needs it.
-static Kumu::Mutex* s_MapLock = 0;
-
-static ui32_t s_MapSize = 0;
-static const ui32_t MapMax = 2048;
-static struct map_entry_t s_ResultMap[MapMax];
-
-
-//
-const Kumu::Result_t&
-Kumu::Result_t::Find(int v)
-{
- if ( v == 0 )
- return RESULT_OK;
-
- assert(s_MapLock);
- AutoMutex L(*s_MapLock);
-
- for ( ui32_t i = 0; i < s_MapSize; ++i )
- {
- if ( s_ResultMap[i].rcode == v )
- return *s_ResultMap[i].result;
- }
-
- return RESULT_UNKNOWN;
-}
-
-//
-Kumu::Result_t
-Kumu::Result_t::Delete(int v)
-{
- if ( v < -99 || v > 99 )
- {
- DefaultLogSink().Error("Cannot delete core result code: %ld\n", v);
- return RESULT_FAIL;
- }
-
- assert(s_MapLock);
- AutoMutex L(*s_MapLock);
-
- for ( ui32_t i = 0; i < s_MapSize; ++i )
- {
- if ( s_ResultMap[i].rcode == v )
- {
- for ( ++i; i < s_MapSize; ++i )
- s_ResultMap[i-1] = s_ResultMap[i];
-
- --s_MapSize;
- return RESULT_OK;
- }
- }
-
- return RESULT_FALSE;
-}
-
-//
-unsigned int
-Kumu::Result_t::End()
-{
- return s_MapSize;
-}
-
-//
-const Kumu::Result_t&
-Kumu::Result_t::Get(unsigned int i)
-{
- return *s_ResultMap[i].result;
-}
-
-//
-Kumu::Result_t::Result_t(int v, const char* s, const char* l) : value(v), label(l), symbol(s)
-{
- assert(l);
- assert(s);
-
- if ( v == 0 )
- return;
-
- // This may seem tricky, but it is certain that the static values declared in KM_error.h will
- // be created (and thus this method will be called) before main(...) is called. It is not
- // until then that threads could be created, thus the mutex will exist before multi-threaded
- // access could occur.
- if ( s_MapLock == 0 )
- s_MapLock = new Kumu::Mutex;
-
- assert(s_MapLock);
- AutoMutex L(*s_MapLock);
-
- for ( ui32_t i = 0; i < s_MapSize; ++i )
- {
- if ( s_ResultMap[i].rcode == v )
- return;
- }
-
- assert(s_MapSize+1 < MapMax);
-
- s_ResultMap[s_MapSize].rcode = v;
- s_ResultMap[s_MapSize].result = this;
- ++s_MapSize;
-
- return;
-}
-
-Kumu::Result_t::~Result_t() {}
-
-
-//------------------------------------------------------------------------------------------
-// DTrace internals
-
-static int s_DTraceSequence = 0;
-
-Kumu::DTrace_t::DTrace_t(const char* Label, Kumu::Result_t* Watch, int Line, const char* File)
- : m_Label(Label), m_Watch(Watch), m_Line(Line), m_File(File)
-{
- m_Sequence = s_DTraceSequence++;
- DefaultLogSink().Debug("@enter %s[%d] (%s at %d)\n", m_Label, m_Sequence, m_File, m_Line);
-}
-
-Kumu::DTrace_t::~DTrace_t()
-{
- if ( m_Watch != 0 )
- DefaultLogSink().Debug("@exit %s[%d]: %s\n", m_Label, m_Sequence, m_Watch->Label());
- else
- DefaultLogSink().Debug("@exit %s[%d]\n", m_Label, m_Sequence);
-}
-
-//------------------------------------------------------------------------------------------
-
-
-const char fill = '=';
-const char* base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-const byte_t decode_map[] =
-{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
- 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
- 0xff, 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 26, 27, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-
-// Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
-// if the binary buffer was large enough to hold the result. If the output buffer
-// is too small or any of the pointer arguments are NULL, the subroutine will
-// return 0.
-//
-const char*
-Kumu::base64encode(const byte_t* buf, ui32_t buf_len, char* strbuf, ui32_t strbuf_len)
-{
- ui32_t out_char = 0;
- ui32_t i, block_len, diff;
-
- if ( buf == 0 || strbuf == 0 )
- return 0;
-
- if ( strbuf_len < base64_encode_length(buf_len) + 1 )
- return 0;
-
- block_len = buf_len;
-
- while ( block_len % 3 )
- block_len--;
-
- for ( i = 0; i < block_len; i += 3 )
- {
- strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
- strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
- strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) | ( buf[2] >> 6 ) )];
- strbuf[out_char++] = base64_chars[( buf[2] & 0x3f )];
- buf += 3;
- }
-
- if ( i < buf_len )
- {
- diff = buf_len - i;
- assert(diff > 0);
- assert(diff < 3);
-
- strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
-
- if ( diff == 1 )
- {
- strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) )];
- strbuf[out_char++] = fill;
- }
- else if ( diff == 2 )
- {
- strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
- strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) )];
- }
-
- strbuf[out_char++] = fill;
- }
-
- strbuf[out_char] = 0;
- return strbuf;;
-}
-
-
-
-
-// Convert NULL-terminated UTF-8 Base64 string to binary, returns 0 if
-// the binary buffer was large enough to hold the result. The output parameter
-// 'char_count' will contain the length of the converted string. If the output
-// buffer is too small or any of the pointer arguments are NULL, the subroutine
-// will return -1 and set 'char_count' to the required buffer size. No data will
-// be written to 'buf' if the subroutine fails.
-//
-i32_t
-Kumu::base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count)
-{
- register byte_t c = 0, d = 0;
- register ui32_t phase = 0, i = 0;
-
- if ( str == 0 || buf == 0 || char_count == 0 )
- return -1;
-
- while ( *str != 0 && i < buf_len )
- {
- c = decode_map[(int)*str++];
- if ( c == 0xff ) continue;
- if ( c == 0xfe ) break;
-
- switch ( phase++ )
- {
- case 0:
- buf[i++] = c << 2;
- break;
-
- case 1:
- buf[i - 1] |= c >> 4;
- d = c;
- break;
-
- case 2:
- buf[i++] = ( d << 4 ) | ( c >> 2 );
- d = c;
- break;
-
- case 3:
- buf[i++] = ( d << 6 ) | c;
- phase = 0;
- break;
- }
- }
-
- *char_count = i;
- return 0;
-}
-
-//------------------------------------------------------------------------------------------
-
-// convert utf-8 hext string to bin
-i32_t
-Kumu::hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* conv_size)
-{
- KM_TEST_NULL_L(str);
- KM_TEST_NULL_L(buf);
- KM_TEST_NULL_L(conv_size);
-
- *conv_size = 0;
-
- if ( str[0] == 0 ) // nothing to convert
- return 0;
-
- for ( int j = 0; str[j]; j++ )
- {
- if ( isxdigit(str[j]) )
- (*conv_size)++;
- }
-
- if ( *conv_size & 0x01 ) (*conv_size)++;
- *conv_size /= 2;
-
- if ( *conv_size > buf_len )// maximum possible data size
- return -1;
-
- *conv_size = 0;
-
- int phase = 0; // track high/low nybble
-
- // for each character, fill in the high nybble then the low
- for ( int i = 0; str[i]; i++ )
- {
- if ( ! isxdigit(str[i]) )
- continue;
-
- byte_t val = str[i] - ( isdigit(str[i]) ? 0x30 : ( isupper(str[i]) ? 0x37 : 0x57 ) );
-
- if ( phase == 0 )
- {
- buf[*conv_size] = val << 4;
- phase++;
- }
- else
- {
- buf[*conv_size] |= val;
- phase = 0;
- (*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
-//
-const char*
-Kumu::bin2hex(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;
-
-#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++ )
- {
- *p = (bin_buf[i] >> 4) & 0x0f;
- *p += *p < 10 ? 0x30 : 0x61 - 10;
- p++;
-
- *p = bin_buf[i] & 0x0f;
- *p += *p < 10 ? 0x30 : 0x61 - 10;
- p++;
- }
-
- *p = '\0';
- return str_buf;
-}
-
-
-// spew a range of bin data as hex
-void
-Kumu::hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream)
-{
- if ( buf == 0 )
- return;
-
- if ( stream == 0 )
- stream = stderr;
-
- static ui32_t row_len = 16;
- const byte_t* p = buf;
- const byte_t* end_p = p + dump_len;
-
- for ( ui32_t line = 0; p < end_p; line++ )
- {
- fprintf(stream, " %06x: ", line);
- ui32_t i;
- const byte_t* pp;
-
- for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
- fprintf(stream, "%02x ", *pp);
-
- while ( i++ < row_len )
- fputs(" ", stream);
-
- for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
- fputc((isprint(*pp) ? *pp : '.'), stream);
-
- fputc('\n', stream);
- p += row_len;
- }
-}
-
-//
-const char*
-Kumu::bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
-{
- ui32_t i, j, k;
-
- if ( str_len < 34 || bin_len != UUID_Length )
- return 0;
-
- if ( bin2hex(bin_buf, bin_len, str_buf, str_len) == 0 )
- return 0;
-
- // shift the node id
- for ( k = 19, i = 12; i > 0; i-- )
- str_buf[k+i+4] = str_buf[k+i];
-
- // shift the time (mid+hi+clk)
- for ( k = 15, j = 3; k > 6; k -= 4, j-- )
- {
- for ( i = 4; i > 0; i-- )
- str_buf[k+i+j] = str_buf[k+i];
- }
-
- // add in the hyphens and trainling null
- for ( i = 8; i < 24; i += 5 )
- str_buf[i] = '-';
-
- str_buf[36] = 0;
- return str_buf;
-}
-
-//
-void
-Kumu::GenRandomValue(UUID& ID)
-{
- byte_t tmp_buf[UUID_Length];
- GenRandomUUID(tmp_buf);
- ID.Set(tmp_buf);
-}
-
-#ifdef LIBDCP_POSIX
-void
-Kumu::ResetTestRNG()
-{
- FortunaRNG RNG;
- RNG.Reset();
-}
-#endif
-
-//
-void
-Kumu::GenRandomUUID(byte_t* buf)
-{
- FortunaRNG RNG;
- RNG.FillRandom(buf, UUID_Length);
- buf[6] &= 0x0f; // clear bits 4-7
- buf[6] |= 0x40; // set UUID version
- buf[8] &= 0x3f; // clear bits 6&7
- buf[8] |= 0x80; // set bit 7
-}
-
-//
-void
-Kumu::GenRandomValue(SymmetricKey& Key)
-{
- byte_t tmp_buf[SymmetricKey_Length];
- FortunaRNG RNG;
- RNG.FillRandom(tmp_buf, SymmetricKey_Length);
- Key.Set(tmp_buf);
-}
-
-
-//------------------------------------------------------------------------------------------
-// read a ber value from the buffer and compare with test value.
-// Advances buffer to first character after BER value.
-//
-bool
-Kumu::read_test_BER(byte_t **buf, ui64_t test_value)
-{
- if ( buf == 0 )
- return false;
-
- if ( ( **buf & 0x80 ) == 0 )
- return false;
-
- ui64_t val = 0;
- ui8_t ber_size = ( **buf & 0x0f ) + 1;
-
- if ( ber_size > 9 )
- return false;
-
- for ( ui8_t i = 1; i < ber_size; i++ )
- {
- if ( (*buf)[i] > 0 )
- val |= (ui64_t)((*buf)[i]) << ( ( ( ber_size - 1 ) - i ) * 8 );
- }
-
- *buf += ber_size;
- return ( val == test_value );
-}
-
-
-//
-bool
-Kumu::read_BER(const byte_t* buf, ui64_t* val)
-{
- ui8_t ber_size, i;
-
- if ( buf == 0 || val == 0 )
- return false;
-
- if ( ( *buf & 0x80 ) == 0 )
- return false;
-
- *val = 0;
- ber_size = ( *buf & 0x0f ) + 1;
-
- if ( ber_size > 9 )
- return false;
-
- for ( i = 1; i < ber_size; i++ )
- {
- if ( buf[i] > 0 )
- *val |= (ui64_t)buf[i] << ( ( ( ber_size - 1 ) - i ) * 8 );
- }
-
- return true;
-}
-
-
-static const ui64_t ber_masks[9] =
- { ui64_C(0xffffffffffffffff), ui64_C(0xffffffffffffff00),
- ui64_C(0xffffffffffff0000), ui64_C(0xffffffffff000000),
- ui64_C(0xffffffff00000000), ui64_C(0xffffff0000000000),
- ui64_C(0xffff000000000000), ui64_C(0xff00000000000000),
- 0
- };
-
-//
-ui32_t
-Kumu::get_BER_length_for_value(ui64_t val)
-{
- for ( ui32_t i = 0; i < 9; i++ )
- {
- if ( ( val & ber_masks[i] ) == 0 )
- return i + 1;
- }
-
- ui64Printer tmp_i(val);
- DefaultLogSink().Error("BER integer encoding not supported for large value %s\n", tmp_i.c_str());
- return 0;
-}
-
-//
-bool
-Kumu::write_BER(byte_t* buf, ui64_t val, ui32_t ber_len)
-{
- if ( buf == 0 )
- return false;
-
- if ( ber_len == 0 )
- { // calculate default length
- if ( val < 0x01000000L )
- ber_len = 4;
- else if ( val < ui64_C(0x0100000000000000) )
- ber_len = 8;
- else
- ber_len = 9;
- }
- else
- { // sanity check BER length
- if ( ber_len > 9 )
- {
- DefaultLogSink().Error("BER integer length %u exceeds maximum size of 9\n", ber_len);
- return false;
- }
-
- if ( ( val & ber_masks[ber_len - 1] ) != 0 )
- {
- ui64Printer tmp_i(val);
- DefaultLogSink().Error("BER integer length %u too small for value %s\n", ber_len, tmp_i.c_str());
- return false;
- }
- }
-
- buf[0] = 0x80 + ( ber_len - 1 );
-
- for ( ui32_t i = ber_len - 1; i > 0; i-- )
- {
- buf[i] = (ui8_t)(val & 0xff);
- val >>= 8;
- }
-
- return true;
-}
-
-
-//------------------------------------------------------------------------------------------
-
-#ifndef KM_WIN32
-#include <time.h>
-#endif
-
-//
-Kumu::Timestamp::Timestamp() : m_TZOffsetMinutes(0) {
- if (libdcp_test)
- {
- m_Timestamp.x = 42;
- }
- else
- {
- m_Timestamp.now();
- }
-}
-
-Kumu::Timestamp::Timestamp(const Timestamp& rhs) {
- m_Timestamp = rhs.m_Timestamp;
- m_TZOffsetMinutes = rhs.m_TZOffsetMinutes;
-}
-
-Kumu::Timestamp::Timestamp(const char* datestr) : m_TZOffsetMinutes(0) {
- DecodeString(datestr);
-}
-
-Kumu::Timestamp::~Timestamp() {
-}
-
-//
-const Kumu::Timestamp&
-Kumu::Timestamp::operator=(const Timestamp& rhs)
-{
- m_Timestamp = rhs.m_Timestamp;
- m_TZOffsetMinutes = rhs.m_TZOffsetMinutes;
- return *this;
-}
-
-bool Kumu::Timestamp::operator<(const Timestamp& rhs) const {
- return m_Timestamp.x < rhs.m_Timestamp.x;
-}
-
-bool Kumu::Timestamp::operator>(const Timestamp& rhs) const {
- return m_Timestamp.x > rhs.m_Timestamp.x;
-}
-
-bool Kumu::Timestamp::operator==(const Timestamp& rhs) const {
- return m_Timestamp.x == rhs.m_Timestamp.x;
-}
-
-bool Kumu::Timestamp::operator!=(const Timestamp& rhs) const {
- return m_Timestamp.x != rhs.m_Timestamp.x;
-}
-
-//
-void
-Kumu::Timestamp::GetComponents(ui16_t& Year, ui8_t& Month, ui8_t& Day,
- ui8_t& Hour, ui8_t& Minute, ui8_t& Second) const
-{
- TAI::caltime ct;
- ct = m_Timestamp;
- Year = ct.date.year;
- Month = ct.date.month;
- Day = ct.date.day;
- Hour = ct.hour;
- Minute = ct.minute;
- Second = ct.second;
-}
-
-//
-void
-Kumu::Timestamp::SetComponents(const ui16_t& Year, const ui8_t& Month, const ui8_t& Day,
- const ui8_t& Hour, const ui8_t& Minute, const ui8_t& Second)
-{
- TAI::caltime ct;
- ct.date.year = Year;
- ct.date.month = Month;
- ct.date.day = Day;
- ct.hour = Hour;
- ct.minute = Minute;
- ct.second = Second;
- ct.offset = 0;
- m_Timestamp = ct;
- m_TZOffsetMinutes = 0;
-}
-
-// returns false if the requested adjustment is out of range
-bool
-Kumu::Timestamp::SetTZOffsetMinutes(const i32_t& minutes)
-{
- static const i32_t tz_limit = 14 * 60 * 60;
-
- if ( minutes < ( - tz_limit) || minutes > tz_limit )
- return false;
-
- m_TZOffsetMinutes = minutes;
- return true;
-}
-
-//
-const char*
-Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const
-{
- if ( buf_len < ( DateTimeLen + 1 ) )
- return 0;
-
- ui16_t year;
- ui8_t month, day, hour, minute, second;
- ui32_t ofst_hours = 0, ofst_minutes = 0;
- char direction = '+';
-
- if ( m_TZOffsetMinutes == 0 )
- {
- GetComponents(year, month, day, hour, minute, second);
- }
- else
- {
- // calculate local time
- Kumu::Timestamp tmp_t(*this);
- tmp_t.AddMinutes(m_TZOffsetMinutes);
- tmp_t.GetComponents(year, month, day, hour, minute, second);
-
- ofst_hours = abs(m_TZOffsetMinutes) / 60;
- ofst_minutes = abs(m_TZOffsetMinutes) % 60;
-
- if ( m_TZOffsetMinutes < 0 )
- direction = '-';
- }
-
- // 2004-05-01T13:20:00+00:00
- snprintf(str_buf, buf_len,
- "%04hu-%02hu-%02huT%02hu:%02hu:%02hu%c%02hu:%02hu",
- year, month, day, hour, minute, second,
- direction, ofst_hours, ofst_minutes);
-
- return str_buf;
-}
-
-//
-bool
-Kumu::Timestamp::DecodeString(const char* datestr)
-{
- if ( ! ( isdigit(datestr[0]) && isdigit(datestr[1]) && isdigit(datestr[2]) && isdigit(datestr[3]) )
- || datestr[4] != '-'
- || ! ( isdigit(datestr[5]) && isdigit(datestr[6]) )
- || datestr[7] != '-'
- || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) ) )
- return false;
-
- ui32_t char_count = 10;
- TAI::caltime YMDhms;
- YMDhms.offset = 0;
- YMDhms.date.year = atoi(datestr);
- YMDhms.date.month = atoi(datestr + 5);
- YMDhms.date.day = atoi(datestr + 8);
-
- if ( datestr[10] == 'T' )
- {
- if ( ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
- || datestr[13] != ':'
- || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) ) )
- return false;
-
- char_count += 6;
- YMDhms.hour = atoi(datestr + 11);
- YMDhms.minute = atoi(datestr + 14);
-
- if ( datestr[16] == ':' )
- {
- if ( ! ( isdigit(datestr[17]) && isdigit(datestr[18]) ) )
- return false;
-
- char_count += 3;
- YMDhms.second = atoi(datestr + 17);
- }
-
- if ( datestr[19] == '.' )
- {
- if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) && isdigit(datestr[22]) ) )
- return false;
-
- // we don't carry the ms value
- datestr += 4;
- }
-
- if ( datestr[19] == '-' || datestr[19] == '+' )
- {
- if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
- || datestr[22] != ':'
- || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
- return false;
-
- char_count += 6;
-
- ui32_t TZ_hh = atoi(datestr + 20);
- ui32_t TZ_mm = atoi(datestr + 23);
- if ((TZ_hh > 14) || (TZ_mm > 59) || ((TZ_hh == 14) && (TZ_mm > 0)))
- return false;
-
- i32_t TZ_offset = 60 * TZ_hh + TZ_mm;
- if (datestr[19] == '-')
- TZ_offset = -TZ_offset;
- /* at this point, TZ_offset reflects the contents of the string */
-
- /* a negative offset is behind UTC and so needs to increment to
- * convert, while a positive offset must do the reverse */
- YMDhms.offset = TZ_offset;
- }
- else if (datestr[19] == 'Z')
- {
- /* act as if the offset were +00:00 */
- char_count++;
- }
- }
-
- if ( datestr[char_count] != 0 )
- {
- Kumu::DefaultLogSink().Error("Unexpected extra characters in string: %s (%ld)\n",
- datestr, char_count);
- return false;
- }
-
- m_Timestamp = YMDhms;
- m_TZOffsetMinutes = YMDhms.offset;
- return true;
-}
-
-//
-bool
-Kumu::Timestamp::HasValue() const
-{
- return true;
-}
-
-//
-bool
-Kumu::Timestamp::Unarchive(MemIOReader* Reader)
-{
- ui16_t year;
- ui8_t month, day, hour, minute, second, tick;
-
- assert(Reader);
- if ( ! Reader->ReadUi16BE(&year) ) return false;
- if ( ! Reader->ReadUi8(&month) ) return false;
- if ( ! Reader->ReadUi8(&day) ) return false;
- if ( ! Reader->ReadUi8(&hour) ) return false;
- if ( ! Reader->ReadUi8(&minute) ) return false;
- if ( ! Reader->ReadUi8(&second) ) return false;
- if ( ! Reader->ReadUi8(&tick) ) return false;
- SetComponents(year, month, day, hour, minute, second);
- return true;
-}
-
-//
-bool
-Kumu::Timestamp::Archive(MemIOWriter* Writer) const
-{
- assert(Writer);
-
- ui16_t year;
- ui8_t month, day, hour, minute, second, tick = 0;
- GetComponents(year, month, day, hour, minute, second);
-
- if ( ! Writer->WriteUi16BE(year) ) return false;
- if ( ! Writer->WriteUi8(month) ) return false;
- if ( ! Writer->WriteUi8(day) ) return false;
- if ( ! Writer->WriteUi8(hour) ) return false;
- if ( ! Writer->WriteUi8(minute) ) return false;
- if ( ! Writer->WriteUi8(second) ) return false;
- if ( ! Writer->WriteUi8(tick) ) return false;
- return true;
-}
-
-//
-ui64_t
-Kumu::Timestamp::GetCTime() const
-{
- return m_Timestamp.x - ui64_C(4611686018427387914);
-}
-
-
-//------------------------------------------------------------------------------------------
-
-Kumu::MemIOWriter::MemIOWriter(ByteString* Buf)
- : m_p(0), m_capacity(0), m_size(0)
-{
- m_p = Buf->Data();
- m_capacity = Buf->Capacity();
- assert(m_p); assert(m_capacity);
-}
-
-bool
-Kumu::MemIOWriter:: WriteBER(ui64_t i, ui32_t ber_len)
-{
- if ( ( m_size + ber_len ) > m_capacity )
- return false;
-
- if ( ! write_BER(m_p + m_size, i, ber_len) )
- return false;
-
- m_size += ber_len;
- return true;
-}
-
-
-Kumu::MemIOReader::MemIOReader(const ByteString* Buf)
- : m_p(0), m_capacity(0), m_size(0)
-{
- m_p = Buf->RoData();
- m_capacity = Buf->Length();
- assert(m_p); assert(m_capacity);
-}
-
-bool
-Kumu::MemIOReader::ReadBER(ui64_t* i, ui32_t* ber_len)
-{
- if ( i == 0 || ber_len == 0 ) return false;
-
- if ( ( *ber_len = BER_length(m_p + m_size) ) == 0 )
- return false;
-
- if ( ( m_size + *ber_len ) > m_capacity )
- return false;
-
- if ( ! read_BER(m_p + m_size, i) )
- return false;
-
- m_size += *ber_len;
- return true;
-}
-
-//------------------------------------------------------------------------------------------
-
-Kumu::ByteString::ByteString() : m_Data(0), m_Capacity(0), m_Length(0) {}
-
-Kumu::ByteString::ByteString(ui32_t cap) : m_Data(0), m_Capacity(0), m_Length(0)
-{
- Capacity(cap);
-}
-
-Kumu::ByteString::~ByteString()
-{
- if ( m_Data != 0 )
- free(m_Data);
-}
-
-
-// copy the given data into the ByteString, set Length value.
-// Returns error if the ByteString is too small.
-Kumu::Result_t
-Kumu::ByteString::Set(const byte_t* buf, ui32_t buf_len)
-{
- if ( m_Capacity < buf_len )
- return RESULT_ALLOC;
-
- memcpy(m_Data, buf, buf_len);
- m_Length = buf_len;
- return RESULT_OK;
-}
-
-
-// copy the given data into the ByteString, set Length value.
-// Returns error if the ByteString is too small.
-Kumu::Result_t
-Kumu::ByteString::Set(const ByteString& Buf)
-{
- if ( m_Capacity < Buf.m_Capacity )
- return RESULT_ALLOC;
-
- memcpy(m_Data, Buf.m_Data, Buf.m_Length);
- m_Length = Buf.m_Length;
- return RESULT_OK;
-}
-
-
-// Sets the size of the internally allocate buffer.
-Kumu::Result_t
-Kumu::ByteString::Capacity(ui32_t cap_size)
-{
- if ( m_Capacity >= cap_size )
- return RESULT_OK;
-
- byte_t* tmp_data = 0;
- if ( m_Data != 0 )
- {
- if ( m_Length > 0 )
- tmp_data = m_Data;
- else
- free(m_Data);
- }
-
- if ( ( m_Data = (byte_t*)malloc(cap_size) ) == 0 )
- return RESULT_ALLOC;
-
- if ( tmp_data != 0 )
- {
- assert(m_Length > 0);
- memcpy(m_Data, tmp_data, m_Length);
- free(tmp_data);
- }
-
- m_Capacity = cap_size;
- return RESULT_OK;
-}
-
-//
-Kumu::Result_t
-Kumu::ByteString::Append(const ByteString& Buf)
-{
- Result_t result = RESULT_OK;
- ui32_t diff = m_Capacity - m_Length;
-
- if ( diff < Buf.Length() )
- result = Capacity(m_Capacity + Buf.Length());
-
- if ( KM_SUCCESS(result) )
- {
- memcpy(m_Data + m_Length, Buf.RoData(), Buf.Length());
- m_Length += Buf.Length();
- }
-
- return result;
-}
-
-//
-Kumu::Result_t
-Kumu::ByteString::Append(const byte_t* buf, ui32_t buf_len)
-{
- Result_t result = RESULT_OK;
- ui32_t diff = m_Capacity - m_Length;
-
- if ( diff < buf_len )
- result = Capacity(m_Capacity + buf_len);
-
- if ( KM_SUCCESS(result) )
- {
- memcpy(m_Data + m_Length, buf, buf_len);
- m_Length += buf_len;
- }
-
- return result;
-}
-
-
-//
-// end KM_util.cpp
-//