2 Copyright (c) 2005-2009, 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 // The version number declaration and explanation are in ../configure.ac
44 const char* Version();
46 // a class that represents the string form of a value
47 template <class T, int SIZE = 16>
48 class IntPrinter : public std::string
50 KM_NO_COPY_CONSTRUCT(IntPrinter);
58 IntPrinter(const char* format, T value) {
61 snprintf(m_strbuf, SIZE, m_format, value);
64 inline operator const char*() { return m_strbuf; }
65 inline const char* c_str() { return m_strbuf; }
66 inline const char* set_value(T value) {
67 snprintf(m_strbuf, SIZE, m_format, value);
72 struct i8Printer : public IntPrinter<i8_t> {
73 i8Printer(i8_t value) : IntPrinter<i8_t>("%hd", value) {}
76 struct ui8Printer : public IntPrinter<ui8_t> {
77 ui8Printer(ui8_t value) : IntPrinter<ui8_t>("%hu", value) {}
80 struct i16Printer : public IntPrinter<i16_t> {
81 i16Printer(i16_t value) : IntPrinter<i16_t>("%hd", value) {}
84 struct ui16Printer : public IntPrinter<ui16_t> {
85 ui16Printer(ui16_t value) : IntPrinter<ui16_t>("%hu", value) {}
88 struct i32Printer : public IntPrinter<i32_t> {
89 i32Printer(i32_t value) : IntPrinter<i32_t>("%d", value) {}
92 struct ui32Printer : public IntPrinter<ui32_t> {
93 ui32Printer(ui32_t value) : IntPrinter<ui32_t>("%u", value) {}
97 struct i64Printer : public IntPrinter<i64_t, 32> {
98 i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%I64d", value) {}
101 struct ui64Printer : public IntPrinter<ui64_t, 32> {
102 ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%I64u", value) {}
105 struct i64Printer : public IntPrinter<i64_t, 32> {
106 i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%qd", value) {}
109 struct ui64Printer : public IntPrinter<ui64_t, 32> {
110 ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%qu", value) {}
114 // Convert NULL-terminated UTF-8 hexadecimal string to binary, returns 0 if
115 // the binary buffer was large enough to hold the result. The output parameter
116 // 'char_count' will contain the length of the converted string. If the output
117 // buffer is too small or any of the pointer arguments are NULL, the subroutine
118 // will return -1 and set 'char_count' to the required buffer size. No data will
119 // be written to 'buf' if the subroutine fails.
120 i32_t hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
122 // Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
123 // if the output buffer was large enough to hold the result. If the output buffer
124 // is too small or any of the pointer arguments are NULL, the subroutine will
127 const char* bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
129 const char* bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
131 // same as above for base64 text
132 i32_t base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
133 const char* base64encode(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
135 // returns the length of a Base64 encoding of a buffer of the given length
136 inline ui32_t base64_encode_length(ui32_t length) {
137 while ( ( length % 3 ) != 0 )
140 return ( length / 3 ) * 4;
143 // print buffer contents to a stream as hexadecimal values in numbered
144 // rows of 16-bytes each.
146 void hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream = 0);
148 // Return the length in bytes of a BER encoded value
149 inline ui32_t BER_length(const byte_t* buf)
151 if ( buf == 0 || (*buf & 0xf0) != 0x80 )
154 return (*buf & 0x0f) + 1;
158 bool read_BER(const byte_t* buf, ui64_t* val);
160 // decode a ber value and compare it to a test value
161 bool read_test_BER(byte_t **buf, ui64_t test_value);
163 // create BER encoding of integer value
164 bool write_BER(byte_t* buf, ui64_t val, ui32_t ber_len = 0);
166 //----------------------------------------------------------------
169 // an abstract base class that objects implement to serialize state
170 // to and from a binary stream.
174 virtual ~IArchive(){}
175 virtual bool HasValue() const = 0;
176 virtual ui32_t ArchiveLength() const = 0;
177 virtual bool Archive(MemIOWriter* Writer) const = 0;
178 virtual bool Unarchive(MemIOReader* Reader) = 0;
183 class ArchivableList : public std::list<T>, public IArchive
187 virtual ~ArchivableList() {}
189 bool HasValue() const { return ! this->empty(); }
191 ui32_t ArchiveLength() const
193 ui32_t arch_size = sizeof(ui32_t);
195 typename ArchivableList<T>::const_iterator i = this->begin();
196 for ( ; i != this->end(); i++ )
197 arch_size += i->ArchiveLength();
202 bool Unarchive(Kumu::MemIOReader* Reader)
204 if ( Reader == 0 ) return false;
205 ui32_t read_size = 0;
206 if ( ! Reader->ReadUi32BE(&read_size) ) return false;
207 for ( ui32_t i = 0; i < read_size; i++ )
210 if ( ! TmpTP.Unarchive(Reader) ) return false;
211 this->push_back(TmpTP);
217 bool Archive(Kumu::MemIOWriter* Writer) const
219 if ( Writer == 0 ) return false;
220 if ( ! Writer->WriteUi32BE(this->size()) ) return false;
221 typename ArchivableList<T>::const_iterator i = this->begin();
222 for ( ; i != this->end(); i++ )
223 if ( ! i->Archive(Writer) ) return false;
230 // the base of all identifier classes, Identifier is not usually used directly
231 // see UUID and SymmetricKey below for more detail.
233 template <ui32_t SIZE>
234 class Identifier : public IArchive
238 byte_t m_Value[SIZE];
241 Identifier() : m_HasValue(false) { memset(m_Value, 0, SIZE); }
242 Identifier(const byte_t* value) : m_HasValue(true) { memcpy(m_Value, value, SIZE); }
243 Identifier(const Identifier& rhs) : IArchive() {
244 m_HasValue = rhs.m_HasValue;
245 memcpy(m_Value, rhs.m_Value, SIZE);
248 virtual ~Identifier() {}
250 const Identifier& operator=(const Identifier& rhs) {
251 m_HasValue = rhs.m_HasValue;
252 memcpy(m_Value, rhs.m_Value, SIZE);
256 inline void Set(const byte_t* value) { m_HasValue = true; memcpy(m_Value, value, SIZE); }
257 inline void Reset() { m_HasValue = false; memset(m_Value, 0, SIZE); }
258 inline const byte_t* Value() const { return m_Value; }
259 inline ui32_t Size() const { return SIZE; }
261 inline bool operator<(const Identifier& rhs) const {
262 ui32_t test_size = xmin(rhs.Size(), SIZE);
264 for ( ui32_t i = 0; i < test_size; i++ )
266 if ( m_Value[i] != rhs.m_Value[i] )
267 return m_Value[i] < rhs.m_Value[i];
273 inline bool operator==(const Identifier& rhs) const {
274 if ( rhs.Size() != SIZE ) return false;
275 return ( memcmp(m_Value, rhs.m_Value, SIZE) == 0 );
278 inline bool operator!=(const Identifier& rhs) const {
279 if ( rhs.Size() != SIZE ) return true;
280 return ( memcmp(m_Value, rhs.m_Value, SIZE) != 0 );
283 inline bool DecodeHex(const char* str) {
285 m_HasValue = ( hex2bin(str, m_Value, SIZE, &char_count) == 0 );
286 if ( m_HasValue && char_count != SIZE )
291 inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
292 return bin2hex(m_Value, SIZE, buf, buf_len);
295 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
296 return EncodeHex(str_buf, buf_len);
299 inline bool DecodeBase64(const char* str) {
301 m_HasValue = ( base64decode(str, m_Value, SIZE, &char_count) == 0 );
302 if ( m_HasValue && char_count != SIZE )
307 inline const char* EncodeBase64(char* buf, ui32_t buf_len) const {
308 return base64encode(m_Value, SIZE, buf, buf_len);
311 inline bool HasValue() const { return m_HasValue; }
313 inline ui32_t ArchiveLength() const { return SIZE; }
315 inline bool Unarchive(Kumu::MemIOReader* Reader) {
316 m_HasValue = Reader->ReadRaw(m_Value, SIZE);
320 inline bool Archive(Kumu::MemIOWriter* Writer) const {
321 return Writer->WriteRaw(m_Value, SIZE);
328 const ui32_t UUID_Length = 16;
329 class UUID : public Identifier<UUID_Length>
333 UUID(const byte_t* value) : Identifier<UUID_Length>(value) {}
334 UUID(const UUID& rhs) : Identifier<UUID_Length>(rhs) {}
337 inline const char* EncodeString(char* buf, ui32_t buf_len) const {
338 return bin2UUIDhex(m_Value, Size(), buf, buf_len);
341 inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
342 return bin2UUIDhex(m_Value, Size(), buf, buf_len);
346 void GenRandomUUID(byte_t* buf); // buf must be UUID_Length or longer
347 void GenRandomValue(UUID&);
349 typedef ArchivableList<UUID> UUIDList;
351 // a self-wiping key container
353 const ui32_t SymmetricKey_Length = 16;
354 const byte_t NilKey[SymmetricKey_Length] = {
355 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce,
356 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce
359 class SymmetricKey : public Identifier<SymmetricKey_Length>
363 SymmetricKey(const byte_t* value) : Identifier<SymmetricKey_Length>(value) {}
364 SymmetricKey(const UUID& rhs) : Identifier<SymmetricKey_Length>(rhs) {}
365 virtual ~SymmetricKey() { memcpy(m_Value, NilKey, 16); m_HasValue = false; }
368 void GenRandomValue(SymmetricKey&);
371 // 2004-05-01T13:20:00+00:00
372 const ui32_t DateTimeLen = 25; // the number of chars in the xs:dateTime format (sans milliseconds)
374 // UTC time+date representation
375 class Timestamp : public IArchive
386 Timestamp(const Timestamp& rhs);
387 Timestamp(const char* datestr);
388 virtual ~Timestamp();
390 const Timestamp& operator=(const Timestamp& rhs);
391 bool operator<(const Timestamp& rhs) const;
392 bool operator>(const Timestamp& rhs) const;
393 bool operator==(const Timestamp& rhs) const;
394 bool operator!=(const Timestamp& rhs) const;
396 // Write the timestamp value to the given buffer in the form 2004-05-01T13:20:00+00:00
397 // returns 0 if the buffer is smaller than DateTimeLen
398 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
399 const char* EncodeStringWithOffset(char* str_buf, ui32_t buf_len,
400 i32_t offset_minutes = 0) const;
402 // decode and set value from string formatted by EncodeString
403 bool DecodeString(const char* datestr);
405 // Add the given number of days, hours, minutes, or seconds to the timestamp value.
406 // Values less than zero will cause the timestamp to decrease
408 void AddHours(i32_t);
409 void AddMinutes(i32_t);
410 void AddSeconds(i32_t);
412 // Read and write the timestamp value as a byte string having
413 // the following format:
414 // | 16 bits int, big-endian | 8 bits | 8 bits | 8 bits | 8 bits | 8 bits |
415 // | Year A.D | Month(1-12) | Day(1-31) | Hour(0-23) | Minute(0-59) | Second(0-59) |
417 virtual bool HasValue() const;
418 virtual ui32_t ArchiveLength() const { return 8L; }
419 virtual bool Archive(MemIOWriter* Writer) const;
420 virtual bool Unarchive(MemIOReader* Reader);
422 // Get the number of seconds since the Unix epoch (1970-01-01T00:00:00+00:00)
423 long GetSecondsSinceEpoch(void) const;
427 class ByteString : public IArchive
429 KM_NO_COPY_CONSTRUCT(ByteString);
432 byte_t* m_Data; // pointer to memory area containing frame data
433 ui32_t m_Capacity; // size of memory area pointed to by m_Data
434 ui32_t m_Length; // length of byte string in memory area pointed to by m_Data
438 ByteString(ui32_t cap);
439 virtual ~ByteString();
441 // Sets or resets the size of the internally allocated buffer.
442 Result_t Capacity(ui32_t cap);
444 Result_t Append(const ByteString&);
445 Result_t Append(const byte_t* buf, ui32_t buf_len);
447 // returns the size of the buffer
448 inline ui32_t Capacity() const { return m_Capacity; }
450 // returns a const pointer to the essence data
451 inline const byte_t* RoData() const { assert(m_Data); return m_Data; }
453 // returns a non-const pointer to the essence data
454 inline byte_t* Data() { assert(m_Data); return m_Data; }
456 // set the length of the buffer's contents
457 inline ui32_t Length(ui32_t l) { return m_Length = l; }
459 // returns the length of the buffer's contents
460 inline ui32_t Length() const { return m_Length; }
462 // copy the given data into the ByteString, set Length value.
463 // Returns error if the ByteString is too small.
464 Result_t Set(const byte_t* buf, ui32_t buf_len);
465 Result_t Set(const ByteString& Buf);
467 inline virtual bool HasValue() const { return m_Length > 0; }
469 inline virtual ui32_t ArchiveLength() const { return m_Length; }
471 inline virtual bool Archive(MemIOWriter* Writer) const {
473 if ( ! Writer->WriteUi32BE(m_Length) ) return false;
474 if ( ! Writer->WriteRaw(m_Data, m_Length) ) return false;
478 inline virtual bool Unarchive(MemIOReader* Reader) {
481 if ( ! Reader->ReadUi32BE(&tmp_len) ) return false;
482 if ( KM_FAILURE(Capacity(tmp_len)) ) return false;
483 if ( ! Reader->ReadRaw(m_Data, tmp_len) ) return false;
492 #endif // _KM_UTIL_H_