xref: /haiku/src/add-ons/kernel/file_systems/nfs4/XDR.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
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 
20 Stream::Stream(void* buffer, uint32 size)
21 	:
22 	fBuffer(reinterpret_cast<uint32*>(buffer)),
23 	fSize(size),
24 	fPosition(0)
25 {
26 }
27 
28 
29 Stream::~Stream()
30 {
31 }
32 
33 
34 uint32
35 Stream::_PositionToSize() const
36 {
37 	return fPosition * sizeof(uint32);
38 }
39 
40 
41 uint32
42 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 
51 ReadStream::ReadStream(void* buffer, uint32 size)
52 	:
53 	Stream(buffer, size),
54 	fEOF(false)
55 {
56 }
57 
58 
59 ReadStream::~ReadStream()
60 {
61 }
62 
63 
64 int32
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
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
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
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*
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*
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 
169 WriteStream::WriteStream()
170 	:
171 	Stream(malloc(kInitialSize), kInitialSize),
172 	fError(B_OK)
173 {
174 }
175 
176 
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 
187 WriteStream::~WriteStream()
188 {
189 	free(fBuffer);
190 }
191 
192 
193 void
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
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
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
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
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
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
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
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
297 WriteStream::AddOpaque(const WriteStream& stream)
298 {
299 	return AddOpaque(stream.Buffer(), stream.Size());
300 }
301 
302 
303 status_t
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
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