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(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 );
604 seconds_to_ns100(ui32_t seconds)
606 return ((ui64_t)seconds * 10000000);
611 Kumu::Timestamp::AddDays(i32_t days)
613 SYSTEMTIME current_st;
615 ULARGE_INTEGER current_ul;
619 TIMESTAMP_TO_SYSTIME(*this, ¤t_st);
620 SystemTimeToFileTime(¤t_st, ¤t_ft);
621 memcpy(¤t_ul, ¤t_ft, sizeof(current_ul));
622 current_ul.QuadPart += ( seconds_to_ns100(86400) * (ui64_t)days );
623 memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
624 FileTimeToSystemTime(¤t_ft, ¤t_st);
625 SYSTIME_TO_TIMESTAMP(¤t_st, *this);
631 Kumu::Timestamp::AddHours(i32_t hours)
633 SYSTEMTIME current_st;
635 ULARGE_INTEGER current_ul;
639 TIMESTAMP_TO_SYSTIME(*this, ¤t_st);
640 SystemTimeToFileTime(¤t_st, ¤t_ft);
641 memcpy(¤t_ul, ¤t_ft, sizeof(current_ul));
642 current_ul.QuadPart += ( seconds_to_ns100(3600) * (ui64_t)hours );
643 memcpy(¤t_ft, ¤t_ul, sizeof(current_ft));
644 FileTimeToSystemTime(¤t_ft, ¤t_st);
645 SYSTIME_TO_TIMESTAMP(¤t_st, *this);
653 #define TIMESTAMP_TO_TM(ts, t) \
654 (t)->tm_year = (ts).Year - 1900; /* year - 1900 */ \
655 (t)->tm_mon = (ts).Month - 1; /* month of year (0 - 11) */ \
656 (t)->tm_mday = (ts).Day; /* day of month (1 - 31) */ \
657 (t)->tm_hour = (ts).Hour; /* hours (0 - 23) */ \
658 (t)->tm_min = (ts).Minute; /* minutes (0 - 59) */ \
659 (t)->tm_sec = (ts).Second; /* seconds (0 - 60) */
661 #define TM_TO_TIMESTAMP(t, ts) \
662 (ts).Year = (t)->tm_year + 1900; /* year - 1900 */ \
663 (ts).Month = (t)->tm_mon + 1; /* month of year (0 - 11) */ \
664 (ts).Day = (t)->tm_mday; /* day of month (1 - 31) */ \
665 (ts).Hour = (t)->tm_hour; /* hours (0 - 23) */ \
666 (ts).Minute = (t)->tm_min; /* minutes (0 - 59) */ \
667 (ts).Second = (t)->tm_sec; /* seconds (0 - 60) */
670 Kumu::Timestamp::Timestamp() :
671 Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
673 time_t t_now = time(0);
674 struct tm* now = gmtime(&t_now);
675 TM_TO_TIMESTAMP(now, *this);
680 Kumu::Timestamp::operator<(const Timestamp& rhs) const
682 struct tm lhtm, rhtm;
683 TIMESTAMP_TO_TM(*this, &lhtm);
684 TIMESTAMP_TO_TM(rhs, &rhtm);
685 return ( timegm(&lhtm) < timegm(&rhtm) );
690 Kumu::Timestamp::AddDays(i32_t days)
696 TIMESTAMP_TO_TM(*this, ¤t);
697 time_t adj_time = timegm(¤t);
698 adj_time += 86400 * days;
699 struct tm* now = gmtime(&adj_time);
700 TM_TO_TIMESTAMP(now, *this);
706 Kumu::Timestamp::AddHours(i32_t hours)
712 TIMESTAMP_TO_TM(*this, ¤t);
713 time_t adj_time = timegm(¤t);
714 adj_time += 3600 * hours;
715 struct tm* now = gmtime(&adj_time);
716 TM_TO_TIMESTAMP(now, *this);
723 Kumu::Timestamp::Timestamp(const Timestamp& rhs)
733 Kumu::Timestamp::~Timestamp()
738 const Kumu::Timestamp&
739 Kumu::Timestamp::operator=(const Timestamp& rhs)
752 Kumu::Timestamp::operator==(const Timestamp& rhs) const
754 if ( Year == rhs.Year
755 && Month == rhs.Month
758 && Minute == rhs.Minute
759 && Second == rhs.Second )
767 Kumu::Timestamp::operator!=(const Timestamp& rhs) const
769 if ( Year != rhs.Year
770 || Month != rhs.Month
773 || Minute != rhs.Minute
774 || Second != rhs.Second )
782 Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const
784 if ( buf_len < ( DateTimeLen + 1 ) )
787 // 2004-05-01T13:20:00-00:00
788 snprintf(str_buf, buf_len,
789 "%04hu-%02hu-%02huT%02hu:%02hu:%02hu-00:00",
790 Year, Month, Day, Hour, Minute, Second);
797 Kumu::Timestamp::DecodeString(const char* datestr)
801 if ( ! ( isdigit(datestr[0]) && isdigit(datestr[1]) && isdigit(datestr[2]) && isdigit(datestr[3]) )
803 || ! ( isdigit(datestr[5]) && isdigit(datestr[6]) )
805 || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) ) )
808 TmpStamp.Year = atoi(datestr);
809 TmpStamp.Month = atoi(datestr + 5);
810 TmpStamp.Day = atoi(datestr + 8);
811 TmpStamp.Hour = TmpStamp.Minute = TmpStamp.Second = 0;
813 if ( datestr[10] == 'T' )
815 if ( ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
816 || datestr[13] != ':'
817 || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) ) )
820 TmpStamp.Hour = atoi(datestr + 11);
821 TmpStamp.Minute = atoi(datestr + 14);
823 if ( datestr[16] == ':' )
825 if ( ! ( isdigit(datestr[17]) && isdigit(datestr[18]) ) )
828 TmpStamp.Second = atoi(datestr + 17);
832 if ( datestr[19] == '-' || datestr[19] == '+' )
834 if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
835 || datestr[22] != ':'
836 || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
839 ui32_t TZ_hh = atoi(datestr + 20);
840 ui32_t TZ_mm = atoi(datestr + 23);
843 DefaultLogSink().Error("Ignoring minutes in timezone offset: %u\n", TZ_mm);
849 AddHours( (datestr[19] == '-' ? (-TZ_hh) : TZ_hh));
855 TIMESTAMP_TO_SYSTIME(TmpStamp, &st);
856 if ( SystemTimeToFileTime(&st, &ft) == 0 )
858 SYSTIME_TO_TIMESTAMP(&st, *this);
861 TIMESTAMP_TO_TM(TmpStamp, &stm);
862 if ( timegm(&stm) == 0 )
864 TM_TO_TIMESTAMP(&stm, *this);
872 Kumu::Timestamp::HasValue() const
874 if ( Year || Month || Day || Hour || Minute || Second )
882 Kumu::Timestamp::Unarchive(MemIOReader* Reader)
885 if ( ! Reader->ReadUi16BE(&Year) ) return false;
886 if ( ! Reader->ReadRaw(&Month, 6) ) return false;
892 Kumu::Timestamp::Archive(MemIOWriter* Writer) const
895 if ( ! Writer->WriteUi16BE(Year) ) return false;
896 if ( ! Writer->WriteRaw(&Month, 6) ) return false;
903 Kumu::UnarchiveString(MemIOReader* Reader, std::string&)
907 if ( ! Reader->ReadUi32BE(&str_length) ) return false;
908 assign((const char*)Reader->CurrentData(), str_length);
909 if ( ! Reader->SkipOffset(str_length) ) return false;
915 Kumu::String::Archive(MemIOWriter* Writer) const
918 if ( ! Writer->WriteUi32BE(length()) ) return false;
919 if ( ! Writer->WriteRaw((const byte_t*)c_str(), length()) ) return false;
925 //------------------------------------------------------------------------------------------
927 Kumu::MemIOWriter::MemIOWriter(ByteString* Buf)
928 : m_p(0), m_capacity(0), m_size(0)
931 m_capacity = Buf->Capacity();
932 assert(m_p); assert(m_capacity);
936 Kumu::MemIOWriter:: WriteBER(ui64_t i, ui32_t ber_len)
938 if ( ( m_size + ber_len ) > m_capacity )
941 if ( ! write_BER(m_p + m_size, i, ber_len) )
949 Kumu::MemIOReader::MemIOReader(const ByteString* Buf)
950 : m_p(0), m_capacity(0), m_size(0)
953 m_capacity = Buf->Capacity();
954 assert(m_p); assert(m_capacity);
958 Kumu::MemIOReader::ReadBER(ui64_t* i, ui32_t* ber_len)
960 if ( i == 0 || ber_len == 0 ) return false;
962 if ( ( *ber_len = BER_length(m_p + m_size) ) == 0 )
965 if ( ( m_size + *ber_len ) > m_capacity )
968 if ( ! read_BER(m_p + m_size, i) )
975 //------------------------------------------------------------------------------------------
977 Kumu::ByteString::ByteString() : m_Data(0), m_Capacity(0), m_Length(0) {}
979 Kumu::ByteString::ByteString(ui32_t cap) : m_Data(0), m_Capacity(0), m_Length(0)
984 Kumu::ByteString::~ByteString()
991 // copy the given data into the ByteString, set Length value.
992 // Returns error if the ByteString is too small.
994 Kumu::ByteString::Set(const byte_t* buf, ui32_t buf_len)
996 if ( m_Capacity < buf_len )
999 memcpy(m_Data, buf, buf_len);
1005 // Sets the size of the internally allocate buffer.
1006 // Resets content length to zero.
1008 Kumu::ByteString::Capacity(ui32_t cap_size)
1010 if ( m_Capacity < cap_size )
1015 m_Data = (byte_t*)malloc(cap_size);
1018 return RESULT_ALLOC;
1020 m_Capacity = cap_size;
1029 Kumu::ByteString::Append(const ByteString& Buf)
1031 Result_t result = RESULT_OK;
1032 ui32_t diff = m_Capacity - m_Length;
1034 if ( diff < Buf.Length() )
1035 result = Capacity(m_Capacity + Buf.Length());
1037 if ( KM_SUCCESS(result) )
1039 memcpy(m_Data + m_Length, Buf.RoData(), Buf.Length());
1040 m_Length += Buf.Length();
1048 Kumu::ByteString::Append(const byte_t* buf, ui32_t buf_len)
1050 Result_t result = RESULT_OK;
1051 ui32_t diff = m_Capacity - m_Length;
1053 if ( diff < buf_len )
1054 result = Capacity(m_Capacity + buf_len);
1056 if ( KM_SUCCESS(result) )
1058 memcpy(m_Data + m_Length, buf, buf_len);
1059 m_Length += buf_len;