Fix a type-punning warning.
[asdcplib-cth.git] / src / KM_memio.h
1 /*
2 Copyright (c) 2006-2011, 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_memio.h
28     \version $Id: KM_memio.h,v 1.10 2014/04/14 18:22:27 jhurst Exp $
29     \brief   abstraction for byte-oriented conversion of integers and objects
30   */
31
32 #ifndef _KM_MEMIO_H_
33 #define _KM_MEMIO_H_
34
35 #include <KM_platform.h>
36 #include <string>
37 #include <cstring>
38
39 namespace Kumu
40 {
41   class ByteString;
42
43   //
44   class MemIOWriter
45     {
46       KM_NO_COPY_CONSTRUCT(MemIOWriter);
47       MemIOWriter();
48       
49     protected:
50       byte_t* m_p;
51       ui32_t  m_capacity;
52       ui32_t  m_size;
53
54     public:
55       MemIOWriter(byte_t* p, ui32_t c) : m_p(p), m_capacity(c), m_size(0) {
56         assert(m_p); assert(m_capacity);
57       }
58
59       MemIOWriter(ByteString* Buf);
60       ~MemIOWriter() {}
61
62       inline void    Reset() { m_size = 0; }
63       inline byte_t* Data() { return m_p; }
64       inline const byte_t* RoData() const { return m_p; }
65       inline byte_t* CurrentData() { return m_p + m_size; }
66       inline ui32_t  Length() const { return m_size; }
67       inline ui32_t  Remainder() const { return m_capacity - m_size; }
68
69       inline bool AddOffset(ui32_t offset) {
70         if ( ( m_size + offset ) > m_capacity )
71           return false;
72
73         m_size += offset;
74         return true;
75
76       }
77
78       inline bool WriteRaw(const byte_t* p, ui32_t buf_len) {
79         if ( ( m_size + buf_len ) > m_capacity )
80           return false;
81
82         memcpy(m_p + m_size, p, buf_len);
83         m_size += buf_len;
84         return true;
85       }
86
87       bool WriteBER(ui64_t i, ui32_t ber_len);
88
89       inline bool WriteUi8(ui8_t i) {
90         if ( ( m_size + 1 ) > m_capacity )
91           return false;
92
93         *(m_p + m_size) = i;
94         m_size++;
95         return true;
96       }
97
98       inline bool WriteUi16BE(ui16_t i) {
99         if ( ( m_size + sizeof(ui16_t) ) > m_capacity )
100           return false;
101         
102         i2p<ui16_t>(KM_i16_BE(i), m_p + m_size);
103         m_size += sizeof(ui16_t);
104         return true;
105       }
106
107       inline bool WriteUi32BE(ui32_t i) {
108         if ( ( m_size + sizeof(ui32_t) ) > m_capacity )
109           return false;
110         
111         i2p<ui32_t>(KM_i32_BE(i), m_p + m_size);
112         m_size += sizeof(ui32_t);
113         return true;
114       }
115
116       inline bool WriteUi64BE(ui64_t i) {
117         if ( ( m_size + sizeof(ui64_t) ) > m_capacity )
118           return false;
119         
120         i2p<ui64_t>(KM_i64_BE(i), m_p + m_size);
121         m_size += sizeof(ui64_t);
122         return true;
123       }
124
125       inline bool WriteString(const std::string& str) {
126         ui32_t len = static_cast<ui32_t>(str.length());
127         if ( ! WriteUi32BE(len) ) return false;
128         if ( ! WriteRaw((const byte_t*)str.c_str(), len) ) return false;
129         return true;
130       }
131    };
132
133   //
134   class MemIOReader
135     {
136       KM_NO_COPY_CONSTRUCT(MemIOReader);
137       MemIOReader();
138       
139     protected:
140       const byte_t* m_p;
141       ui32_t  m_capacity;
142       ui32_t  m_size; // this is sort of a misnomer, when we are reading it measures offset
143
144     public:
145       MemIOReader(const byte_t* p, ui32_t c) :
146         m_p(p), m_capacity(c), m_size(0) {
147         assert(m_p); assert(m_capacity);
148       }
149
150       MemIOReader(const ByteString* Buf);
151       ~MemIOReader() {}
152
153       inline void          Reset() { m_size = 0; }
154       inline const byte_t* Data() const { return m_p; }
155       inline const byte_t* CurrentData() const { return m_p + m_size; }
156       inline ui32_t        Offset() const { return m_size; }
157       inline ui32_t        Remainder() const { return m_capacity - m_size; }
158
159       inline bool SkipOffset(ui32_t offset) {
160         if ( ( m_size + offset ) > m_capacity )
161           return false;
162
163         m_size += offset;
164         return true;
165       }
166
167       inline bool ReadRaw(byte_t* p, ui32_t buf_len) {
168         if ( ( m_size + buf_len ) > m_capacity )
169           return false;
170
171         memcpy(p, m_p + m_size, buf_len);
172         m_size += buf_len;
173         return true;
174       }
175
176       bool ReadBER(ui64_t* i, ui32_t* ber_len);
177
178       inline bool ReadUi8(ui8_t* i) {
179         assert(i);
180         if ( ( m_size + 1 ) > m_capacity )
181           return false;
182
183         *i = *(m_p + m_size);
184         m_size++;
185         return true;
186       }
187
188       inline bool ReadUi16BE(ui16_t* i) {
189         assert(i);
190         if ( ( m_size + sizeof(ui16_t) ) > m_capacity )
191           return false;
192
193         *i = KM_i16_BE(cp2i<ui16_t>(m_p + m_size));
194         m_size += sizeof(ui16_t);
195         return true;
196       }
197
198       inline bool ReadUi32BE(ui32_t* i) {
199         assert(i);
200         if ( ( m_size + sizeof(ui32_t) ) > m_capacity )
201           return false;
202
203         *i = KM_i32_BE(cp2i<ui32_t>(m_p + m_size));
204         m_size += sizeof(ui32_t);
205         return true;
206       }
207
208       inline bool ReadUi64BE(ui64_t* i) {
209         assert(i);
210         if ( ( m_size + sizeof(ui64_t) ) > m_capacity )
211           return false;
212
213         *i = KM_i64_BE(cp2i<ui64_t>(m_p + m_size));
214         m_size += sizeof(ui64_t);
215         return true;
216       }
217
218       inline bool ReadString(std::string& str)
219       {
220         ui32_t str_length = 0;
221         if ( ! ReadUi32BE(&str_length) ) return false;
222
223         if ( str_length > 0 )
224           {
225             if ( ( m_size + str_length ) > m_capacity ) return false;
226             str.assign((const char*)CurrentData(), str_length);
227             if ( ! SkipOffset(str_length) ) return false;
228           }
229
230         return true;
231       }
232     };
233
234   //
235   inline bool
236   UnarchiveString(MemIOReader& Reader, std::string& str) {
237     return Reader.ReadString(str);
238   }
239
240   //
241   inline bool
242   ArchiveString(MemIOWriter& Writer, const std::string& str)
243   {
244     return Writer.WriteString(str);
245   }
246
247
248 } // namespace Kumu
249
250 #endif // _KM_MEMIO_H_
251
252 //
253 // end KM_memio.h
254 //