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
43 // a class that represents the string form of a value
44 template <class T, int SIZE = 16>
45 class IntPrinter : public std::string
47 KM_NO_COPY_CONSTRUCT(IntPrinter);
55 IntPrinter(const char* format, T value) {
58 snprintf(m_strbuf, SIZE, m_format, value);
61 inline operator const char*() { return m_strbuf; }
62 inline const char* c_str() { return m_strbuf; }
63 inline const char* set_value(T value) {
64 snprintf(m_strbuf, SIZE, m_format, value);
69 struct i8Printer : public IntPrinter<i8_t> {
70 i8Printer(i8_t value) : IntPrinter<i8_t>("%hd", value) {}
73 struct ui8Printer : public IntPrinter<ui8_t> {
74 ui8Printer(ui8_t value) : IntPrinter<ui8_t>("%hu", value) {}
77 struct i16Printer : public IntPrinter<i16_t> {
78 i16Printer(i16_t value) : IntPrinter<i16_t>("%hd", value) {}
81 struct ui16Printer : public IntPrinter<ui16_t> {
82 ui16Printer(ui16_t value) : IntPrinter<ui16_t>("%hu", value) {}
85 struct i32Printer : public IntPrinter<i32_t> {
86 i32Printer(i32_t value) : IntPrinter<i32_t>("%d", value) {}
89 struct ui32Printer : public IntPrinter<ui32_t> {
90 ui32Printer(ui32_t value) : IntPrinter<ui32_t>("%u", value) {}
94 struct i64Printer : public IntPrinter<i64_t, 32> {
95 i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%I64d", value) {}
98 struct ui64Printer : public IntPrinter<ui64_t, 32> {
99 ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%I64u", value) {}
102 struct i64Printer : public IntPrinter<i64_t, 32> {
103 i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%qd", value) {}
106 struct ui64Printer : public IntPrinter<ui64_t, 32> {
107 ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%qu", value) {}
111 // Convert NULL-terminated UTF-8 hexadecimal string to binary, returns 0 if
112 // the binary buffer was large enough to hold the result. The output parameter
113 // 'char_count' will contain the length of the converted string. If the output
114 // buffer is too small or any of the pointer arguments are NULL, the subroutine
115 // will return -1 and set 'char_count' to the required buffer size. No data will
116 // be written to 'buf' if the subroutine fails.
117 i32_t hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
119 // Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
120 // if the output buffer was large enough to hold the result. If the output buffer
121 // is too small or any of the pointer arguments are NULL, the subroutine will
124 const char* bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
126 const char* bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
128 // same as above for base64 text
129 i32_t base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
130 const char* base64encode(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
132 // returns the length of a Base64 encoding of a buffer of the given length
133 inline ui32_t base64_encode_length(ui32_t length) {
134 while ( ( length % 3 ) != 0 )
137 return ( length / 3 ) * 4;
140 // print buffer contents to a stream as hexadecimal values in numbered
141 // rows of 16-bytes each.
143 void hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream = 0);
145 // Return the length in bytes of a BER encoded value
146 inline ui32_t BER_length(const byte_t* buf)
148 if ( buf == 0 || (*buf & 0xf0) != 0x80 )
151 return (*buf & 0x0f) + 1;
155 bool read_BER(const byte_t* buf, ui64_t* val);
157 // decode a ber value and compare it to a test value
158 bool read_test_BER(byte_t **buf, ui64_t test_value);
160 // create BER encoding of integer value
161 bool write_BER(byte_t* buf, ui64_t val, ui32_t ber_len = 0);
163 //----------------------------------------------------------------
166 // an abstract base class that objects implement to serialize state
167 // to and from a binary stream.
171 virtual ~IArchive(){}
172 virtual bool HasValue() const = 0;
173 virtual bool Archive(MemIOWriter* Writer) const = 0;
174 virtual bool Unarchive(MemIOReader* Reader) = 0;
179 // the base of all identifier classes, Identifier is not usually used directly
180 // see UUID and SymmetricKey below for more detail.
182 template <ui32_t SIZE>
183 class Identifier : public IArchive
187 byte_t m_Value[SIZE];
190 Identifier() : m_HasValue(false) { memset(m_Value, 0, SIZE); }
191 Identifier(const byte_t* value) : m_HasValue(true) { memcpy(m_Value, value, SIZE); }
192 Identifier(const Identifier& rhs) {
193 m_HasValue = rhs.m_HasValue;
194 memcpy(m_Value, rhs.m_Value, SIZE);
197 virtual ~Identifier() {}
199 const Identifier& operator=(const Identifier& rhs) {
200 m_HasValue = rhs.m_HasValue;
201 memcpy(m_Value, rhs.m_Value, SIZE);
205 inline void Set(const byte_t* value) { m_HasValue = true; memcpy(m_Value, value, SIZE); }
206 inline void Reset() { m_HasValue = false; memset(m_Value, 0, SIZE); }
207 inline const byte_t* Value() const { return m_Value; }
208 inline ui32_t Size() const { return SIZE; }
210 inline bool operator<(const Identifier& rhs) const {
211 ui32_t test_size = xmin(rhs.Size(), SIZE);
213 for ( ui32_t i = 0; i < test_size; i++ )
215 if ( m_Value[i] != rhs.m_Value[i] )
216 return m_Value[i] < rhs.m_Value[i];
222 inline bool operator==(const Identifier& rhs) const {
223 if ( rhs.Size() != SIZE ) return false;
224 return ( memcmp(m_Value, rhs.m_Value, SIZE) == 0 );
227 inline bool operator!=(const Identifier& rhs) const {
228 if ( rhs.Size() != SIZE ) return true;
229 return ( memcmp(m_Value, rhs.m_Value, SIZE) != 0 );
232 inline bool DecodeHex(const char* str) {
234 m_HasValue = ( hex2bin(str, m_Value, SIZE, &char_count) == 0 );
238 inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
239 return bin2hex(m_Value, SIZE, buf, buf_len);
242 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
243 return EncodeHex(str_buf, buf_len);
246 inline bool DecodeBase64(const char* str) {
248 m_HasValue = ( base64decode(str, m_Value, SIZE, &char_count) == 0 );
252 inline const char* EncodeBase64(char* buf, ui32_t buf_len) const {
253 return base64encode(m_Value, SIZE, buf, buf_len);
256 inline bool HasValue() const { return m_HasValue; }
258 inline bool Unarchive(Kumu::MemIOReader* Reader) {
259 m_HasValue = Reader->ReadRaw(m_Value, SIZE);
263 inline bool Archive(Kumu::MemIOWriter* Writer) const {
264 return Writer->WriteRaw(m_Value, SIZE);
271 const ui32_t UUID_Length = 16;
272 class UUID : public Identifier<UUID_Length>
276 UUID(const byte_t* value) : Identifier<UUID_Length>(value) {}
277 UUID(const UUID& rhs) : Identifier<UUID_Length>(rhs) {}
280 inline const char* EncodeString(char* buf, ui32_t buf_len) const {
281 return bin2UUIDhex(m_Value, Size(), buf, buf_len);
284 inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
285 return bin2UUIDhex(m_Value, Size(), buf, buf_len);
289 void GenRandomUUID(byte_t* buf); // buf must be UUID_Length or longer
290 void GenRandomValue(UUID&);
292 // a self-wiping key container
294 const ui32_t SymmetricKey_Length = 16;
295 const byte_t NilKey[SymmetricKey_Length] = {
296 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce,
297 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce
300 class SymmetricKey : public Identifier<SymmetricKey_Length>
304 SymmetricKey(const byte_t* value) : Identifier<SymmetricKey_Length>(value) {}
305 SymmetricKey(const UUID& rhs) : Identifier<SymmetricKey_Length>(rhs) {}
306 virtual ~SymmetricKey() { memcpy(m_Value, NilKey, 16); m_HasValue = false; }
309 void GenRandomValue(SymmetricKey&);
312 // 2004-05-01T13:20:00-00:00
313 const ui32_t DateTimeLen = 25; // the number of chars in the xs:dateTime format (sans milliseconds)
315 // UTC time+date representation
316 class Timestamp : public IArchive
327 Timestamp(const Timestamp& rhs);
328 Timestamp(const char* datestr);
329 virtual ~Timestamp();
331 const Timestamp& operator=(const Timestamp& rhs);
332 bool operator<(const Timestamp& rhs) const;
333 bool operator>(const Timestamp& rhs) const;
334 bool operator==(const Timestamp& rhs) const;
335 bool operator!=(const Timestamp& rhs) const;
337 // Write the timestamp value to the given buffer in the form 2004-05-01T13:20:00-00:00
338 // returns 0 if the buffer is smaller than DateTimeLen
339 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
341 // decode and set value from string formatted by EncodeString
342 bool DecodeString(const char* datestr);
344 // Add the given number of days or hours to the timestamp value.
345 // Values less than zero will cause the timestamp to decrease
347 void AddHours(i32_t);
349 // Read and write the timestamp value as a byte string having
350 // the following format:
351 // | 16 bits int, big-endian | 8 bits | 8 bits | 8 bits | 8 bits | 8 bits |
352 // | Year A.D | Month(1-12) | Day(1-31) | Hour(0-23) | Minute(0-59) | Second(0-59) |
354 virtual bool HasValue() const;
355 virtual bool Archive(MemIOWriter* Writer) const;
356 virtual bool Unarchive(MemIOReader* Reader);
360 class ByteString : public IArchive
362 KM_NO_COPY_CONSTRUCT(ByteString);
365 byte_t* m_Data; // pointer to memory area containing frame data
366 ui32_t m_Capacity; // size of memory area pointed to by m_Data
367 ui32_t m_Length; // length of byte string in memory area pointed to by m_Data
371 ByteString(ui32_t cap);
372 virtual ~ByteString();
374 // Sets the size of the internally allocated buffer.
375 // Resets content Size to zero.
376 Result_t Capacity(ui32_t cap);
378 Result_t Append(const ByteString&);
379 Result_t Append(const byte_t* buf, ui32_t buf_len);
381 // returns the size of the buffer
382 inline ui32_t Capacity() const { return m_Capacity; }
384 // returns a const pointer to the essence data
385 inline const byte_t* RoData() const { assert(m_Data); return m_Data; }
387 // returns a non-const pointer to the essence data
388 inline byte_t* Data() { assert(m_Data); return m_Data; }
390 // set the length of the buffer's contents
391 inline ui32_t Length(ui32_t l) { return m_Length = l; }
393 // returns the length of the buffer's contents
394 inline ui32_t Length() const { return m_Length; }
396 // copy the given data into the ByteString, set Length value.
397 // Returns error if the ByteString is too small.
398 Result_t Set(const byte_t* buf, ui32_t buf_len);
399 Result_t Set(const ByteString& Buf);
401 inline virtual bool HasValue() const { return m_Length > 0; }
403 inline virtual bool Archive(MemIOWriter* Writer) const {
405 if ( ! Writer->WriteUi32BE(m_Length) ) return false;
406 if ( ! Writer->WriteRaw(m_Data, m_Length) ) return false;
410 inline virtual bool Unarchive(MemIOReader* Reader) {
412 if ( ! Reader->ReadUi32BE(&m_Length) ) return false;
413 if ( KM_FAILURE(Capacity(m_Length)) ) return false;
414 if ( ! Reader->ReadRaw(m_Data, m_Length) ) return false;
422 #endif // _KM_UTIL_H_