X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FKM_util.cpp;h=b84f7f520ab044ce07e5680d5dbce60ecf97d29c;hb=80463afc197c90372d3f4c7890c6520f1040aedc;hp=f0a779ab78ffdf3f8cd82ede066a2a7e9e52b43f;hpb=60480513f2dbf60bd659d86ac8b61c49b24322a7;p=asdcplib.git diff --git a/src/KM_util.cpp b/src/KM_util.cpp index f0a779a..b84f7f5 100755 --- a/src/KM_util.cpp +++ b/src/KM_util.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2009, John Hurst +Copyright (c) 2005-2011, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -35,6 +35,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include @@ -53,14 +54,19 @@ Kumu::Version() struct map_entry_t { - int rcode; + int rcode; Kumu::Result_t* result; }; -const ui32_t MapMax = 1024; -const ui32_t MapSize = MapMax * (sizeof(struct map_entry_t)); -static bool s_MapInit = false; -static struct map_entry_t s_ResultMap[MapSize]; + +// 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& @@ -69,7 +75,10 @@ Kumu::Result_t::Find(int v) if ( v == 0 ) return RESULT_OK; - for ( ui32_t i = 0; s_ResultMap[i].result != 0 && i < MapMax; i++ ) + 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; @@ -82,22 +91,23 @@ Kumu::Result_t::Find(int v) Kumu::Result_t Kumu::Result_t::Delete(int v) { - if ( v >= RESULT_NOTAFILE.Value() ) + if ( v < -99 || v > 99 ) { DefaultLogSink().Error("Cannot delete core result code: %ld\n", v); return RESULT_FAIL; } - for ( ui32_t i = 0; s_ResultMap[i].result != 0 && i < MapMax; i++ ) + assert(s_MapLock); + AutoMutex L(*s_MapLock); + + for ( ui32_t i = 0; i < s_MapSize; ++i ) { if ( s_ResultMap[i].rcode == v ) { - s_ResultMap[i].rcode = 0; - s_ResultMap[i++].result = 0; - - for ( ; s_ResultMap[i].result != 0 && i < MapMax; i++ ) + for ( ++i; i < s_MapSize; ++i ) s_ResultMap[i-1] = s_ResultMap[i]; + --s_MapSize; return RESULT_OK; } } @@ -105,41 +115,51 @@ Kumu::Result_t::Delete(int v) 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* l) : value(v), label(l) +Kumu::Result_t::Result_t(int v, const char* s, const char* l) : value(v), symbol(s), label(l) { assert(l); - assert(value < (int)MapMax); + assert(s); if ( v == 0 ) return; - if ( ! s_MapInit ) - { - s_MapInit = true; - s_ResultMap[0].rcode = v; - s_ResultMap[0].result = this; - s_ResultMap[1].rcode = 0; - s_ResultMap[1].result = 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); - ui32_t i = 0; - while ( s_ResultMap[i].result != 0 && i < MapMax ) + for ( ui32_t i = 0; i < s_MapSize; ++i ) { - if ( s_ResultMap[i].rcode == v && s_ResultMap[i].result != 0 ) + if ( s_ResultMap[i].rcode == v ) return; - - i++; } - assert(i+2 < MapMax); + assert(s_MapSize+1 < MapMax); + + s_ResultMap[s_MapSize].rcode = v; + s_ResultMap[s_MapSize].result = this; + ++s_MapSize; - s_ResultMap[i].rcode = v; - s_ResultMap[i].result = this; - s_ResultMap[i+1].rcode = 0; - s_ResultMap[i+1].result = 0; return; } @@ -537,9 +557,6 @@ Kumu::GenRandomValue(SymmetricKey& Key) //------------------------------------------------------------------------------------------ -// read a ber value from the buffer and compare with test value. -// Advances buffer to first character after BER value. - // read a ber value from the buffer and compare with test value. // Advances buffer to first character after BER value. // @@ -605,6 +622,20 @@ static const ui64_t ber_masks[9] = 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 @@ -626,14 +657,14 @@ Kumu::write_BER(byte_t* buf, ui64_t val, ui32_t ber_len) { // sanity check BER length if ( ber_len > 9 ) { - DefaultLogSink().Error("BER size %u exceeds maximum size of 9\n", ber_len); + DefaultLogSink().Error("BER integer length %u exceeds maximum size of 9\n", ber_len); return false; } - if ( val & ber_masks[ber_len - 1] ) + if ( ( val & ber_masks[ber_len - 1] ) != 0 ) { ui64Printer tmp_i(val); - DefaultLogSink().Error("BER size %u too small for value %s\n", tmp_i.c_str()); + DefaultLogSink().Error("BER integer length %u too small for value %s\n", ber_len, tmp_i.c_str()); return false; } } @@ -774,6 +805,26 @@ Kumu::Timestamp::AddMinutes(i32_t minutes) } } +// +void +Kumu::Timestamp::AddSeconds(i32_t seconds) +{ + SYSTEMTIME current_st; + FILETIME current_ft; + ULARGE_INTEGER current_ul; + + if ( seconds != 0 ) + { + TIMESTAMP_TO_SYSTIME(*this, ¤t_st); + SystemTimeToFileTime(¤t_st, ¤t_ft); + memcpy(¤t_ul, ¤t_ft, sizeof(current_ul)); + current_ul.QuadPart += ( seconds_to_ns100(1) * (i64_t)seconds ); + memcpy(¤t_ft, ¤t_ul, sizeof(current_ft)); + FileTimeToSystemTime(¤t_ft, ¤t_st); + SYSTIME_TO_TIMESTAMP(¤t_st, *this); + } +} + #else // KM_WIN32 #include @@ -889,6 +940,23 @@ Kumu::Timestamp::AddMinutes(i32_t minutes) } } +// +void +Kumu::Timestamp::AddSeconds(i32_t seconds) +{ + Kumu::TAI::caltime ct; + Kumu::TAI::tai t; + + if ( seconds != 0 ) + { + TIMESTAMP_TO_CALTIME(*this, &ct) + t = ct; + t.add_seconds(seconds); + ct = t; + CALTIME_TO_TIMESTAMP(&ct, *this) + } +} + #endif // KM_WIN32 @@ -902,6 +970,16 @@ Kumu::Timestamp::Timestamp(const Timestamp& rhs) : IArchive() Second = rhs.Second; } +// +Kumu::Timestamp::Timestamp(const char* datestr) : IArchive() +{ + if ( ! DecodeString(datestr) ) + { + *this = Timestamp(); + } +} + +// Kumu::Timestamp::~Timestamp() { } @@ -952,15 +1030,42 @@ Kumu::Timestamp::operator!=(const Timestamp& rhs) const // const char* Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const +{ + return EncodeStringWithOffset(str_buf, buf_len, 0); +} + +// +const char* +Kumu::Timestamp::EncodeStringWithOffset(char* str_buf, ui32_t buf_len, + i32_t offset_minutes) const { if ( buf_len < ( DateTimeLen + 1 ) ) return 0; - // 2004-05-01T13:20:00-00:00 + // ensure offset is within +/- 14 hours + if ((offset_minutes < -14 * 60) || (offset_minutes > 14 * 60)) + return 0; + + // set the apparent time + Kumu::Timestamp tmp_t(*this); + tmp_t.AddMinutes(offset_minutes); + + char direction = '+'; + if (offset_minutes < 0) { + direction = '-'; + // need absolute offset from zero + offset_minutes = -offset_minutes; + } + + // 2004-05-01T13:20:00+00:00 snprintf(str_buf, buf_len, - "%04hu-%02hu-%02huT%02hu:%02hu:%02hu+00:00", - Year, Month, Day, Hour, Minute, Second); - + "%04hu-%02hu-%02huT%02hu:%02hu:%02hu%c%02hu:%02hu", + tmp_t.Year, tmp_t.Month, tmp_t.Day, + tmp_t.Hour, tmp_t.Minute, tmp_t.Second, + direction, + offset_minutes / 60, + offset_minutes % 60); + return str_buf; } @@ -1021,16 +1126,19 @@ Kumu::Timestamp::DecodeString(const char* datestr) char_count += 6; - i32_t TZ_mm = 60 * atoi(datestr + 20); - TZ_mm += atoi(datestr + 23); - if (datestr[19] == '-') - TZ_mm = -TZ_mm; - - if ((TZ_mm > 14 * 60) || (TZ_mm < -14 * 60)) + 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; - else - TmpStamp.AddMinutes(-TZ_mm); + 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 */ + TmpStamp.AddMinutes(-TZ_offset); } else if (datestr[19] == 'Z') { @@ -1095,6 +1203,45 @@ Kumu::Timestamp::Archive(MemIOWriter* Writer) const return true; } +// +long +Kumu::Timestamp::GetSecondsSinceEpoch(void) const +{ +#ifdef KM_WIN32 + SYSTEMTIME timeST; + TIMESTAMP_TO_SYSTIME(*this, &timeST); + FILETIME timeFT; + SystemTimeToFileTime(&timeST, &timeFT); + ULARGE_INTEGER timeUL; + timeUL.LowPart = timeFT.dwLowDateTime; + timeUL.HighPart = timeFT.dwHighDateTime; + + SYSTEMTIME epochST; + epochST.wYear = 1970; + epochST.wMonth = 0; + epochST.wDayOfWeek = 4; + epochST.wDay = 1; + epochST.wHour = 0; + epochST.wMinute = 0; + epochST.wSecond = 0; + epochST.wMilliseconds = 0; + FILETIME epochFT; + SystemTimeToFileTime(&epochST, &epochFT); + ULARGE_INTEGER epochUL; + epochUL.LowPart = epochFT.dwLowDateTime; + epochUL.HighPart = epochFT.dwHighDateTime; + + return (timeUL.QuadPart - epochUL.QuadPart) / 10000000; +#else + Kumu::TAI::caltime ct; + Kumu::TAI::tai t; + TIMESTAMP_TO_CALTIME(*this, &ct); + t = ct; + + return (long) (t.x - ui64_C(4611686018427387914)); +#endif +} + //------------------------------------------------------------------------------------------ Kumu::MemIOWriter::MemIOWriter(ByteString* Buf)