fixed Identifier copy constructor -- wasn't playing well with std::map
[asdcplib.git] / src / KM_util.h
1 /*
2 Copyright (c) 2005-2006, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27   /*! \file    KM_util.h
28     \version $Id$
29     \brief   Utility functions
30   */
31
32 #ifndef _KM_UTIL_H_
33 #define _KM_UTIL_H_
34
35 #include <KM_memio.h>
36 #include <KM_error.h>
37 #include <string.h>
38 #include <string>
39
40 namespace Kumu
41 {
42
43   template <class T, int SIZE = 16>
44     class IntPrinter : public std::string
45   {
46     protected:
47     IntPrinter();
48     char m_strbuf[SIZE];
49     
50     public:
51     inline const char* c_str() { return m_strbuf; }
52     
53     IntPrinter(const char* format, T value) {
54       snprintf(m_strbuf, SIZE, format, value);
55     }
56   };
57
58   struct i8Printer : public IntPrinter<i8_t> {
59     i8Printer(i8_t value) : IntPrinter<i8_t>("%hd", value) {}
60   };
61
62   struct ui8Printer : public IntPrinter<ui8_t> {
63     ui8Printer(ui8_t value) : IntPrinter<ui8_t>("%hu", value) {}
64   };
65
66   struct i16Printer : public IntPrinter<i16_t> {
67     i16Printer(i16_t value) : IntPrinter<i16_t>("%hd", value) {}
68   };
69
70   struct ui16Printer : public IntPrinter<ui16_t> {
71     ui16Printer(ui16_t value) : IntPrinter<ui16_t>("%hu", value) {}
72   };
73
74   struct i32Printer : public IntPrinter<i32_t> {
75     i32Printer(i32_t value) : IntPrinter<i32_t>("%d", value) {}
76   };
77
78   struct ui32Printer : public IntPrinter<ui32_t> {
79     ui32Printer(ui32_t value) : IntPrinter<ui32_t>("%u", value) {}
80   };
81
82 #ifdef KM_WIN32
83   struct i64Printer : public IntPrinter<i64_t, 32> {
84     i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%I64d", value) {}
85   };
86
87   struct ui64Printer : public IntPrinter<ui64_t, 32> {
88     ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%I64u", value) {}
89   };
90 #else
91   struct i64Printer : public IntPrinter<i64_t, 32> {
92     i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%qd", value) {}
93   };
94
95   struct ui64Printer : public IntPrinter<ui64_t, 32> {
96     ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%qu", value) {}
97   };
98 #endif
99
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);
107
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
111   // return 0.
112   //
113   const char* bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
114
115   const char* bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
116
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);
120
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 )
124       length++;
125
126     return ( length / 3 ) * 4;
127   }
128
129   // print buffer contents to a stream as hexadecimal values in numbered
130   // rows of 16-bytes each.
131   //
132   void hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream = 0);
133
134   // Return the length in bytes of a BER encoded value
135   inline ui32_t BER_length(const byte_t* buf)
136     {
137       if ( buf == 0 || (*buf & 0xf0) != 0x80 )
138         return 0;
139
140       return (*buf & 0x0f) + 1;
141     }
142
143   // read a BER value
144   bool read_BER(const byte_t* buf, ui64_t* val);
145
146   // decode a ber value and compare it to a test value
147   bool read_test_BER(byte_t **buf, ui64_t test_value);
148
149   // create BER encoding of integer value
150   bool write_BER(byte_t* buf, ui64_t val, ui32_t ber_len = 0);
151
152   //----------------------------------------------------------------
153   //
154
155   class IArchive
156     {
157     public:
158       virtual ~IArchive(){}
159       virtual bool HasValue() const = 0;
160       virtual bool Archive(MemIOWriter* Writer) const = 0;
161       virtual bool Unarchive(MemIOReader* Reader) = 0;
162     };
163
164
165   //
166   // the base of all identifier classes
167   template <ui32_t SIZE>
168     class Identifier : public IArchive
169     {
170       const Identifier& operator=(const Identifier& rhs);
171
172     protected:
173       bool   m_HasValue;
174       byte_t m_Value[SIZE];
175
176     public:
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         m_HasValue = rhs.m_HasValue;
181         memcpy(m_Value, rhs.m_Value, SIZE);
182       }
183
184       virtual ~Identifier() {}
185
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; }
189
190       inline bool operator<(const Identifier& rhs) const
191         {
192           ui32_t test_size = xmin(rhs.Size(), SIZE);
193           for ( ui32_t i = 0; i < test_size; i++ )
194             {
195               if ( m_Value[i] != rhs.m_Value[i] )
196                 return m_Value[i] < rhs.m_Value[i];
197             }
198
199           return false;
200         }
201
202       inline bool operator==(const Identifier& rhs) const
203         {
204           if ( rhs.Size() != SIZE ) return false;
205           return ( memcmp(m_Value, rhs.m_Value, SIZE) == 0 );
206         }
207
208       inline bool operator!=(const Identifier& rhs) const
209         {
210           if ( rhs.Size() != SIZE ) return true;
211           return ( memcmp(m_Value, rhs.m_Value, SIZE) != 0 );
212         }
213
214       inline bool DecodeHex(const char* str)
215         {
216           ui32_t char_count;
217           m_HasValue = ( hex2bin(str, m_Value, SIZE, &char_count) == 0 );
218           return m_HasValue;
219         }
220
221       inline const char* EncodeHex(char* buf, ui32_t buf_len) const
222         {
223           return bin2hex(m_Value, SIZE, buf, buf_len);
224         }
225
226       inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
227         return EncodeHex(str_buf, buf_len);
228       }
229
230       inline bool DecodeBase64(const char* str)
231         {
232           ui32_t char_count;
233           m_HasValue = ( base64decode(str, m_Value, SIZE, &char_count) == 0 );
234           return m_HasValue;
235         }
236
237       inline const char* EncodeBase64(char* buf, ui32_t buf_len) const
238         {
239           return base64encode(m_Value, SIZE, buf, buf_len);
240         }
241
242       inline bool HasValue() const { return m_HasValue; }
243
244       inline bool Unarchive(Kumu::MemIOReader* Reader) {
245         m_HasValue = Reader->ReadRaw(m_Value, SIZE);
246         return m_HasValue;
247       }
248
249       inline bool Archive(Kumu::MemIOWriter* Writer) const {
250         return Writer->WriteRaw(m_Value, SIZE);
251       }
252     };
253
254   
255   // UUID
256   //
257   const ui32_t UUID_Length = 16;
258   class UUID : public Identifier<UUID_Length>
259     {
260     public:
261       UUID() {}
262       UUID(const byte_t* value) : Identifier<UUID_Length>(value) {}
263       UUID(const UUID& rhs) : Identifier<UUID_Length>(rhs) {}
264       virtual ~UUID() {}
265       
266       const UUID& operator=(const UUID& rhs) {
267         if ( m_HasValue = rhs.m_HasValue )
268           memcpy(m_Value, rhs.m_Value, UUID_Length);
269         return *this;
270       }
271
272       inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
273         return bin2UUIDhex(m_Value, Size(), buf, buf_len);
274       }
275     };
276   
277   void GenRandomUUID(byte_t* buf);
278   void GenRandomValue(UUID&);
279   
280   // a self-wiping key container
281   //
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
286   };
287
288   class SymmetricKey : public Identifier<SymmetricKey_Length>
289     {
290     public:
291       SymmetricKey() {}
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; }
295
296       const SymmetricKey& operator=(const SymmetricKey& rhs) {
297         if ( m_HasValue = rhs.m_HasValue )
298           memcpy(m_Value, rhs.m_Value, SymmetricKey_Length);
299         return *this;
300       }
301     };
302
303   void GenRandomValue(SymmetricKey&);
304
305   //
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)
308
309   // UTC time+date representation
310   class Timestamp : public IArchive
311     {
312     public:
313       ui16_t Year;
314       ui8_t  Month;
315       ui8_t  Day;
316       ui8_t  Hour;
317       ui8_t  Minute;
318       ui8_t  Second;
319
320       Timestamp();
321       Timestamp(const Timestamp& rhs);
322       Timestamp(const char* datestr);
323       virtual ~Timestamp();
324
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;
329
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;
333
334       // decode and set value from string formatted by EncodeString
335       bool        DecodeString(const char* datestr);
336
337       // add the given number of days or hours to the timestamp value. Values less than zero
338       // will cause the value to decrease
339       void AddDays(i32_t);
340       void AddHours(i32_t);
341
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);
346     };
347
348   //
349   class ByteString
350     {
351       KM_NO_COPY_CONSTRUCT(ByteString);
352         
353     protected:
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
357         
358     public:
359       ByteString();
360       ByteString(ui32_t cap);
361       virtual ~ByteString();
362
363       // Sets the size of the internally allocated buffer.
364       // Resets content Size to zero.
365       Result_t Capacity(ui32_t cap);
366
367       Result_t Append(const ByteString&);
368       Result_t Append(const byte_t* buf, ui32_t buf_len);
369         
370       // returns the size of the buffer
371       inline ui32_t  Capacity() const { return m_Capacity; }
372
373       // returns a const pointer to the essence data
374       inline const byte_t* RoData() const { return m_Data; }
375         
376       // returns a non-const pointer to the essence data
377       inline byte_t* Data() { return m_Data; }
378         
379       // set the length of the buffer's contents
380       inline ui32_t  Length(ui32_t l) { return m_Length = l; }
381         
382       // returns the length of the buffer's contents
383       inline ui32_t  Length() const { return m_Length; }
384
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);
388     };
389
390 } // namespace Kumu
391
392
393 #endif // _KM_UTIL_H_
394
395 //
396 // end KM_util.h
397 //