1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <Variant.h> 9 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include <ByteOrder.h> 14 #include <Message.h> 15 16 17 template<typename NumberType> 18 inline NumberType 19 BVariant::_ToNumber() const 20 { 21 switch (fType) { 22 case B_BOOL_TYPE: 23 return fBool ? 1 : 0; 24 case B_INT8_TYPE: 25 return (NumberType)fInt8; 26 case B_UINT8_TYPE: 27 return (NumberType)fUInt8; 28 case B_INT16_TYPE: 29 return (NumberType)fInt16; 30 case B_UINT16_TYPE: 31 return (NumberType)fUInt16; 32 case B_INT32_TYPE: 33 return (NumberType)fInt32; 34 case B_UINT32_TYPE: 35 return (NumberType)fUInt32; 36 case B_INT64_TYPE: 37 return (NumberType)fInt64; 38 case B_UINT64_TYPE: 39 return (NumberType)fUInt64; 40 case B_FLOAT_TYPE: 41 return (NumberType)fFloat; 42 case B_DOUBLE_TYPE: 43 return (NumberType)fDouble; 44 default: 45 return 0; 46 } 47 } 48 49 50 BVariant::~BVariant() 51 { 52 Unset(); 53 } 54 55 56 status_t 57 BVariant::SetToTypedData(const void* data, type_code type) 58 { 59 Unset(); 60 61 switch (type) { 62 case B_BOOL_TYPE: 63 fBool = *(bool*)data; 64 break; 65 case B_INT8_TYPE: 66 fInt8 = *(int8*)data; 67 break; 68 case B_UINT8_TYPE: 69 fUInt8 = *(uint8*)data; 70 break; 71 case B_INT16_TYPE: 72 fInt16 = *(int16*)data; 73 break; 74 case B_UINT16_TYPE: 75 fUInt16 = *(uint16*)data; 76 break; 77 case B_INT32_TYPE: 78 fInt32 = *(int32*)data; 79 break; 80 case B_UINT32_TYPE: 81 fUInt32 = *(uint32*)data; 82 break; 83 case B_INT64_TYPE: 84 fInt64 = *(int64*)data; 85 break; 86 case B_UINT64_TYPE: 87 fUInt64 = *(uint64*)data; 88 break; 89 case B_FLOAT_TYPE: 90 fFloat = *(float*)data; 91 break; 92 case B_DOUBLE_TYPE: 93 fDouble = *(double*)data; 94 break; 95 case B_POINTER_TYPE: 96 fPointer = *(void**)data; 97 break; 98 case B_STRING_TYPE: 99 return _SetTo((const char*)data, 0) ? B_OK : B_NO_MEMORY; 100 case B_RECT_TYPE: 101 { 102 BRect *rect = (BRect *)data; 103 _SetTo(rect->left, rect->top, rect->right, rect->bottom); 104 break; 105 } 106 default: 107 return B_BAD_TYPE; 108 } 109 110 fType = type; 111 return B_OK; 112 } 113 114 115 void 116 BVariant::Unset() 117 { 118 if ((fFlags & B_VARIANT_OWNS_DATA) != 0) { 119 switch (fType) { 120 case B_STRING_TYPE: 121 free(fString); 122 break; 123 default: 124 break; 125 } 126 } else if ((fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0) { 127 if (fReferenceable != NULL) 128 fReferenceable->ReleaseReference(); 129 } 130 131 fType = 0; 132 fFlags = 0; 133 } 134 135 136 bool 137 BVariant::operator==(const BVariant& other) const 138 { 139 if (fType == 0) 140 return other.fType == 0; 141 if (other.fType == 0) 142 return false; 143 144 // TODO: The number comparisons are not really accurate. Particularly a 145 // conversion between signed and unsigned integers might actually change the 146 // value. 147 148 switch (fType) { 149 case B_BOOL_TYPE: 150 return fBool == other.ToBool(); 151 case B_INT8_TYPE: 152 case B_INT16_TYPE: 153 case B_INT32_TYPE: 154 case B_INT64_TYPE: 155 if (!other.IsNumber()) 156 return false; 157 return ToInt64() == other.ToInt64(); 158 case B_UINT8_TYPE: 159 case B_UINT16_TYPE: 160 case B_UINT32_TYPE: 161 case B_UINT64_TYPE: 162 if (!other.IsNumber()) 163 return false; 164 return ToUInt64() == other.ToUInt64(); 165 case B_FLOAT_TYPE: 166 case B_DOUBLE_TYPE: 167 if (!other.IsNumber()) 168 return false; 169 return ToDouble() == other.ToDouble(); 170 case B_POINTER_TYPE: 171 return other.fType == B_POINTER_TYPE 172 && fPointer == other.fPointer; 173 case B_STRING_TYPE: 174 if (other.fType != B_STRING_TYPE) 175 return false; 176 if (fString == NULL || other.fString == NULL) 177 return fString == other.fString; 178 return strcmp(fString, other.fString) == 0; 179 case B_RECT_TYPE: 180 return BRect(fRect.left, fRect.top, fRect.right, fRect.bottom) 181 == BRect(other.fRect.left, other.fRect.top, other.fRect.right, 182 other.fRect.bottom); 183 default: 184 return false; 185 } 186 } 187 188 189 size_t 190 BVariant::Size() const 191 { 192 if (fType == B_STRING_TYPE) 193 return fString != NULL ? strlen(fString) + 1 : 0; 194 if ((fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0) 195 return sizeof(this->fReferenceable); 196 return SizeOfType(fType); 197 } 198 199 200 const uint8* 201 BVariant::Bytes() const 202 { 203 if (fType == B_STRING_TYPE) 204 return (const uint8*)fString; 205 return fBytes; 206 } 207 208 209 bool 210 BVariant::ToBool() const 211 { 212 switch (fType) { 213 case B_BOOL_TYPE: 214 return fBool; 215 case B_INT8_TYPE: 216 return fInt8 != 0; 217 case B_UINT8_TYPE: 218 return fUInt8 != 0; 219 case B_INT16_TYPE: 220 return fInt16 != 0; 221 case B_UINT16_TYPE: 222 return fUInt16 != 0; 223 case B_INT32_TYPE: 224 return fInt32 != 0; 225 case B_UINT32_TYPE: 226 return fUInt32 != 0; 227 case B_INT64_TYPE: 228 return fInt64 != 0; 229 case B_UINT64_TYPE: 230 return fUInt64 != 0; 231 case B_FLOAT_TYPE: 232 return fFloat != 0; 233 case B_DOUBLE_TYPE: 234 return fDouble != 0; 235 case B_POINTER_TYPE: 236 return fPointer != NULL; 237 case B_STRING_TYPE: 238 return fString != NULL; 239 // TODO: We should probably check for actual values like "true", 240 // "false", "on", "off", etc. 241 default: 242 return false; 243 } 244 } 245 246 247 int8 248 BVariant::ToInt8() const 249 { 250 return _ToNumber<int8>(); 251 } 252 253 254 uint8 255 BVariant::ToUInt8() const 256 { 257 return _ToNumber<uint8>(); 258 } 259 260 261 int16 262 BVariant::ToInt16() const 263 { 264 return _ToNumber<int16>(); 265 } 266 267 268 uint16 269 BVariant::ToUInt16() const 270 { 271 return _ToNumber<uint16>(); 272 } 273 274 275 int32 276 BVariant::ToInt32() const 277 { 278 return _ToNumber<int32>(); 279 } 280 281 282 uint32 283 BVariant::ToUInt32() const 284 { 285 return _ToNumber<uint32>(); 286 } 287 288 289 int64 290 BVariant::ToInt64() const 291 { 292 return _ToNumber<int64>(); 293 } 294 295 296 uint64 297 BVariant::ToUInt64() const 298 { 299 return _ToNumber<uint64>(); 300 } 301 302 303 float 304 BVariant::ToFloat() const 305 { 306 return _ToNumber<float>(); 307 } 308 309 310 double 311 BVariant::ToDouble() const 312 { 313 return _ToNumber<double>(); 314 } 315 316 317 BRect 318 BVariant::ToRect() const 319 { 320 return BRect(fRect.left, fRect.top, fRect.right, fRect.bottom); 321 } 322 323 324 void* 325 BVariant::ToPointer() const 326 { 327 return fType == B_POINTER_TYPE ? fString : NULL; 328 } 329 330 331 const char* 332 BVariant::ToString() const 333 { 334 return fType == B_STRING_TYPE ? fString : NULL; 335 } 336 337 338 void 339 BVariant::_SetTo(const BVariant& other) 340 { 341 if ((other.fFlags & B_VARIANT_OWNS_DATA) != 0) { 342 switch (other.fType) { 343 case B_STRING_TYPE: 344 fType = B_STRING_TYPE; 345 fString = strdup(other.fString); 346 fFlags = B_VARIANT_OWNS_DATA; 347 return; 348 default: 349 break; 350 } 351 } else if ((other.fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0) { 352 if (other.fReferenceable != NULL) 353 other.fReferenceable->AcquireReference(); 354 } 355 356 memcpy((void*)this, (void*)&other, sizeof(BVariant)); 357 } 358 359 360 BReferenceable* 361 BVariant::ToReferenceable() const 362 { 363 return (fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0 364 ? fReferenceable : NULL; 365 } 366 367 368 void 369 BVariant::SwapEndianess() 370 { 371 if (!IsNumber() || fType == B_POINTER_TYPE) 372 return; 373 374 swap_data(fType, fBytes, Size(), B_SWAP_ALWAYS); 375 } 376 377 378 status_t 379 BVariant::AddToMessage(BMessage& message, const char* fieldName) const 380 { 381 switch (fType) { 382 case B_BOOL_TYPE: 383 return message.AddBool(fieldName, fBool); 384 case B_INT8_TYPE: 385 return message.AddInt8(fieldName, fInt8); 386 case B_UINT8_TYPE: 387 return message.AddUInt8(fieldName, fUInt8); 388 case B_INT16_TYPE: 389 return message.AddInt16(fieldName, fInt16); 390 case B_UINT16_TYPE: 391 return message.AddUInt16(fieldName, fUInt16); 392 case B_INT32_TYPE: 393 return message.AddInt32(fieldName, fInt32); 394 case B_UINT32_TYPE: 395 return message.AddUInt32(fieldName, fUInt32); 396 case B_INT64_TYPE: 397 return message.AddInt64(fieldName, fInt64); 398 case B_UINT64_TYPE: 399 return message.AddUInt64(fieldName, fUInt64); 400 case B_FLOAT_TYPE: 401 return message.AddFloat(fieldName, fFloat); 402 case B_DOUBLE_TYPE: 403 return message.AddDouble(fieldName, fDouble); 404 case B_POINTER_TYPE: 405 return message.AddPointer(fieldName, fPointer); 406 case B_STRING_TYPE: 407 return message.AddString(fieldName, fString); 408 case B_RECT_TYPE: 409 return message.AddRect(fieldName, BRect(fRect.left, fRect.top, 410 fRect.right, fRect.bottom)); 411 default: 412 return B_UNSUPPORTED; 413 } 414 } 415 416 417 status_t 418 BVariant::SetFromMessage(const BMessage& message, const char* fieldName) 419 { 420 // get the message field info 421 type_code type; 422 int32 count; 423 status_t error = message.GetInfo(fieldName, &type, &count); 424 if (error != B_OK) 425 return error; 426 427 // get the data 428 const void* data; 429 ssize_t numBytes; 430 error = message.FindData(fieldName, type, &data, &numBytes); 431 if (error != B_OK) 432 return error; 433 434 // init the object 435 return SetToTypedData(data, type); 436 } 437 438 439 /*static*/ size_t 440 BVariant::SizeOfType(type_code type) 441 { 442 switch (type) { 443 case B_BOOL_TYPE: 444 return 1; 445 case B_INT8_TYPE: 446 return 1; 447 case B_UINT8_TYPE: 448 return 1; 449 case B_INT16_TYPE: 450 return 2; 451 case B_UINT16_TYPE: 452 return 2; 453 case B_INT32_TYPE: 454 return 4; 455 case B_UINT32_TYPE: 456 return 4; 457 case B_INT64_TYPE: 458 return 8; 459 case B_UINT64_TYPE: 460 return 8; 461 case B_FLOAT_TYPE: 462 return sizeof(float); 463 case B_DOUBLE_TYPE: 464 return sizeof(double); 465 case B_POINTER_TYPE: 466 return sizeof(void*); 467 case B_RECT_TYPE: 468 return sizeof(BRect); 469 default: 470 return 0; 471 } 472 } 473 474 475 /*static*/ bool 476 BVariant::TypeIsNumber(type_code type) 477 { 478 switch (type) { 479 case B_INT8_TYPE: 480 case B_UINT8_TYPE: 481 case B_INT16_TYPE: 482 case B_UINT16_TYPE: 483 case B_INT32_TYPE: 484 case B_UINT32_TYPE: 485 case B_INT64_TYPE: 486 case B_UINT64_TYPE: 487 case B_FLOAT_TYPE: 488 case B_DOUBLE_TYPE: 489 return true; 490 default: 491 return false; 492 } 493 } 494 495 496 /*static*/ bool 497 BVariant::TypeIsInteger(type_code type, bool* _isSigned) 498 { 499 switch (type) { 500 case B_INT8_TYPE: 501 case B_INT16_TYPE: 502 case B_INT32_TYPE: 503 case B_INT64_TYPE: 504 if (_isSigned != NULL) 505 *_isSigned = true; 506 return true; 507 case B_UINT8_TYPE: 508 case B_UINT16_TYPE: 509 case B_UINT32_TYPE: 510 case B_UINT64_TYPE: 511 if (_isSigned != NULL) 512 *_isSigned = false; 513 return true; 514 default: 515 return false; 516 } 517 } 518 519 520 /*static*/ bool 521 BVariant::TypeIsFloat(type_code type) 522 { 523 switch (type) { 524 case B_FLOAT_TYPE: 525 case B_DOUBLE_TYPE: 526 return true; 527 default: 528 return false; 529 } 530 } 531 532 533 void 534 BVariant::_SetTo(bool value) 535 { 536 fType = B_BOOL_TYPE; 537 fFlags = 0; 538 fBool = value; 539 } 540 541 542 void 543 BVariant::_SetTo(int8 value) 544 { 545 fType = B_INT8_TYPE; 546 fFlags = 0; 547 fInt8 = value; 548 } 549 550 551 void 552 BVariant::_SetTo(uint8 value) 553 { 554 fType = B_UINT8_TYPE; 555 fFlags = 0; 556 fUInt8 = value; 557 } 558 559 560 void 561 BVariant::_SetTo(int16 value) 562 { 563 fType = B_INT16_TYPE; 564 fFlags = 0; 565 fInt16 = value; 566 } 567 568 569 void 570 BVariant::_SetTo(uint16 value) 571 { 572 fType = B_UINT16_TYPE; 573 fFlags = 0; 574 fUInt16 = value; 575 } 576 577 578 void 579 BVariant::_SetTo(int32 value) 580 { 581 fType = B_INT32_TYPE; 582 fFlags = 0; 583 fInt32 = value; 584 } 585 586 587 void 588 BVariant::_SetTo(uint32 value) 589 { 590 fType = B_UINT32_TYPE; 591 fFlags = 0; 592 fUInt32 = value; 593 } 594 595 596 void 597 BVariant::_SetTo(int64 value) 598 { 599 fType = B_INT64_TYPE; 600 fFlags = 0; 601 fInt64 = value; 602 } 603 604 605 void 606 BVariant::_SetTo(uint64 value) 607 { 608 fType = B_UINT64_TYPE; 609 fFlags = 0; 610 fUInt64 = value; 611 } 612 613 614 void 615 BVariant::_SetTo(float value) 616 { 617 fType = B_FLOAT_TYPE; 618 fFlags = 0; 619 fFloat = value; 620 } 621 622 623 void 624 BVariant::_SetTo(double value) 625 { 626 fType = B_DOUBLE_TYPE; 627 fFlags = 0; 628 fDouble = value; 629 } 630 631 632 void 633 BVariant::_SetTo(float left, float top, float right, float bottom) 634 { 635 fType = B_RECT_TYPE; 636 fFlags = 0; 637 fRect.left = left; 638 fRect.top = top; 639 fRect.right = right; 640 fRect.bottom = bottom; 641 } 642 643 644 void 645 BVariant::_SetTo(const void* value) 646 { 647 fType = B_POINTER_TYPE; 648 fFlags = 0; 649 fPointer = (void*)value; 650 } 651 652 653 bool 654 BVariant::_SetTo(const char* value, uint32 flags) 655 { 656 fType = B_STRING_TYPE; 657 fFlags = 0; 658 659 if (value != NULL) { 660 if ((flags & B_VARIANT_DONT_COPY_DATA) == 0) { 661 fString = strdup(value); 662 fFlags |= B_VARIANT_OWNS_DATA; 663 if (fString == NULL) 664 return false; 665 } else { 666 fString = (char*)value; 667 fFlags |= flags & B_VARIANT_OWNS_DATA; 668 } 669 } else 670 fString = NULL; 671 672 return true; 673 } 674 675 676 void 677 BVariant::_SetTo(BReferenceable* value, type_code type) 678 { 679 fType = type; 680 fFlags = B_VARIANT_REFERENCEABLE_DATA; 681 fReferenceable = value; 682 683 if (fReferenceable != NULL) 684 fReferenceable->AcquireReference(); 685 } 686