/*
-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
#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>
+const char*
+Kumu::Version()
+{
+ return PACKAGE_VERSION;
+}
+
+
//------------------------------------------------------------------------------------------
// Result_t Internals
struct map_entry_t
{
- long rcode;
+ int rcode;
Kumu::Result_t* result;
};
-const ui32_t MapMax = 512;
+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];
//
const Kumu::Result_t&
-Kumu::Result_t::Find(long v)
+Kumu::Result_t::Find(int v)
{
if ( v == 0 )
return RESULT_OK;
return *s_ResultMap[i].result;
}
- DefaultLogSink().Error("Unknown result code: %ld\n", v);
- return RESULT_FAIL;
+ return RESULT_UNKNOWN;
+}
+
+//
+Kumu::Result_t
+Kumu::Result_t::Delete(int v)
+{
+ if ( v >= RESULT_NOTAFILE.Value() )
+ {
+ 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++ )
+ {
+ 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++ )
+ s_ResultMap[i-1] = s_ResultMap[i];
+
+ return RESULT_OK;
+ }
+ }
+
+ return RESULT_FALSE;
}
+
//
-Kumu::Result_t::Result_t(long v, const char* l) : value(v), label(l)
+Kumu::Result_t::Result_t(int v, const char* l) : value(v), label(l)
{
assert(l);
+ assert(value < (int)MapMax);
if ( v == 0 )
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);
+}
+
//------------------------------------------------------------------------------------------
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
//
|| ((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++ )
//------------------------------------------------------------------------------------------
-// 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.
//
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
{ // 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;
}
}
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(86400) * (ui64_t)days );
+ current_ul.QuadPart += ( seconds_to_ns100(86400) * (i64_t)days );
memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
FileTimeToSystemTime(¤t_ft, ¤t_st);
SYSTIME_TO_TIMESTAMP(¤t_st, *this);
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(3600) * (ui64_t)hours );
+ current_ul.QuadPart += ( seconds_to_ns100(3600) * (i64_t)hours );
+ memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
+ FileTimeToSystemTime(¤t_ft, ¤t_st);
+ SYSTIME_TO_TIMESTAMP(¤t_st, *this);
+ }
+}
+
+//
+void
+Kumu::Timestamp::AddMinutes(i32_t minutes)
+{
+ SYSTEMTIME current_st;
+ FILETIME current_ft;
+ ULARGE_INTEGER current_ul;
+
+ if ( minutes != 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(60) * (i64_t)minutes );
+ memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
+ FileTimeToSystemTime(¤t_ft, ¤t_st);
+ SYSTIME_TO_TIMESTAMP(¤t_st, *this);
+ }
+}
+
+//
+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);
#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, ¤t);
- time_t adj_time = timegm(¤t);
- 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)
}
}
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, ¤t);
- time_t adj_time = timegm(¤t);
- 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)
+ }
+}
+
+//
+void
+Kumu::Timestamp::AddMinutes(i32_t minutes)
+{
+ Kumu::TAI::caltime ct;
+ Kumu::TAI::tai t;
+
+ if ( minutes != 0 )
+ {
+ TIMESTAMP_TO_CALTIME(*this, &ct)
+ t = ct;
+ t.add_minutes(minutes);
+ ct = t;
+ CALTIME_TO_TIMESTAMP(&ct, *this)
+ }
+}
+
+//
+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
-Kumu::Timestamp::Timestamp(const Timestamp& rhs)
+Kumu::Timestamp::Timestamp(const Timestamp& rhs) : IArchive()
{
Year = rhs.Year;
Month = rhs.Month;
//
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;
}
|| ! ( isdigit(datestr[8]) && isdigit(datestr[9]) ) )
return false;
+ ui32_t char_count = 10;
TmpStamp.Year = atoi(datestr);
TmpStamp.Month = atoi(datestr + 5);
TmpStamp.Day = atoi(datestr + 8);
|| ! ( isdigit(datestr[14]) && isdigit(datestr[15]) ) )
return false;
+ char_count += 6;
TmpStamp.Hour = atoi(datestr + 11);
TmpStamp.Minute = atoi(datestr + 14);
if ( ! ( isdigit(datestr[17]) && isdigit(datestr[18]) ) )
return false;
+ char_count += 3;
TmpStamp.Second = atoi(datestr + 17);
}
- }
- if ( datestr[19] == '-' || datestr[19] == '+' )
- {
- if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
- || datestr[22] != ':'
- || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
- return false;
+ if ( datestr[19] == '.' )
+ {
+ if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) && isdigit(datestr[22]) ) )
+ return false;
+
+ // we don't carry the ms value
+ datestr += 4;
+ }
- ui32_t TZ_hh = atoi(datestr + 20);
- ui32_t TZ_mm = atoi(datestr + 23);
-
- if ( TZ_mm != 0 )
- DefaultLogSink().Error("Ignoring minutes in timezone offset: %u\n", TZ_mm);
+ if ( datestr[19] == '-' || datestr[19] == '+' )
+ {
+ if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
+ || datestr[22] != ':'
+ || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
+ return false;
- if ( TZ_hh > 12 )
- 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 */
+ TmpStamp.AddMinutes(-TZ_offset);
+ }
+ else if (datestr[19] == 'Z')
+ {
+ /* act as if the offset were +00:00 */
+ char_count++;
+ }
+ }
- else
- AddHours( (datestr[19] == '-' ? (-TZ_hh) : TZ_hh));
+ if ( datestr[char_count] != 0 )
+ {
+ Kumu::DefaultLogSink().Error("Unexpected extra characters in string: %s (%ld)\n",
+ datestr, char_count);
+ return false;
}
#ifdef KM_WIN32
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;
return true;
}
-#if 0
//
-bool
-Kumu::UnarchiveString(MemIOReader* Reader, std::string&)
-{
- assert(Reader);
- ui32_t str_length;
- if ( ! Reader->ReadUi32BE(&str_length) ) return false;
- assign((const char*)Reader->CurrentData(), str_length);
- if ( ! Reader->SkipOffset(str_length) ) return false;
- return true;
-}
-
-//
-bool
-Kumu::String::Archive(MemIOWriter* Writer) const
+long
+Kumu::Timestamp::GetSecondsSinceEpoch(void) const
{
- assert(Writer);
- if ( ! Writer->WriteUi32BE(length()) ) return false;
- if ( ! Writer->WriteRaw((const byte_t*)c_str(), length()) ) return false;
+#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 true;
-}
+ return (long) (t.x - ui64_C(4611686018427387914));
#endif
+}
//------------------------------------------------------------------------------------------
}
+// 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.
-// Resets content length to zero.
Kumu::Result_t
Kumu::ByteString::Capacity(ui32_t cap_size)
{
- if ( m_Capacity < cap_size )
+ if ( m_Capacity >= cap_size )
+ return RESULT_OK;
+
+ byte_t* tmp_data = 0;
+ if ( m_Data != 0 )
{
- if ( m_Data != 0 )
+ if ( m_Length > 0 )
+ tmp_data = m_Data;
+ else
free(m_Data);
+ }
- m_Data = (byte_t*)malloc(cap_size);
-
- if ( m_Data == 0 )
- return RESULT_ALLOC;
-
- m_Capacity = cap_size;
- m_Length = 0;
+ 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;
}