1 /*
2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Paweł Dziepak, pdziepak@quarnos.org
7 */
8
9
10 #include "XDR.h"
11
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <ByteOrder.h>
16
17
18 using namespace XDR;
19
Stream(void * buffer,uint32 size)20 Stream::Stream(void* buffer, uint32 size)
21 :
22 fBuffer(reinterpret_cast<uint32*>(buffer)),
23 fSize(size),
24 fPosition(0)
25 {
26 }
27
28
~Stream()29 Stream::~Stream()
30 {
31 }
32
33
34 uint32
_PositionToSize() const35 Stream::_PositionToSize() const
36 {
37 return fPosition * sizeof(uint32);
38 }
39
40
41 uint32
_RealSize(uint32 size) const42 Stream::_RealSize(uint32 size) const
43 {
44 uint32 real_size = size;
45 if (real_size % 4 != 0)
46 real_size = ((real_size >> 2) + 1) << 2;
47 return real_size;
48 }
49
50
ReadStream(void * buffer,uint32 size)51 ReadStream::ReadStream(void* buffer, uint32 size)
52 :
53 Stream(buffer, size),
54 fEOF(false)
55 {
56 }
57
58
~ReadStream()59 ReadStream::~ReadStream()
60 {
61 }
62
63
64 int32
GetInt()65 ReadStream::GetInt()
66 {
67 if (_PositionToSize() >= fSize) {
68 fEOF = true;
69 return 0;
70 }
71
72 return B_BENDIAN_TO_HOST_INT32(fBuffer[fPosition++]);
73 }
74
75
76 uint32
GetUInt()77 ReadStream::GetUInt()
78 {
79 if (_PositionToSize() >= fSize) {
80 fEOF = true;
81 return 0;
82 }
83
84 return B_BENDIAN_TO_HOST_INT32(fBuffer[fPosition++]);
85 }
86
87
88 int64
GetHyper()89 ReadStream::GetHyper()
90 {
91 if (_PositionToSize() + sizeof(int64) > fSize) {
92 fEOF = true;
93 return 0;
94 }
95
96 int64* ptr = reinterpret_cast<int64*>(fBuffer + fPosition);
97 fPosition += 2;
98
99 return B_BENDIAN_TO_HOST_INT64(*ptr);
100 }
101
102
103 uint64
GetUHyper()104 ReadStream::GetUHyper()
105 {
106 if (_PositionToSize() + sizeof(uint64) > fSize) {
107 fEOF = true;
108 return 0;
109 }
110
111 uint64* ptr = reinterpret_cast<uint64*>(fBuffer + fPosition);
112 fPosition += 2;
113
114 return B_BENDIAN_TO_HOST_INT64(*ptr);
115 }
116
117
118 char*
GetString()119 ReadStream::GetString()
120 {
121 if (_PositionToSize() >= fSize) {
122 fEOF = true;
123 return NULL;
124 }
125
126 uint32 size;
127 const void* ptr = GetOpaque(&size);
128 if (ptr == NULL)
129 return NULL;
130
131 char* str = reinterpret_cast<char*>(malloc(size + 1));
132 if (str == NULL)
133 return NULL;
134
135 memcpy(str, ptr, size);
136 str[size] = 0;
137
138 return str;
139 }
140
141
142 const void*
GetOpaque(uint32 * size)143 ReadStream::GetOpaque(uint32* size)
144 {
145 if (_PositionToSize() >= fSize) {
146 fEOF = true;
147 return NULL;
148 }
149
150 void* ptr = NULL;
151 uint32 s = GetUInt();
152 if (s != 0) {
153 ptr = fBuffer + fPosition;
154 if (_PositionToSize() + s <= fSize)
155 fPosition += _RealSize(s) / sizeof(uint32);
156 else {
157 s = fSize - _PositionToSize();
158 fPosition = fSize;
159 }
160 }
161
162 if (size != NULL)
163 *size = s;
164
165 return ptr;
166 }
167
168
WriteStream()169 WriteStream::WriteStream()
170 :
171 Stream(malloc(kInitialSize), kInitialSize),
172 fError(B_OK)
173 {
174 }
175
176
WriteStream(const WriteStream & x)177 WriteStream::WriteStream(const WriteStream& x)
178 :
179 Stream(malloc(x.fSize), x.fSize),
180 fError(x.fError)
181 {
182 fPosition = x.fPosition;
183 memcpy(fBuffer, x.fBuffer, fSize);
184 }
185
186
~WriteStream()187 WriteStream::~WriteStream()
188 {
189 free(fBuffer);
190 }
191
192
193 void
Clear()194 WriteStream::Clear()
195 {
196 free(fBuffer);
197 fSize = kInitialSize;
198 fBuffer = reinterpret_cast<uint32*>(malloc(fSize));
199 fError = B_OK;
200 fPosition = 0;
201 }
202
203
204 status_t
InsertUInt(Stream::Position pos,uint32 x)205 WriteStream::InsertUInt(Stream::Position pos, uint32 x)
206 {
207 if (pos * sizeof(uint32) >= fSize) {
208 fError = B_BAD_VALUE;
209 return B_BAD_VALUE;
210 }
211
212 fBuffer[pos] = B_HOST_TO_BENDIAN_INT32(x);
213 return B_OK;
214 }
215
216
217 status_t
AddInt(int32 x)218 WriteStream::AddInt(int32 x)
219 {
220 status_t err = _CheckResize(sizeof(int32));
221 if (err != B_OK)
222 return err;
223
224 fBuffer[fPosition++] = B_HOST_TO_BENDIAN_INT32(x);
225 return B_OK;
226 }
227
228
229 status_t
AddUInt(uint32 x)230 WriteStream::AddUInt(uint32 x)
231 {
232 status_t err = _CheckResize(sizeof(uint32));
233 if (err != B_OK)
234 return err;
235
236 fBuffer[fPosition++] = B_HOST_TO_BENDIAN_INT32(x);
237 return B_OK;
238 }
239
240
241 status_t
AddHyper(int64 x)242 WriteStream::AddHyper(int64 x)
243 {
244 status_t err = _CheckResize(sizeof(int64));
245 if (err != B_OK)
246 return err;
247
248 int64* ptr = reinterpret_cast<int64*>(fBuffer + fPosition);
249 *ptr = B_HOST_TO_BENDIAN_INT64(x);
250 fPosition += 2;
251 return B_OK;
252 }
253
254
255 status_t
AddUHyper(uint64 x)256 WriteStream::AddUHyper(uint64 x)
257 {
258 status_t err = _CheckResize(sizeof(uint64));
259 if (err != B_OK)
260 return err;
261
262 uint64* ptr = reinterpret_cast<uint64*>(fBuffer + fPosition);
263 *ptr = B_HOST_TO_BENDIAN_INT64(x);
264 fPosition += 2;
265 return B_OK;
266 }
267
268
269 status_t
AddString(const char * str,uint32 maxlen)270 WriteStream::AddString(const char* str, uint32 maxlen)
271 {
272 uint32 len = strlen(str);
273 uint32 size = maxlen == 0 ? len : min_c(maxlen, len);
274
275 return AddOpaque(str, size);
276 }
277
278
279 status_t
AddOpaque(const void * ptr,uint32 size)280 WriteStream::AddOpaque(const void* ptr, uint32 size)
281 {
282 uint32 real_size = _RealSize(size);
283 status_t err = _CheckResize(real_size + sizeof(uint32));
284 if (err != B_OK)
285 return err;
286
287 AddUInt(size);
288 memset(fBuffer + fPosition, 0, real_size);
289 memcpy(fBuffer + fPosition, ptr, size);
290 fPosition += real_size / sizeof(int32);
291
292 return B_OK;
293 }
294
295
296 status_t
AddOpaque(const WriteStream & stream)297 WriteStream::AddOpaque(const WriteStream& stream)
298 {
299 return AddOpaque(stream.Buffer(), stream.Size());
300 }
301
302
303 status_t
Append(const WriteStream & stream)304 WriteStream::Append(const WriteStream& stream)
305 {
306 uint32 size = stream.Size();
307 status_t err = _CheckResize(size);
308 if (err != B_OK)
309 return err;
310
311 memcpy(fBuffer + fPosition, stream.Buffer(), size);
312 fPosition += size / sizeof(int32);
313
314 return B_OK;
315 }
316
317
318 status_t
_CheckResize(uint32 size)319 WriteStream::_CheckResize(uint32 size)
320 {
321 if (_PositionToSize() + size <= fSize)
322 return B_OK;
323
324 uint32 new_size = max_c(fSize * 2, fPosition * sizeof(uint32) + size);
325
326 void* ptr = realloc(fBuffer, new_size);
327 if (ptr == NULL) {
328 fError = B_NO_MEMORY;
329 return B_NO_MEMORY;
330 }
331
332 fBuffer = reinterpret_cast<uint32*>(ptr);
333 fSize = new_size;
334
335 return B_OK;
336 }
337
338