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 template <class T, int SIZE = 16>
44 class IntPrinter : public std::string
51 inline const char* c_str() { return m_strbuf; }
53 IntPrinter(const char* format, T value) {
54 snprintf(m_strbuf, SIZE, format, value);
58 struct i8Printer : public IntPrinter<i8_t> {
59 i8Printer(i8_t value) : IntPrinter<i8_t>("%hd", value) {}
62 struct ui8Printer : public IntPrinter<ui8_t> {
63 ui8Printer(ui8_t value) : IntPrinter<ui8_t>("%hu", value) {}
66 struct i16Printer : public IntPrinter<i16_t> {
67 i16Printer(i16_t value) : IntPrinter<i16_t>("%hd", value) {}
70 struct ui16Printer : public IntPrinter<ui16_t> {
71 ui16Printer(ui16_t value) : IntPrinter<ui16_t>("%hu", value) {}
74 struct i32Printer : public IntPrinter<i32_t> {
75 i32Printer(i32_t value) : IntPrinter<i32_t>("%d", value) {}
78 struct ui32Printer : public IntPrinter<ui32_t> {
79 ui32Printer(ui32_t value) : IntPrinter<ui32_t>("%u", value) {}
83 struct i64Printer : public IntPrinter<i64_t, 32> {
84 i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%I64d", value) {}
87 struct ui64Printer : public IntPrinter<ui64_t, 32> {
88 ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%I64u", value) {}
91 struct i64Printer : public IntPrinter<i64_t, 32> {
92 i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%qd", value) {}
95 struct ui64Printer : public IntPrinter<ui64_t, 32> {
96 ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%qu", value) {}
100 // Convert NULL-terminated UTF-8 hexadecimal string to binary, returns 0 if
101 // the binary buffer was large enough to hold the result. The output parameter
102 // 'char_count' will contain the length of the converted string. If the output
103 // buffer is too small or any of the pointer arguments are NULL, the subroutine
104 // will return -1 and set 'char_count' to the required buffer size. No data will
105 // be written to 'buf' if the subroutine fails.
106 i32_t hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
108 // Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
109 // if the binary buffer was large enough to hold the result. If the output buffer
110 // is too small or any of the pointer arguments are NULL, the subroutine will
113 const char* bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
115 const char* bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
117 // same as above for base64 text
118 i32_t base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
119 const char* base64encode(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
121 // returns the length of a Base64 encoding of a buffer of the given length
122 inline ui32_t base64_encode_length(ui32_t length) {
123 while ( ( length % 3 ) != 0 )
126 return ( length / 3 ) * 4;
129 // print buffer contents to a stream as hexadecimal values in numbered
130 // rows of 16-bytes each.
132 void hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream = 0);
134 // Return the length in bytes of a BER encoded value
135 inline ui32_t BER_length(const byte_t* buf)
137 if ( buf == 0 || (*buf & 0xf0) != 0x80 )
140 return (*buf & 0x0f) + 1;
144 bool read_BER(const byte_t* buf, ui64_t* val);
146 // decode a ber value and compare it to a test value
147 bool read_test_BER(byte_t **buf, ui64_t test_value);
149 // create BER encoding of integer value
150 bool write_BER(byte_t* buf, ui64_t val, ui32_t ber_len = 0);
152 //----------------------------------------------------------------
158 virtual ~IArchive(){}
159 virtual bool HasValue() const = 0;
160 virtual bool Archive(MemIOWriter* Writer) const = 0;
161 virtual bool Unarchive(MemIOReader* Reader) = 0;
166 // the base of all identifier classes
167 template <ui32_t SIZE>
168 class Identifier : public IArchive
170 const Identifier& operator=(const Identifier& rhs);
174 byte_t m_Value[SIZE];
177 Identifier() : m_HasValue(false) { memset(m_Value, 0, SIZE); }
178 Identifier(const byte_t* value) : m_HasValue(true) { memcpy(m_Value, value, SIZE); }
179 Identifier(const Identifier& rhs) {
180 if ( m_HasValue = rhs.m_HasValue )
181 memcpy(m_Value, rhs.m_Value, SIZE);
184 virtual ~Identifier() {}
186 inline void Set(const byte_t* value) { m_HasValue = true; memcpy(m_Value, value, SIZE); }
187 inline const byte_t* Value() const { return m_Value; }
188 inline ui32_t Size() const { return SIZE; }
190 inline bool operator<(const Identifier& rhs) const
192 ui32_t test_size = xmin(rhs.Size(), SIZE);
193 for ( ui32_t i = 0; i < test_size; i++ )
195 if ( m_Value[i] != rhs.m_Value[i] )
196 return m_Value[i] < rhs.m_Value[i];
202 inline bool operator==(const Identifier& rhs) const
204 if ( rhs.Size() != SIZE ) return false;
205 return ( memcmp(m_Value, rhs.m_Value, SIZE) == 0 );
208 inline bool operator!=(const Identifier& rhs) const
210 if ( rhs.Size() != SIZE ) return true;
211 return ( memcmp(m_Value, rhs.m_Value, SIZE) != 0 );
214 inline bool DecodeHex(const char* str)
217 m_HasValue = ( hex2bin(str, m_Value, SIZE, &char_count) == 0 );
221 inline const char* EncodeHex(char* buf, ui32_t buf_len) const
223 return bin2hex(m_Value, SIZE, buf, buf_len);
226 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
227 return EncodeHex(str_buf, buf_len);
230 inline bool DecodeBase64(const char* str)
233 m_HasValue = ( base64decode(str, m_Value, SIZE, &char_count) == 0 );
237 inline const char* EncodeBase64(char* buf, ui32_t buf_len) const
239 return base64encode(m_Value, SIZE, buf, buf_len);
242 inline bool HasValue() const { return m_HasValue; }
244 inline bool Unarchive(Kumu::MemIOReader* Reader) {
245 m_HasValue = Reader->ReadRaw(m_Value, SIZE);
249 inline bool Archive(Kumu::MemIOWriter* Writer) const {
250 return Writer->WriteRaw(m_Value, SIZE);
257 const ui32_t UUID_Length = 16;
258 class UUID : public Identifier<UUID_Length>
262 UUID(const byte_t* value) : Identifier<UUID_Length>(value) {}
263 UUID(const UUID& rhs) : Identifier<UUID_Length>(rhs) {}
266 const UUID& operator=(const UUID& rhs) {
267 if ( m_HasValue = rhs.m_HasValue )
268 memcpy(m_Value, rhs.m_Value, UUID_Length);
272 inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
273 return bin2UUIDhex(m_Value, Size(), buf, buf_len);
277 void GenRandomUUID(byte_t* buf);
278 void GenRandomValue(UUID&);
280 // a self-wiping key container
282 const ui32_t SymmetricKey_Length = 16;
283 const byte_t NilKey[SymmetricKey_Length] = {
284 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce,
285 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce
288 class SymmetricKey : public Identifier<SymmetricKey_Length>
292 SymmetricKey(const byte_t* value) : Identifier<SymmetricKey_Length>(value) {}
293 SymmetricKey(const UUID& rhs) : Identifier<SymmetricKey_Length>(rhs) {}
294 virtual ~SymmetricKey() { memcpy(m_Value, NilKey, 16); m_HasValue = false; }
296 const SymmetricKey& operator=(const SymmetricKey& rhs) {
297 if ( m_HasValue = rhs.m_HasValue )
298 memcpy(m_Value, rhs.m_Value, SymmetricKey_Length);
303 void GenRandomValue(SymmetricKey&);
306 // 2004-05-01T13:20:00-00:00
307 const ui32_t DateTimeLen = 25; // the number of chars in the xs:dateTime format (sans milliseconds)
309 // UTC time+date representation
310 class Timestamp : public IArchive
321 Timestamp(const Timestamp& rhs);
322 Timestamp(const char* datestr);
323 virtual ~Timestamp();
325 const Timestamp& operator=(const Timestamp& rhs);
326 bool operator<(const Timestamp& rhs) const;
327 bool operator==(const Timestamp& rhs) const;
328 bool operator!=(const Timestamp& rhs) const;
330 // Write the timestamp value to the given buffer in the form 2004-05-01T13:20:00-00:00
331 // returns 0 if the buffer is smaller than DateTimeLen
332 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
334 // decode and set value from string formatted by EncodeString
335 bool DecodeString(const char* datestr);
337 // add the given number of days or hours to the timestamp value. Values less than zero
338 // will cause the value to decrease
340 void AddHours(i32_t);
342 // Read and write the timestamp value as a byte string
343 virtual bool HasValue() const;
344 virtual bool Archive(MemIOWriter* Writer) const;
345 virtual bool Unarchive(MemIOReader* Reader);
351 KM_NO_COPY_CONSTRUCT(ByteString);
354 byte_t* m_Data; // pointer to memory area containing frame data
355 ui32_t m_Capacity; // size of memory area pointed to by m_Data
356 ui32_t m_Length; // length of byte string in memory area pointed to by m_Data
360 ByteString(ui32_t cap);
361 virtual ~ByteString();
363 // Sets the size of the internally allocated buffer.
364 // Resets content Size to zero.
365 Result_t Capacity(ui32_t cap);
367 Result_t Append(const ByteString&);
368 Result_t Append(const byte_t* buf, ui32_t buf_len);
370 // returns the size of the buffer
371 inline ui32_t Capacity() const { return m_Capacity; }
373 // returns a const pointer to the essence data
374 inline const byte_t* RoData() const { return m_Data; }
376 // returns a non-const pointer to the essence data
377 inline byte_t* Data() { return m_Data; }
379 // set the length of the buffer's contents
380 inline ui32_t Length(ui32_t l) { return m_Length = l; }
382 // returns the length of the buffer's contents
383 inline ui32_t Length() const { return m_Length; }
385 // copy the given data into the ByteString, set Length value.
386 // Returns error if the ByteString is too small.
387 Result_t Set(const byte_t* buf, ui32_t buf_len);
393 #endif // _KM_UTIL_H_