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