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