1/* 2 * Copyright 2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Scott T. Mansfield, thephantom@mac.com 7 * Bruno Albuquerque, bga@bug-br.org.br 8 */ 9 10#include <ByteOrder.h> 11#include <Message.h> 12#include <TypeConstants.h> 13 14#include "DynamicBuffer.h" 15#include "NetBuffer.h" 16 17#include <new> 18#include <string.h> 19 20BNetBuffer::BNetBuffer(size_t size) : 21 BArchivable(), 22 fInit(B_NO_INIT) 23{ 24 fImpl = new (std::nothrow) DynamicBuffer(size); 25 if (fImpl != NULL) 26 fInit = fImpl->InitCheck(); 27} 28 29 30BNetBuffer::~BNetBuffer() 31{ 32 delete fImpl; 33} 34 35 36BNetBuffer::BNetBuffer(const BNetBuffer& buffer) : 37 BArchivable(), 38 fInit(B_NO_INIT) 39{ 40 fImpl = new (std::nothrow) DynamicBuffer(*buffer.GetImpl()); 41 if (fImpl != NULL) 42 fInit = fImpl->InitCheck(); 43} 44 45 46BNetBuffer::BNetBuffer(BMessage* archive) : 47 BArchivable(), 48 fInit(B_NO_INIT) 49{ 50 const unsigned char* bufferPtr; 51 ssize_t bufferSize; 52 53 if (archive->FindData("buffer", B_RAW_TYPE, (const void**)&bufferPtr, 54 &bufferSize) == B_OK) { 55 fImpl = new (std::nothrow) DynamicBuffer(bufferSize); 56 if (fImpl != NULL) { 57 status_t result = fImpl->Insert(bufferPtr, bufferSize); 58 if (result == B_OK) 59 fInit = fImpl->InitCheck(); 60 else 61 fInit = result; 62 } 63 } 64} 65 66BNetBuffer& 67BNetBuffer::operator=(const BNetBuffer& buffer) 68{ 69 delete fImpl; 70 71 fImpl = new (std::nothrow) DynamicBuffer(*buffer.GetImpl()); 72 if (fImpl != NULL) 73 fInit = fImpl->InitCheck(); 74 75 return *this; 76} 77 78 79status_t 80BNetBuffer::Archive(BMessage* into, bool deep) const 81{ 82 if (fInit != B_OK) 83 return B_NO_INIT; 84 85 status_t result = into->AddData("buffer", B_RAW_TYPE, fImpl->Data(), 86 fImpl->BytesRemaining()); 87 88 return result; 89} 90 91 92BArchivable* 93BNetBuffer::Instantiate(BMessage* archive) 94{ 95 if (!validate_instantiation(archive, "BNetBuffer")) { 96 return NULL; 97 } 98 99 BNetBuffer* buffer = new (std::nothrow) BNetBuffer(archive); 100 if (buffer == NULL) 101 return NULL; 102 103 if (buffer->InitCheck() != B_OK) { 104 delete buffer; 105 return NULL; 106 } 107 108 return buffer; 109} 110 111 112status_t 113BNetBuffer::InitCheck() 114{ 115 return fInit; 116} 117 118 119status_t 120BNetBuffer::AppendInt8(int8 data) 121{ 122 return AppendData((const void*)&data, sizeof(int8)); 123} 124 125 126status_t 127BNetBuffer::AppendUint8(uint8 data) 128{ 129 return AppendData((const void*)&data, sizeof(int8)); 130} 131 132 133status_t 134BNetBuffer::AppendInt16(int16 data) 135{ 136 int16 be_data = B_HOST_TO_BENDIAN_INT16(data); 137 return AppendData((const void*)&be_data, sizeof(int16)); 138} 139 140 141status_t 142BNetBuffer::AppendUint16(uint16 data) 143{ 144 uint16 be_data = B_HOST_TO_BENDIAN_INT16(data); 145 return AppendData((const void*)&be_data, sizeof(uint16)); 146} 147 148 149status_t 150BNetBuffer::AppendInt32(int32 data) 151{ 152 int32 be_data = B_HOST_TO_BENDIAN_INT32(data); 153 return AppendData((const void*)&be_data, sizeof(int32)); 154} 155 156 157status_t 158BNetBuffer::AppendUint32(uint32 data) 159{ 160 uint32 be_data = B_HOST_TO_BENDIAN_INT32(data); 161 return AppendData((const void*)&be_data, sizeof(uint32)); 162} 163 164 165status_t 166BNetBuffer::AppendFloat(float data) 167{ 168 return AppendData((const void*)&data, sizeof(float)); 169} 170 171 172status_t 173BNetBuffer::AppendDouble(double data) 174{ 175 return AppendData((const void*)&data, sizeof(double)); 176} 177 178 179status_t 180BNetBuffer::AppendString(const char* data) 181{ 182 return AppendData((const void*)data, strlen(data) + 1); 183} 184 185 186status_t 187BNetBuffer::AppendData(const void* data, size_t size) 188{ 189 return fImpl->Insert(data, size); 190} 191 192 193#define STACK_BUFFER_SIZE 2048 194 195status_t 196BNetBuffer::AppendMessage(const BMessage& data) 197{ 198 char stackFlattenedData[STACK_BUFFER_SIZE]; 199 200 size_t dataSize = data.FlattenedSize(); 201 if (dataSize == 0) 202 return B_ERROR; 203 204 status_t result = B_OK; 205 206 if (dataSize > STACK_BUFFER_SIZE) { 207 char* flattenedData = new (std::nothrow) char[dataSize]; 208 if (flattenedData == NULL) 209 return B_NO_MEMORY; 210 211 if (data.Flatten(flattenedData, dataSize) == B_OK) 212 result = AppendData((const void*)&flattenedData, dataSize); 213 214 delete[] flattenedData; 215 } else { 216 if (data.Flatten(stackFlattenedData, dataSize) == B_OK) 217 result = AppendData((const void*)&stackFlattenedData, dataSize); 218 } 219 220 return result; 221} 222 223 224status_t 225BNetBuffer::AppendInt64(int64 data) 226{ 227 int64 be_data = B_HOST_TO_BENDIAN_INT64(data); 228 return AppendData((const void*)&be_data, sizeof(int64)); 229} 230 231 232status_t 233BNetBuffer::AppendUint64(uint64 data) 234{ 235 uint64 be_data = B_HOST_TO_BENDIAN_INT64(data); 236 return AppendData((const void*)&be_data, sizeof(uint64)); 237} 238 239 240status_t 241BNetBuffer::RemoveInt8(int8& data) 242{ 243 return RemoveData((void*)&data, sizeof(int8)); 244} 245 246 247status_t 248BNetBuffer::RemoveUint8(uint8& data) 249{ 250 return RemoveData((void*)&data, sizeof(uint8)); 251} 252 253 254status_t 255BNetBuffer::RemoveInt16(int16& data) 256{ 257 int16 be_data; 258 status_t result = RemoveData((void*)&be_data, sizeof(int16)); 259 if (result != B_OK) 260 return result; 261 262 data = B_BENDIAN_TO_HOST_INT16(be_data); 263 264 return B_OK; 265} 266 267 268status_t 269BNetBuffer::RemoveUint16(uint16& data) 270{ 271 uint16 be_data; 272 status_t result = RemoveData((void*)&be_data, sizeof(uint16)); 273 if (result != B_OK) 274 return result; 275 276 data = B_BENDIAN_TO_HOST_INT16(be_data); 277 278 return B_OK; 279} 280 281 282status_t 283BNetBuffer::RemoveInt32(int32& data) 284{ 285 int32 be_data; 286 status_t result = RemoveData((void*)&be_data, sizeof(int32)); 287 if (result != B_OK) 288 return result; 289 290 data = B_BENDIAN_TO_HOST_INT32(be_data); 291 292 return B_OK; 293} 294 295 296status_t 297BNetBuffer::RemoveUint32(uint32& data) 298{ 299 uint32 be_data; 300 status_t result = RemoveData((void*)&be_data, sizeof(uint32)); 301 if (result != B_OK) 302 return result; 303 304 data = B_BENDIAN_TO_HOST_INT32(be_data); 305 306 return B_OK; 307} 308 309 310status_t 311BNetBuffer::RemoveFloat(float& data) 312{ 313 return RemoveData((void*)&data, sizeof(float)); 314} 315 316 317status_t 318BNetBuffer::RemoveDouble(double& data) 319{ 320 return RemoveData((void*)&data, sizeof(double)); 321} 322 323 324status_t 325BNetBuffer::RemoveString(char* data, size_t size) 326{ 327 // TODO(bga): Should we do anything specific to handle the terminating 328 // NULL byte? 329 return RemoveData((void*)data, size); 330} 331 332 333status_t 334BNetBuffer::RemoveData(void* data, size_t size) 335{ 336 return fImpl->Remove(data, size); 337} 338 339 340status_t 341BNetBuffer::RemoveMessage(BMessage& data) 342{ 343 unsigned char* bufferPtr = fImpl->Data(); 344 345 if (*(int32*)bufferPtr != B_MESSAGE_TYPE) 346 return B_ERROR; 347 348 349 bufferPtr += sizeof(int32); 350 int32 dataSize = *(int32*)bufferPtr; 351 352 char* flattenedData = new (std::nothrow) char[dataSize]; 353 if (flattenedData == NULL) 354 return B_NO_MEMORY; 355 356 status_t result = RemoveData(flattenedData, dataSize); 357 if (result == B_OK) 358 result = data.Unflatten(flattenedData); 359 360 delete[] flattenedData; 361 362 return result; 363} 364 365 366status_t 367BNetBuffer::RemoveInt64(int64& data) 368{ 369 int64 be_data; 370 status_t result = RemoveData((void*)&be_data, sizeof(int64)); 371 if (result != B_OK) 372 return result; 373 374 data = B_BENDIAN_TO_HOST_INT64(be_data); 375 376 return B_OK; 377} 378 379 380status_t 381BNetBuffer::RemoveUint64(uint64& data) 382{ 383 uint64 be_data; 384 status_t result = RemoveData((void*)&be_data, sizeof(uint64)); 385 if (result != B_OK) 386 return result; 387 388 data = B_BENDIAN_TO_HOST_INT64(be_data); 389 390 return B_OK; 391} 392 393 394unsigned char* 395BNetBuffer::Data() const 396{ 397 return fImpl->Data(); 398} 399 400 401size_t 402BNetBuffer::Size() const 403{ 404 return fImpl->Size(); 405} 406 407 408size_t 409BNetBuffer::BytesRemaining() const 410{ 411 return fImpl->BytesRemaining(); 412} 413 414 415void 416BNetBuffer::_ReservedBNetBufferFBCCruft1() 417{ 418} 419 420 421void 422BNetBuffer::_ReservedBNetBufferFBCCruft2() 423{ 424} 425 426 427void 428BNetBuffer::_ReservedBNetBufferFBCCruft3() 429{ 430} 431 432 433void 434BNetBuffer::_ReservedBNetBufferFBCCruft4() 435{ 436} 437 438 439void 440BNetBuffer::_ReservedBNetBufferFBCCruft5() 441{ 442} 443 444 445void 446BNetBuffer::_ReservedBNetBufferFBCCruft6() 447{ 448} 449