2 Copyright (c) 2005-2006, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \brief Utility functions
35 #include <KM_fileio.h>
42 //------------------------------------------------------------------------------------------
49 Kumu::Result_t* result;
52 const ui32_t MapMax = 512;
53 const ui32_t MapSize = MapMax * (sizeof(struct map_entry_t));
54 static bool s_MapInit = false;
55 static struct map_entry_t s_ResultMap[MapSize];
59 Kumu::Result_t::Find(long v)
64 for ( ui32_t i = 0; s_ResultMap[i].result != 0 && i < MapMax; i++ )
66 if ( s_ResultMap[i].rcode == v )
67 return *s_ResultMap[i].result;
70 DefaultLogSink().Error("Unknown result code: %ld\n", v);
75 Kumu::Result_t::Result_t(long v, const char* l) : value(v), label(l)
85 s_ResultMap[0].rcode = v;
86 s_ResultMap[0].result = this;
87 s_ResultMap[1].rcode = 0;
88 s_ResultMap[1].result = 0;
93 while ( s_ResultMap[i].result != 0 && i < MapMax )
95 if ( s_ResultMap[i].rcode == v && s_ResultMap[i].result != 0 )
101 assert(i+2 < MapMax);
103 s_ResultMap[i].rcode = v;
104 s_ResultMap[i].result = this;
105 s_ResultMap[i+1].rcode = 0;
106 s_ResultMap[i+1].result = 0;
110 Kumu::Result_t::~Result_t() {}
113 //------------------------------------------------------------------------------------------
116 const char fill = '=';
117 const char* base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
119 const byte_t decode_map[] =
120 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
123 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
124 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
125 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
126 52, 53, 54, 55, 56, 57, 58, 59,
127 60, 61, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
128 0xff, 0, 1, 2, 3, 4, 5, 6,
129 7, 8, 9, 10, 11, 12, 13, 14,
130 15, 16, 17, 18, 19, 20, 21, 22,
131 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 26, 27, 28, 29, 30, 31, 32,
133 33, 34, 35, 36, 37, 38, 39, 40,
134 41, 42, 43, 44, 45, 46, 47, 48,
135 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
155 // Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
156 // if the binary buffer was large enough to hold the result. If the output buffer
157 // is too small or any of the pointer arguments are NULL, the subroutine will
161 Kumu::base64encode(const byte_t* buf, ui32_t buf_len, char* strbuf, ui32_t strbuf_len)
164 ui32_t i, block_len, diff;
166 if ( buf == 0 || strbuf == 0 )
169 if ( strbuf_len < base64_encode_length(buf_len) + 1 )
174 while ( block_len % 3 )
177 for ( i = 0; i < block_len; i += 3 )
179 strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
180 strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
181 strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) | ( buf[2] >> 6 ) )];
182 strbuf[out_char++] = base64_chars[( buf[2] & 0x3f )];
192 strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
196 strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) )];
197 strbuf[out_char++] = fill;
199 else if ( diff == 2 )
201 strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
202 strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) )];
205 strbuf[out_char++] = fill;
208 strbuf[out_char] = 0;
215 // Convert NULL-terminated UTF-8 Base64 string to binary, returns 0 if
216 // the binary buffer was large enough to hold the result. The output parameter
217 // 'char_count' will contain the length of the converted string. If the output
218 // buffer is too small or any of the pointer arguments are NULL, the subroutine
219 // will return -1 and set 'char_count' to the required buffer size. No data will
220 // be written to 'buf' if the subroutine fails.
223 Kumu::base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count)
225 register byte_t c = 0, d = 0;
226 register ui32_t phase = 0, i = 0;
228 if ( str == 0 || buf == 0 || char_count == 0 )
231 while ( *str != 0 && i < buf_len )
233 c = decode_map[(int)*str++];
234 if ( c == 0xff ) continue;
235 if ( c == 0xfe ) break;
244 buf[i - 1] |= c >> 4;
249 buf[i++] = ( d << 4 ) | ( c >> 2 );
254 buf[i++] = ( d << 6 ) | c;
264 //------------------------------------------------------------------------------------------
266 // convert utf-8 hext string to bin
268 Kumu::hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* conv_size)
272 KM_TEST_NULL_L(conv_size);
276 if ( str[0] == 0 ) // nothing to convert
279 for ( int j = 0; str[j]; j++ )
281 if ( isxdigit(str[j]) )
285 if ( *conv_size & 0x01 ) (*conv_size)++;
288 if ( *conv_size > buf_len )// maximum possible data size
293 int phase = 0; // track high/low nybble
295 // for each character, fill in the high nybble then the low
296 for ( int i = 0; str[i]; i++ )
298 if ( ! isxdigit(str[i]) )
301 byte_t val = str[i] - ( isdigit(str[i]) ? 0x30 : ( isupper(str[i]) ? 0x37 : 0x57 ) );
305 buf[*conv_size] = val << 4;
310 buf[*conv_size] |= val;
320 // convert a memory region to a NULL-terminated hexadecimal string
323 Kumu::bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
327 || ((bin_len * 2) + 1) > str_len )
332 for ( ui32_t i = 0; i < bin_len; i++ )
334 *p = (bin_buf[i] >> 4) & 0x0f;
335 *p += *p < 10 ? 0x30 : 0x61 - 10;
338 *p = bin_buf[i] & 0x0f;
339 *p += *p < 10 ? 0x30 : 0x61 - 10;
348 // spew a range of bin data as hex
350 Kumu::hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream)
358 static ui32_t row_len = 16;
359 const byte_t* p = buf;
360 const byte_t* end_p = p + dump_len;
362 for ( ui32_t line = 0; p < end_p; line++ )
364 fprintf(stream, " %06x: ", line);
368 for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
369 fprintf(stream, "%02x ", *pp);
371 while ( i++ < row_len )
374 for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
375 fputc((isprint(*pp) ? *pp : '.'), stream);
384 Kumu::bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
388 if ( str_len < 34 || bin_len != UUID_Length )
391 if ( bin2hex(bin_buf, bin_len, str_buf, str_len) == 0 )
395 for ( k = 19, i = 12; i > 0; i-- )
396 str_buf[k+i+4] = str_buf[k+i];
398 // shift the time (mid+hi+clk)
399 for ( k = 15, j = 3; k > 6; k -= 4, j-- )
401 for ( i = 4; i > 0; i-- )
402 str_buf[k+i+j] = str_buf[k+i];
405 // add in the hyphens and trainling null
406 for ( i = 8; i < 24; i += 5 )
415 Kumu::GenRandomValue(UUID& ID)
417 byte_t tmp_buf[UUID_Length];
418 GenRandomUUID(tmp_buf);
424 Kumu::GenRandomUUID(byte_t* buf)
427 RNG.FillRandom(buf, UUID_Length);
428 buf[6] &= 0x0f; // clear bits 4-7
429 buf[6] |= 0x40; // set UUID version
430 buf[8] &= 0x3f; // clear bits 6&7
431 buf[8] |= 0x80; // set bit 7
436 Kumu::GenRandomValue(SymmetricKey& Key)
438 byte_t tmp_buf[SymmetricKey_Length];
440 RNG.FillRandom(tmp_buf, SymmetricKey_Length);
445 //------------------------------------------------------------------------------------------
446 // read a ber value from the buffer and compare with test value.
447 // Advances buffer to first character after BER value.
449 // read a ber value from the buffer and compare with test value.
450 // Advances buffer to first character after BER value.
453 Kumu::read_test_BER(byte_t **buf, ui64_t test_value)
458 if ( ( **buf & 0x80 ) == 0 )
462 ui8_t ber_size = ( **buf & 0x0f ) + 1;
467 for ( ui8_t i = 1; i < ber_size; i++ )
470 val |= (ui64_t)((*buf)[i]) << ( ( ( ber_size - 1 ) - i ) * 8 );
474 return ( val == test_value );
480 Kumu::read_BER(const byte_t* buf, ui64_t* val)
484 if ( buf == 0 || val == 0 )
487 if ( ( *buf & 0x80 ) == 0 )
491 ber_size = ( *buf & 0x0f ) + 1;
496 for ( i = 1; i < ber_size; i++ )
499 *val |= (ui64_t)buf[i] << ( ( ( ber_size - 1 ) - i ) * 8 );
506 static const ui64_t ber_masks[9] =
507 { ui64_C(0xffffffffffffffff), ui64_C(0xffffffffffffff00),
508 ui64_C(0xffffffffffff0000), ui64_C(0xffffffffff000000),
509 ui64_C(0xffffffff00000000), ui64_C(0xffffff0000000000),
510 ui64_C(0xffff000000000000), ui64_C(0xff00000000000000),
517 Kumu::write_BER(byte_t* buf, ui64_t val, ui32_t ber_len)
523 { // calculate default length
524 if ( val < 0x01000000L )
526 else if ( val < ui64_C(0x0100000000000000) )
532 { // sanity check BER length
535 DefaultLogSink().Error("BER size %u exceeds maximum size of 9\n", ber_len);
539 if ( val & ber_masks[ber_len - 1] )
541 ui64Printer tmp_i(val);
542 DefaultLogSink().Error("BER size %u too small for value %s\n", tmp_i.c_str());
547 buf[0] = 0x80 + ( ber_len - 1 );
549 for ( ui32_t i = ber_len - 1; i > 0; i-- )
551 buf[i] = (ui8_t)(val & 0xff);
559 //------------------------------------------------------------------------------------------
562 #define TIMESTAMP_TO_SYSTIME(ts, t) \
563 (t)->wYear = (ts).Year; /* year */ \
564 (t)->wMonth = (ts).Month; /* month of year (1 - 12) */ \
565 (t)->wDay = (ts).Day; /* day of month (1 - 31) */ \
566 (t)->wHour = (ts).Hour; /* hours (0 - 23) */ \
567 (t)->wMinute = (ts).Minute; /* minutes (0 - 59) */ \
568 (t)->wSecond = (ts).Second; /* seconds (0 - 60) */ \
569 (t)->wDayOfWeek = 0; \
570 (t)->wMilliseconds = 0
572 #define SYSTIME_TO_TIMESTAMP(t, ts) \
573 (ts).Year = (t)->wYear; /* year */ \
574 (ts).Month = (t)->wMonth; /* month of year (1 - 12) */ \
575 (ts).Day = (t)->wDay; /* day of month (1 - 31) */ \
576 (ts).Hour = (t)->wHour; /* hours (0 - 23) */ \
577 (ts).Minute = (t)->wMinute; /* minutes (0 - 59) */ \
578 (ts).Second = (t)->wSecond; /* seconds (0 - 60) */
581 Kumu::Timestamp::Timestamp() :
582 Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
585 GetSystemTime(&sys_time);
586 SYSTIME_TO_TIMESTAMP(&sys_time, *this);
591 Kumu::Timestamp::operator<(const Timestamp& rhs) const
593 SYSTEMTIME lhst, rhst;
596 TIMESTAMP_TO_SYSTIME(*this, &lhst);
597 TIMESTAMP_TO_SYSTIME(rhs, &rhst);
598 SystemTimeToFileTime(&lhst, &lft);
599 SystemTimeToFileTime(&rhst, &rft);
600 return ( CompareFileTime(&lft, &rft) == -1 );
605 Kumu::Timestamp::operator>(const Timestamp& rhs) const
607 SYSTEMTIME lhst, rhst;
610 TIMESTAMP_TO_SYSTIME(*this, &lhst);
611 TIMESTAMP_TO_SYSTIME(rhs, &rhst);
612 SystemTimeToFileTime(&lhst, &lft);
613 SystemTimeToFileTime(&rhst, &rft);
614 return ( CompareFileTime(&lft, &rft) == 1 );
618 seconds_to_ns100(ui32_t seconds)
620 return ((ui64_t)seconds * 10000000);
625 Kumu::Timestamp::AddDays(i32_t days)
627 SYSTEMTIME current_st;
629 ULARGE_INTEGER current_ul;
633 TIMESTAMP_TO_SYSTIME(*this, ¤t_st);
634 SystemTimeToFileTime(¤t_st, ¤t_ft);
635 memcpy(¤t_ul, ¤t_ft, sizeof(current_ul));
636 current_ul.QuadPart += ( seconds_to_ns100(86400) * (ui64_t)days );
637 memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
638 FileTimeToSystemTime(¤t_ft, ¤t_st);
639 SYSTIME_TO_TIMESTAMP(¤t_st, *this);
645 Kumu::Timestamp::AddHours(i32_t hours)
647 SYSTEMTIME current_st;
649 ULARGE_INTEGER current_ul;
653 TIMESTAMP_TO_SYSTIME(*this, ¤t_st);
654 SystemTimeToFileTime(¤t_st, ¤t_ft);
655 memcpy(¤t_ul, ¤t_ft, sizeof(current_ul));
656 current_ul.QuadPart += ( seconds_to_ns100(3600) * (ui64_t)hours );
657 memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
658 FileTimeToSystemTime(¤t_ft, ¤t_st);
659 SYSTIME_TO_TIMESTAMP(¤t_st, *this);
667 #define TIMESTAMP_TO_TM(ts, t) \
668 (t)->tm_year = (ts).Year - 1900; /* year - 1900 */ \
669 (t)->tm_mon = (ts).Month - 1; /* month of year (0 - 11) */ \
670 (t)->tm_mday = (ts).Day; /* day of month (1 - 31) */ \
671 (t)->tm_hour = (ts).Hour; /* hours (0 - 23) */ \
672 (t)->tm_min = (ts).Minute; /* minutes (0 - 59) */ \
673 (t)->tm_sec = (ts).Second; /* seconds (0 - 60) */
675 #define TM_TO_TIMESTAMP(t, ts) \
676 (ts).Year = (t)->tm_year + 1900; /* year - 1900 */ \
677 (ts).Month = (t)->tm_mon + 1; /* month of year (0 - 11) */ \
678 (ts).Day = (t)->tm_mday; /* day of month (1 - 31) */ \
679 (ts).Hour = (t)->tm_hour; /* hours (0 - 23) */ \
680 (ts).Minute = (t)->tm_min; /* minutes (0 - 59) */ \
681 (ts).Second = (t)->tm_sec; /* seconds (0 - 60) */
684 Kumu::Timestamp::Timestamp() :
685 Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
687 time_t t_now = time(0);
688 struct tm* now = gmtime(&t_now);
689 TM_TO_TIMESTAMP(now, *this);
694 Kumu::Timestamp::operator<(const Timestamp& rhs) const
696 struct tm lhtm, rhtm;
697 TIMESTAMP_TO_TM(*this, &lhtm);
698 TIMESTAMP_TO_TM(rhs, &rhtm);
699 return ( timegm(&lhtm) < timegm(&rhtm) );
704 Kumu::Timestamp::operator>(const Timestamp& rhs) const
706 struct tm lhtm, rhtm;
707 TIMESTAMP_TO_TM(*this, &lhtm);
708 TIMESTAMP_TO_TM(rhs, &rhtm);
709 return ( timegm(&lhtm) > timegm(&rhtm) );
714 Kumu::Timestamp::AddDays(i32_t days)
720 TIMESTAMP_TO_TM(*this, ¤t);
721 time_t adj_time = timegm(¤t);
722 adj_time += 86400 * days;
723 struct tm* now = gmtime(&adj_time);
724 TM_TO_TIMESTAMP(now, *this);
730 Kumu::Timestamp::AddHours(i32_t hours)
736 TIMESTAMP_TO_TM(*this, ¤t);
737 time_t adj_time = timegm(¤t);
738 adj_time += 3600 * hours;
739 struct tm* now = gmtime(&adj_time);
740 TM_TO_TIMESTAMP(now, *this);
747 Kumu::Timestamp::Timestamp(const Timestamp& rhs)
757 Kumu::Timestamp::~Timestamp()
762 const Kumu::Timestamp&
763 Kumu::Timestamp::operator=(const Timestamp& rhs)
776 Kumu::Timestamp::operator==(const Timestamp& rhs) const
778 if ( Year == rhs.Year
779 && Month == rhs.Month
782 && Minute == rhs.Minute
783 && Second == rhs.Second )
791 Kumu::Timestamp::operator!=(const Timestamp& rhs) const
793 if ( Year != rhs.Year
794 || Month != rhs.Month
797 || Minute != rhs.Minute
798 || Second != rhs.Second )
806 Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const
808 if ( buf_len < ( DateTimeLen + 1 ) )
811 // 2004-05-01T13:20:00-00:00
812 snprintf(str_buf, buf_len,
813 "%04hu-%02hu-%02huT%02hu:%02hu:%02hu-00:00",
814 Year, Month, Day, Hour, Minute, Second);
821 Kumu::Timestamp::DecodeString(const char* datestr)
825 if ( ! ( isdigit(datestr[0]) && isdigit(datestr[1]) && isdigit(datestr[2]) && isdigit(datestr[3]) )
827 || ! ( isdigit(datestr[5]) && isdigit(datestr[6]) )
829 || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) ) )
832 TmpStamp.Year = atoi(datestr);
833 TmpStamp.Month = atoi(datestr + 5);
834 TmpStamp.Day = atoi(datestr + 8);
835 TmpStamp.Hour = TmpStamp.Minute = TmpStamp.Second = 0;
837 if ( datestr[10] == 'T' )
839 if ( ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
840 || datestr[13] != ':'
841 || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) ) )
844 TmpStamp.Hour = atoi(datestr + 11);
845 TmpStamp.Minute = atoi(datestr + 14);
847 if ( datestr[16] == ':' )
849 if ( ! ( isdigit(datestr[17]) && isdigit(datestr[18]) ) )
852 TmpStamp.Second = atoi(datestr + 17);
856 if ( datestr[19] == '-' || datestr[19] == '+' )
858 if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
859 || datestr[22] != ':'
860 || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
863 ui32_t TZ_hh = atoi(datestr + 20);
864 ui32_t TZ_mm = atoi(datestr + 23);
867 DefaultLogSink().Error("Ignoring minutes in timezone offset: %u\n", TZ_mm);
873 AddHours( (datestr[19] == '-' ? (-TZ_hh) : TZ_hh));
879 TIMESTAMP_TO_SYSTIME(TmpStamp, &st);
880 if ( SystemTimeToFileTime(&st, &ft) == 0 )
882 SYSTIME_TO_TIMESTAMP(&st, *this);
885 TIMESTAMP_TO_TM(TmpStamp, &stm);
886 if ( timegm(&stm) == 0 )
888 TM_TO_TIMESTAMP(&stm, *this);
896 Kumu::Timestamp::HasValue() const
898 if ( Year || Month || Day || Hour || Minute || Second )
906 Kumu::Timestamp::Unarchive(MemIOReader* Reader)
909 if ( ! Reader->ReadUi16BE(&Year) ) return false;
910 if ( ! Reader->ReadRaw(&Month, 6) ) return false;
916 Kumu::Timestamp::Archive(MemIOWriter* Writer) const
919 if ( ! Writer->WriteUi16BE(Year) ) return false;
920 if ( ! Writer->WriteRaw(&Month, 6) ) return false;
924 //------------------------------------------------------------------------------------------
926 Kumu::MemIOWriter::MemIOWriter(ByteString* Buf)
927 : m_p(0), m_capacity(0), m_size(0)
930 m_capacity = Buf->Capacity();
931 assert(m_p); assert(m_capacity);
935 Kumu::MemIOWriter:: WriteBER(ui64_t i, ui32_t ber_len)
937 if ( ( m_size + ber_len ) > m_capacity )
940 if ( ! write_BER(m_p + m_size, i, ber_len) )
948 Kumu::MemIOReader::MemIOReader(const ByteString* Buf)
949 : m_p(0), m_capacity(0), m_size(0)
952 m_capacity = Buf->Length();
953 assert(m_p); assert(m_capacity);
957 Kumu::MemIOReader::ReadBER(ui64_t* i, ui32_t* ber_len)
959 if ( i == 0 || ber_len == 0 ) return false;
961 if ( ( *ber_len = BER_length(m_p + m_size) ) == 0 )
964 if ( ( m_size + *ber_len ) > m_capacity )
967 if ( ! read_BER(m_p + m_size, i) )
974 //------------------------------------------------------------------------------------------
976 Kumu::ByteString::ByteString() : m_Data(0), m_Capacity(0), m_Length(0) {}
978 Kumu::ByteString::ByteString(ui32_t cap) : m_Data(0), m_Capacity(0), m_Length(0)
983 Kumu::ByteString::~ByteString()
990 // copy the given data into the ByteString, set Length value.
991 // Returns error if the ByteString is too small.
993 Kumu::ByteString::Set(const byte_t* buf, ui32_t buf_len)
995 if ( m_Capacity < buf_len )
998 memcpy(m_Data, buf, buf_len);
1004 // copy the given data into the ByteString, set Length value.
1005 // Returns error if the ByteString is too small.
1007 Kumu::ByteString::Set(const ByteString& Buf)
1009 if ( m_Capacity < Buf.m_Capacity )
1010 return RESULT_ALLOC;
1012 memcpy(m_Data, Buf.m_Data, Buf.m_Length);
1013 m_Length = Buf.m_Length;
1018 // Sets the size of the internally allocate buffer.
1019 // Resets content length to zero.
1021 Kumu::ByteString::Capacity(ui32_t cap_size)
1023 if ( m_Capacity < cap_size )
1028 m_Data = (byte_t*)malloc(cap_size);
1031 return RESULT_ALLOC;
1033 m_Capacity = cap_size;
1042 Kumu::ByteString::Append(const ByteString& Buf)
1044 Result_t result = RESULT_OK;
1045 ui32_t diff = m_Capacity - m_Length;
1047 if ( diff < Buf.Length() )
1048 result = Capacity(m_Capacity + Buf.Length());
1050 if ( KM_SUCCESS(result) )
1052 memcpy(m_Data + m_Length, Buf.RoData(), Buf.Length());
1053 m_Length += Buf.Length();
1061 Kumu::ByteString::Append(const byte_t* buf, ui32_t buf_len)
1063 Result_t result = RESULT_OK;
1064 ui32_t diff = m_Capacity - m_Length;
1066 if ( diff < buf_len )
1067 result = Capacity(m_Capacity + buf_len);
1069 if ( KM_SUCCESS(result) )
1071 memcpy(m_Data + m_Length, buf, buf_len);
1072 m_Length += buf_len;