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 18using namespace XDR; 19 20Stream::Stream(void* buffer, uint32 size) 21 : 22 fBuffer(reinterpret_cast<uint32*>(buffer)), 23 fSize(size), 24 fPosition(0) 25{ 26} 27 28 29Stream::~Stream() 30{ 31} 32 33 34uint32 35Stream::_PositionToSize() const 36{ 37 return fPosition * sizeof(uint32); 38} 39 40 41uint32 42Stream::_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 51ReadStream::ReadStream(void* buffer, uint32 size) 52 : 53 Stream(buffer, size), 54 fEOF(false) 55{ 56} 57 58 59ReadStream::~ReadStream() 60{ 61} 62 63 64int32 65ReadStream::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 76uint32 77ReadStream::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 88int64 89ReadStream::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 103uint64 104ReadStream::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 118char* 119ReadStream::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 142const void* 143ReadStream::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 169WriteStream::WriteStream() 170 : 171 Stream(malloc(kInitialSize), kInitialSize), 172 fError(B_OK) 173{ 174} 175 176 177WriteStream::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 187WriteStream::~WriteStream() 188{ 189 free(fBuffer); 190} 191 192 193void 194WriteStream::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 204status_t 205WriteStream::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 217status_t 218WriteStream::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 229status_t 230WriteStream::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 241status_t 242WriteStream::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 255status_t 256WriteStream::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 269status_t 270WriteStream::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 279status_t 280WriteStream::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 296status_t 297WriteStream::AddOpaque(const WriteStream& stream) 298{ 299 return AddOpaque(stream.Buffer(), stream.Size()); 300} 301 302 303status_t 304WriteStream::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 318status_t 319WriteStream::_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