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