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)
61 for ( ui32_t i = 0; s_ResultMap[i].result != 0 && i < MapMax; i++ )
63 if ( s_ResultMap[i].rcode == v )
64 return *s_ResultMap[i].result;
67 DefaultLogSink().Error("Unknown result code: %ld\n", v);
72 Kumu::Result_t::Result_t(long v, const char* l) : value(v), label(l)
79 s_ResultMap[0].rcode = v;
80 s_ResultMap[0].result = this;
81 s_ResultMap[1].rcode = 0;
82 s_ResultMap[1].result = 0;
87 while ( s_ResultMap[i].result != 0 && i < MapMax )
90 if ( s_ResultMap[i].rcode == v )
96 s_ResultMap[i].rcode = v;
97 s_ResultMap[i].result = this;
98 s_ResultMap[i+1].rcode = 0;
99 s_ResultMap[i+1].result = 0;
103 Kumu::Result_t::~Result_t() {}
106 //------------------------------------------------------------------------------------------
109 const char fill = '=';
110 const char* base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
112 const byte_t decode_map[] =
113 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
117 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
118 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
119 52, 53, 54, 55, 56, 57, 58, 59,
120 60, 61, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
121 0xff, 0, 1, 2, 3, 4, 5, 6,
122 7, 8, 9, 10, 11, 12, 13, 14,
123 15, 16, 17, 18, 19, 20, 21, 22,
124 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
125 0xff, 26, 27, 28, 29, 30, 31, 32,
126 33, 34, 35, 36, 37, 38, 39, 40,
127 41, 42, 43, 44, 45, 46, 47, 48,
128 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0xff, 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
148 // Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
149 // if the binary buffer was large enough to hold the result. If the output buffer
150 // is too small or any of the pointer arguments are NULL, the subroutine will
154 Kumu::base64encode(const byte_t* buf, ui32_t buf_len, char* strbuf, ui32_t strbuf_len)
157 ui32_t i, block_len, diff;
159 if ( buf == 0 || strbuf == 0 )
162 if ( strbuf_len < base64_encode_length(buf_len) + 1 )
167 while ( block_len % 3 )
170 for ( i = 0; i < block_len; i += 3 )
172 strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
173 strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
174 strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) | ( buf[2] >> 6 ) )];
175 strbuf[out_char++] = base64_chars[( buf[2] & 0x3f )];
185 strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
189 strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) )];
190 strbuf[out_char++] = fill;
192 else if ( diff == 2 )
194 strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
195 strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) )];
198 strbuf[out_char++] = fill;
201 strbuf[out_char] = 0;
208 // Convert NULL-terminated UTF-8 Base64 string to binary, returns 0 if
209 // the binary buffer was large enough to hold the result. The output parameter
210 // 'char_count' will contain the length of the converted string. If the output
211 // buffer is too small or any of the pointer arguments are NULL, the subroutine
212 // will return -1 and set 'char_count' to the required buffer size. No data will
213 // be written to 'buf' if the subroutine fails.
216 Kumu::base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count)
218 register byte_t c = 0, d = 0;
219 register ui32_t phase = 0, i = 0;
221 if ( str == 0 || buf == 0 || char_count == 0 )
224 while ( *str != 0 && i < buf_len )
226 c = decode_map[(int)*str++];
227 if ( c == 0xff ) continue;
228 if ( c == 0xfe ) break;
237 buf[i - 1] |= c >> 4;
242 buf[i++] = ( d << 4 ) | ( c >> 2 );
247 buf[i++] = ( d << 6 ) | c;
257 //------------------------------------------------------------------------------------------
259 // convert utf-8 hext string to bin
261 Kumu::hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* conv_size)
265 KM_TEST_NULL(conv_size);
269 if ( str[0] == 0 ) // nothing to convert
272 for ( int j = 0; str[j]; j++ )
274 if ( isxdigit(str[j]) )
278 if ( *conv_size & 0x01 ) (*conv_size)++;
281 if ( *conv_size > buf_len )// maximum possible data size
286 int phase = 0; // track high/low nybble
288 // for each character, fill in the high nybble then the low
289 for ( int i = 0; str[i]; i++ )
291 if ( ! isxdigit(str[i]) )
294 byte_t val = str[i] - ( isdigit(str[i]) ? 0x30 : ( isupper(str[i]) ? 0x37 : 0x57 ) );
298 buf[*conv_size] = val << 4;
303 buf[*conv_size] |= val;
313 // convert a memory region to a NULL-terminated hexadecimal string
316 Kumu::bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
320 || ((bin_len * 2) + 1) > str_len )
325 for ( ui32_t i = 0; i < bin_len; i++ )
327 *p = (bin_buf[i] >> 4) & 0x0f;
328 *p += *p < 10 ? 0x30 : 0x61 - 10;
331 *p = bin_buf[i] & 0x0f;
332 *p += *p < 10 ? 0x30 : 0x61 - 10;
341 // spew a range of bin data as hex
343 Kumu::hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream)
351 static ui32_t row_len = 16;
352 const byte_t* p = buf;
353 const byte_t* end_p = p + dump_len;
355 for ( ui32_t line = 0; p < end_p; line++ )
357 fprintf(stream, " %06x: ", line);
361 for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
362 fprintf(stream, "%02x ", *pp);
364 while ( i++ < row_len )
367 for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
368 fputc((isprint(*pp) ? *pp : '.'), stream);
377 Kumu::bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
381 if ( str_len < 34 || bin_len != UUID_Length )
384 if ( bin2hex(bin_buf, bin_len, str_buf, str_len) == 0 )
388 for ( k = 19, i = 12; i > 0; i-- )
389 str_buf[k+i+4] = str_buf[k+i];
391 // shift the time (mid+hi+clk)
392 for ( k = 15, j = 3; k > 6; k -= 4, j-- )
394 for ( i = 4; i > 0; i-- )
395 str_buf[k+i+j] = str_buf[k+i];
398 // add in the hyphens and trainling null
399 for ( i = 8; i < 24; i += 5 )
408 Kumu::GenRandomValue(UUID& ID)
410 byte_t tmp_buf[UUID_Length];
411 GenRandomUUID(tmp_buf);
417 Kumu::GenRandomUUID(byte_t* buf)
420 RNG.FillRandom(buf, UUID_Length);
421 buf[6] &= 0x0f; // clear bits 4-7
422 buf[6] |= 0x40; // set UUID version
423 buf[8] &= 0x3f; // clear bits 6&7
424 buf[8] |= 0x80; // set bit 7
429 Kumu::GenRandomValue(SymmetricKey& ID)
431 byte_t tmp_buf[SymmetricKey_Length];
433 RNG.FillRandom(tmp_buf, SymmetricKey_Length);
438 //------------------------------------------------------------------------------------------
439 // read a ber value from the buffer and compare with test value.
440 // Advances buffer to first character after BER value.
442 // read a ber value from the buffer and compare with test value.
443 // Advances buffer to first character after BER value.
446 Kumu::read_test_BER(byte_t **buf, ui64_t test_value)
451 if ( ( **buf & 0x80 ) == 0 )
455 ui8_t ber_size = ( **buf & 0x0f ) + 1;
460 for ( ui8_t i = 1; i < ber_size; i++ )
463 val |= (ui64_t)((*buf)[i]) << ( ( ( ber_size - 1 ) - i ) * 8 );
467 return ( val == test_value );
473 Kumu::read_BER(const byte_t* buf, ui64_t* val)
477 if ( buf == 0 || val == 0 )
480 if ( ( *buf & 0x80 ) == 0 )
484 ber_size = ( *buf & 0x0f ) + 1;
489 for ( i = 1; i < ber_size; i++ )
492 *val |= (ui64_t)buf[i] << ( ( ( ber_size - 1 ) - i ) * 8 );
499 static const ui64_t ber_masks[9] =
500 { ui64_C(0xffffffffffffffff), ui64_C(0xffffffffffffff00),
501 ui64_C(0xffffffffffff0000), ui64_C(0xffffffffff000000),
502 ui64_C(0xffffffff00000000), ui64_C(0xffffff0000000000),
503 ui64_C(0xffff000000000000), ui64_C(0xff00000000000000),
510 Kumu::write_BER(byte_t* buf, ui64_t val, ui32_t ber_len)
516 { // calculate default length
517 if ( val < 0x01000000L )
519 else if ( val < ui64_C(0x0100000000000000) )
525 { // sanity check BER length
528 DefaultLogSink().Error("BER size %lu exceeds maximum size of 9\n", ber_len);
532 if ( val & ber_masks[ber_len - 1] )
534 ui64Printer tmp_i(val);
535 DefaultLogSink().Error("BER size %lu too small for value %s\n", tmp_i.c_str());
540 buf[0] = 0x80 + ( ber_len - 1 );
542 for ( ui32_t i = ber_len - 1; i > 0; i-- )
544 buf[i] = (ui8_t)(val & 0xff);
552 //------------------------------------------------------------------------------------------
555 #define TIMESTAMP_TO_SYSTIME(ts, t) \
556 (t)->wYear = (ts).Year; /* year */ \
557 (t)->wMonth = (ts).Month; /* month of year (1 - 12) */ \
558 (t)->wDay = (ts).Day; /* day of month (1 - 31) */ \
559 (t)->wHour = (ts).Hour; /* hours (0 - 23) */ \
560 (t)->wMinute = (ts).Minute; /* minutes (0 - 59) */ \
561 (t)->wSecond = (ts).Second; /* seconds (0 - 60) */ \
562 (t)->wDayOfWeek = 0; \
563 (t)->wMilliseconds = 0
565 #define SYSTIME_TO_TIMESTAMP(t, ts) \
566 (ts).Year = (t)->wYear; /* year */ \
567 (ts).Month = (t)->wMonth; /* month of year (1 - 12) */ \
568 (ts).Day = (t)->wDay; /* day of month (1 - 31) */ \
569 (ts).Hour = (t)->wHour; /* hours (0 - 23) */ \
570 (ts).Minute = (t)->wMinute; /* minutes (0 - 59) */ \
571 (ts).Second = (t)->wSecond; /* seconds (0 - 60) */
574 Kumu::Timestamp::Timestamp() :
575 Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
578 GetSystemTime(&sys_time);
579 SYSTIME_TO_TIMESTAMP(&sys_time, *this);
584 Kumu::Timestamp::operator<(const Timestamp& rhs) const
586 SYSTEMTIME lhst, rhst;
589 TIMESTAMP_TO_SYSTIME(*this, &lhst);
590 TIMESTAMP_TO_SYSTIME(rhs, &rhst);
591 SystemTimeToFileTime(&lhst, &lft);
592 SystemTimeToFileTime(&rhst, &rft);
593 return ( CompareFileTime(&lft, &rft) == -1 );
597 seconds_to_ns100(ui32_t seconds)
599 return ((ui64_t)seconds * 10000000);
604 Kumu::Timestamp::AddDays(i32_t days)
606 SYSTEMTIME current_st;
608 ULARGE_INTEGER current_ul;
612 TIMESTAMP_TO_SYSTIME(*this, ¤t_st);
613 SystemTimeToFileTime(¤t_st, ¤t_ft);
614 memcpy(¤t_ul, ¤t_ft, sizeof(current_ul));
615 current_ul.QuadPart += ( seconds_to_ns100(86400) * (ui64_t)days );
616 memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
617 FileTimeToSystemTime(¤t_ft, ¤t_st);
618 SYSTIME_TO_TIMESTAMP(¤t_st, *this);
624 Kumu::Timestamp::AddHours(i32_t hours)
626 SYSTEMTIME current_st;
628 ULARGE_INTEGER current_ul;
632 TIMESTAMP_TO_SYSTIME(*this, ¤t_st);
633 SystemTimeToFileTime(¤t_st, ¤t_ft);
634 memcpy(¤t_ul, ¤t_ft, sizeof(current_ul));
635 current_ul.QuadPart += ( seconds_to_ns100(3600) * (ui64_t)hours );
636 memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
637 FileTimeToSystemTime(¤t_ft, ¤t_st);
638 SYSTIME_TO_TIMESTAMP(¤t_st, *this);
646 #define TIMESTAMP_TO_TM(ts, t) \
647 (t)->tm_year = (ts).Year - 1900; /* year - 1900 */ \
648 (t)->tm_mon = (ts).Month - 1; /* month of year (0 - 11) */ \
649 (t)->tm_mday = (ts).Day; /* day of month (1 - 31) */ \
650 (t)->tm_hour = (ts).Hour; /* hours (0 - 23) */ \
651 (t)->tm_min = (ts).Minute; /* minutes (0 - 59) */ \
652 (t)->tm_sec = (ts).Second; /* seconds (0 - 60) */
654 #define TM_TO_TIMESTAMP(t, ts) \
655 (ts).Year = (t)->tm_year + 1900; /* year - 1900 */ \
656 (ts).Month = (t)->tm_mon + 1; /* month of year (0 - 11) */ \
657 (ts).Day = (t)->tm_mday; /* day of month (1 - 31) */ \
658 (ts).Hour = (t)->tm_hour; /* hours (0 - 23) */ \
659 (ts).Minute = (t)->tm_min; /* minutes (0 - 59) */ \
660 (ts).Second = (t)->tm_sec; /* seconds (0 - 60) */
663 Kumu::Timestamp::Timestamp() :
664 Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
666 time_t t_now = time(0);
667 struct tm* now = gmtime(&t_now);
668 TM_TO_TIMESTAMP(now, *this);
673 Kumu::Timestamp::operator<(const Timestamp& rhs) const
675 struct tm lhtm, rhtm;
676 TIMESTAMP_TO_TM(*this, &lhtm);
677 TIMESTAMP_TO_TM(rhs, &rhtm);
678 return ( timegm(&lhtm) < timegm(&rhtm) );
683 Kumu::Timestamp::AddDays(i32_t days)
689 TIMESTAMP_TO_TM(*this, ¤t);
690 time_t adj_time = timegm(¤t);
691 adj_time += 86400 * days;
692 struct tm* now = gmtime(&adj_time);
693 TM_TO_TIMESTAMP(now, *this);
699 Kumu::Timestamp::AddHours(i32_t hours)
705 TIMESTAMP_TO_TM(*this, ¤t);
706 time_t adj_time = timegm(¤t);
707 adj_time += 3600 * hours;
708 struct tm* now = gmtime(&adj_time);
709 TM_TO_TIMESTAMP(now, *this);
716 Kumu::Timestamp::Timestamp(const Timestamp& rhs)
726 Kumu::Timestamp::~Timestamp()
731 const Kumu::Timestamp&
732 Kumu::Timestamp::operator=(const Timestamp& rhs)
745 Kumu::Timestamp::operator==(const Timestamp& rhs) const
747 if ( Year == rhs.Year
748 && Month == rhs.Month
751 && Minute == rhs.Minute
752 && Second == rhs.Second )
760 Kumu::Timestamp::operator!=(const Timestamp& rhs) const
762 if ( Year != rhs.Year
763 || Month != rhs.Month
766 || Minute != rhs.Minute
767 || Second != rhs.Second )
775 Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const
777 if ( buf_len < ( DateTimeLen + 1 ) )
780 // 2004-05-01T13:20:00-00:00
781 snprintf(str_buf, buf_len,
782 "%04hu-%02hu-%02huT%02hu:%02hu:%02hu-00:00",
783 Year, Month, Day, Hour, Minute, Second);
790 Kumu::Timestamp::DecodeString(const char* datestr)
792 if ( ! ( isdigit(datestr[0]) && isdigit(datestr[1]) && isdigit(datestr[2]) && isdigit(datestr[3]) )
794 || ! ( isdigit(datestr[5]) && isdigit(datestr[6]) )
796 || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) )
797 || datestr[10] != 'T'
798 || ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
799 || datestr[13] != ':'
800 || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) )
801 || datestr[16] != ':'
802 || ! ( isdigit(datestr[17]) && isdigit(datestr[18]) )
803 || ! ( datestr[19] == '-' || datestr[19] == '+' )
804 || ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
805 || datestr[22] != ':'
806 || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
809 // TODO -- test this!
810 Year = atoi(datestr);
811 Month = atoi(datestr + 5);
812 Day = atoi(datestr + 8);
813 Hour = atoi(datestr + 11);
814 Minute = atoi(datestr + 14);
815 Second = atoi(datestr + 17);
817 ui32_t TZ_hh = atoi(datestr + 20);
818 ui32_t TZ_mm = atoi(datestr + 23);
821 DefaultLogSink().Error("Ignoring sub-hours timezone offset: %lu\n", TZ_mm);
824 DefaultLogSink().Error("Ignoring large timezone offset: %s\n", (datestr+19));
833 Kumu::Timestamp::HasValue() const
835 if ( Year || Month || Day || Hour || Minute || Second )
843 Kumu::Timestamp::Unarchive(MemIOReader* Reader)
846 if ( ! Reader->ReadUi16BE(&Year) ) return false;
847 if ( ! Reader->ReadRaw(&Month, 6) ) return false;
853 Kumu::Timestamp::Archive(MemIOWriter* Writer) const
856 if ( ! Writer->WriteUi16BE(Year) ) return false;
857 if ( ! Writer->WriteRaw(&Month, 6) ) return false;
864 Kumu::UnarchiveString(MemIOReader* Reader, std::string&)
868 if ( ! Reader->ReadUi32BE(&str_length) ) return false;
869 assign((const char*)Reader->CurrentData(), str_length);
870 if ( ! Reader->SkipOffset(str_length) ) return false;
876 Kumu::String::Archive(MemIOWriter* Writer) const
879 if ( ! Writer->WriteUi32BE(length()) ) return false;
880 if ( ! Writer->WriteRaw((const byte_t*)c_str(), length()) ) return false;
886 //------------------------------------------------------------------------------------------
888 Kumu::MemIOWriter::MemIOWriter(ByteString* Buf)
889 : m_p(0), m_capacity(0), m_size(0)
892 m_capacity = Buf->Capacity();
893 assert(m_p); assert(m_capacity);
897 Kumu::MemIOWriter:: WriteBER(ui64_t i, ui32_t ber_len)
899 if ( ( m_size + ber_len ) > m_capacity )
902 if ( ! write_BER(m_p + m_size, i, ber_len) )
910 Kumu::MemIOReader::MemIOReader(const ByteString* Buf)
911 : m_p(0), m_capacity(0), m_size(0)
914 m_capacity = Buf->Capacity();
915 assert(m_p); assert(m_capacity);
919 Kumu::MemIOReader::ReadBER(ui64_t* i, ui32_t* ber_len)
921 if ( i == 0 || ber_len == 0 ) return false;
923 if ( ( *ber_len = BER_length(m_p + m_size) ) == 0 )
926 if ( ( m_size + *ber_len ) > m_capacity )
929 if ( ! read_BER(m_p + m_size, i) )
936 //------------------------------------------------------------------------------------------
938 Kumu::ByteString::ByteString() : m_Data(0), m_Capacity(0), m_Length(0) {}
940 Kumu::ByteString::ByteString(ui32_t cap) : m_Data(0), m_Capacity(0), m_Length(0)
945 Kumu::ByteString::~ByteString()
952 // copy the given data into the ByteString, set Length value.
953 // Returns error if the ByteString is too small.
955 Kumu::ByteString::Set(const byte_t* buf, ui32_t buf_len)
957 if ( m_Capacity < buf_len )
960 memcpy(m_Data, buf, buf_len);
966 // Sets the size of the internally allocate buffer.
967 // Resets content length to zero.
969 Kumu::ByteString::Capacity(ui32_t cap_size)
971 if ( m_Capacity < cap_size )
976 m_Data = (byte_t*)malloc(cap_size);
981 m_Capacity = cap_size;
990 Kumu::ByteString::Append(const ByteString& Buf)
992 Result_t result = RESULT_OK;
993 ui32_t diff = m_Capacity - m_Length;
995 if ( diff < Buf.Length() )
996 result = Capacity(m_Capacity + Buf.Length());
998 if ( KM_SUCCESS(result) )
1000 memcpy(m_Data + m_Length, Buf.RoData(), Buf.Length());
1001 m_Length += Buf.Length();
1009 Kumu::ByteString::Append(const byte_t* buf, ui32_t buf_len)
1011 Result_t result = RESULT_OK;
1012 ui32_t diff = m_Capacity - m_Length;
1014 if ( diff < buf_len )
1015 result = Capacity(m_Capacity + buf_len);
1017 if ( KM_SUCCESS(result) )
1019 memcpy(m_Data + m_Length, buf, buf_len);
1020 m_Length += buf_len;