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 size_t 129 BVariant::Size() const 130 { 131 if (fType == B_STRING_TYPE) 132 return fString != NULL ? strlen(fString) + 1 : 0; 133 if ((fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0) 134 return sizeof(this->fReferenceable); 135 return SizeOfType(fType); 136 } 137 138 139 const uint8* 140 BVariant::Bytes() const 141 { 142 if (fType == B_STRING_TYPE) 143 return (const uint8*)fString; 144 return fBytes; 145 } 146 147 148 bool 149 BVariant::IsNumber() const 150 { 151 switch (fType) { 152 case B_INT8_TYPE: 153 case B_UINT8_TYPE: 154 case B_INT16_TYPE: 155 case B_UINT16_TYPE: 156 case B_INT32_TYPE: 157 case B_UINT32_TYPE: 158 case B_INT64_TYPE: 159 case B_UINT64_TYPE: 160 case B_FLOAT_TYPE: 161 case B_DOUBLE_TYPE: 162 return true; 163 default: 164 return false; 165 } 166 } 167 168 169 bool 170 BVariant::IsInteger() const 171 { 172 switch (fType) { 173 case B_INT8_TYPE: 174 case B_UINT8_TYPE: 175 case B_INT16_TYPE: 176 case B_UINT16_TYPE: 177 case B_INT32_TYPE: 178 case B_UINT32_TYPE: 179 case B_INT64_TYPE: 180 case B_UINT64_TYPE: 181 return true; 182 default: 183 return false; 184 } 185 } 186 187 188 bool 189 BVariant::IsFloat() const 190 { 191 switch (fType) { 192 case B_FLOAT_TYPE: 193 case B_DOUBLE_TYPE: 194 return true; 195 default: 196 return false; 197 } 198 } 199 200 201 202 bool 203 BVariant::ToBool() const 204 { 205 switch (fType) { 206 case B_BOOL_TYPE: 207 return fBool; 208 case B_INT8_TYPE: 209 return fInt8 != 0; 210 case B_UINT8_TYPE: 211 return fUInt8 != 0; 212 case B_INT16_TYPE: 213 return fInt16 != 0; 214 case B_UINT16_TYPE: 215 return fUInt16 != 0; 216 case B_INT32_TYPE: 217 return fInt32 != 0; 218 case B_UINT32_TYPE: 219 return fUInt32 != 0; 220 case B_INT64_TYPE: 221 return fInt64 != 0; 222 case B_UINT64_TYPE: 223 return fUInt64 != 0; 224 case B_FLOAT_TYPE: 225 return fFloat != 0; 226 case B_DOUBLE_TYPE: 227 return fDouble != 0; 228 case B_POINTER_TYPE: 229 return fPointer != NULL; 230 case B_STRING_TYPE: 231 return fString != NULL; 232 // TODO: We should probably check for actual values like "true", 233 // "false", "on", "off", etc. 234 default: 235 return false; 236 } 237 } 238 239 240 int8 241 BVariant::ToInt8() const 242 { 243 return _ToNumber<int8>(); 244 } 245 246 247 uint8 248 BVariant::ToUInt8() const 249 { 250 return _ToNumber<uint8>(); 251 } 252 253 254 int16 255 BVariant::ToInt16() const 256 { 257 return _ToNumber<int16>(); 258 } 259 260 261 uint16 262 BVariant::ToUInt16() const 263 { 264 return _ToNumber<uint16>(); 265 } 266 267 268 int32 269 BVariant::ToInt32() const 270 { 271 return _ToNumber<int32>(); 272 } 273 274 275 uint32 276 BVariant::ToUInt32() const 277 { 278 return _ToNumber<uint32>(); 279 } 280 281 282 int64 283 BVariant::ToInt64() const 284 { 285 return _ToNumber<int64>(); 286 } 287 288 289 uint64 290 BVariant::ToUInt64() const 291 { 292 return _ToNumber<uint64>(); 293 } 294 295 296 float 297 BVariant::ToFloat() const 298 { 299 return _ToNumber<float>(); 300 } 301 302 303 double 304 BVariant::ToDouble() const 305 { 306 return _ToNumber<double>(); 307 } 308 309 310 void* 311 BVariant::ToPointer() const 312 { 313 return fType == B_POINTER_TYPE ? fString : NULL; 314 } 315 316 317 const char* 318 BVariant::ToString() const 319 { 320 return fType == B_STRING_TYPE ? fString : NULL; 321 } 322 323 324 void 325 BVariant::_SetTo(const BVariant& other) 326 { 327 if ((other.fFlags & B_VARIANT_OWNS_DATA) != 0) { 328 switch (other.fType) { 329 case B_STRING_TYPE: 330 fType = B_STRING_TYPE; 331 fString = strdup(other.fString); 332 fFlags = B_VARIANT_OWNS_DATA; 333 return; 334 default: 335 break; 336 } 337 } else if ((other.fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0) { 338 if (other.fReferenceable != NULL) 339 other.fReferenceable->AcquireReference(); 340 } 341 342 memcpy(this, &other, sizeof(BVariant)); 343 } 344 345 346 BReferenceable* 347 BVariant::ToReferenceable() const 348 { 349 return (fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0 350 ? fReferenceable : NULL; 351 } 352 353 354 void 355 BVariant::SwapEndianess() 356 { 357 if (!IsNumber() || fType == B_POINTER_TYPE) 358 return; 359 360 swap_data(fType, fBytes, Size(), B_SWAP_ALWAYS); 361 } 362 363 364 /*static*/ size_t 365 BVariant::SizeOfType(type_code type) 366 { 367 switch (type) { 368 case B_BOOL_TYPE: 369 return 1; 370 case B_INT8_TYPE: 371 return 1; 372 case B_UINT8_TYPE: 373 return 1; 374 case B_INT16_TYPE: 375 return 2; 376 case B_UINT16_TYPE: 377 return 2; 378 case B_INT32_TYPE: 379 return 4; 380 case B_UINT32_TYPE: 381 return 4; 382 case B_INT64_TYPE: 383 return 8; 384 case B_UINT64_TYPE: 385 return 8; 386 case B_FLOAT_TYPE: 387 return sizeof(float); 388 case B_DOUBLE_TYPE: 389 return sizeof(double); 390 case B_POINTER_TYPE: 391 return sizeof(void*); 392 default: 393 return 0; 394 } 395 } 396 397 398 void 399 BVariant::_SetTo(bool value) 400 { 401 fType = B_BOOL_TYPE; 402 fFlags = 0; 403 fBool = value; 404 } 405 406 407 void 408 BVariant::_SetTo(int8 value) 409 { 410 fType = B_INT8_TYPE; 411 fFlags = 0; 412 fInt8 = value; 413 } 414 415 416 void 417 BVariant::_SetTo(uint8 value) 418 { 419 fType = B_UINT8_TYPE; 420 fFlags = 0; 421 fUInt8 = value; 422 } 423 424 425 void 426 BVariant::_SetTo(int16 value) 427 { 428 fType = B_INT16_TYPE; 429 fFlags = 0; 430 fInt16 = value; 431 } 432 433 434 void 435 BVariant::_SetTo(uint16 value) 436 { 437 fType = B_UINT16_TYPE; 438 fFlags = 0; 439 fUInt16 = value; 440 } 441 442 443 void 444 BVariant::_SetTo(int32 value) 445 { 446 fType = B_INT32_TYPE; 447 fFlags = 0; 448 fInt32 = value; 449 } 450 451 452 void 453 BVariant::_SetTo(uint32 value) 454 { 455 fType = B_UINT32_TYPE; 456 fFlags = 0; 457 fUInt32 = value; 458 } 459 460 461 void 462 BVariant::_SetTo(int64 value) 463 { 464 fType = B_INT64_TYPE; 465 fFlags = 0; 466 fInt64 = value; 467 } 468 469 470 void 471 BVariant::_SetTo(uint64 value) 472 { 473 fType = B_UINT64_TYPE; 474 fFlags = 0; 475 fUInt64 = value; 476 } 477 478 479 void 480 BVariant::_SetTo(float value) 481 { 482 fType = B_FLOAT_TYPE; 483 fFlags = 0; 484 fFloat = value; 485 } 486 487 488 void 489 BVariant::_SetTo(double value) 490 { 491 fType = B_DOUBLE_TYPE; 492 fFlags = 0; 493 fDouble = value; 494 } 495 496 497 void 498 BVariant::_SetTo(const void* value) 499 { 500 fType = B_POINTER_TYPE; 501 fFlags = 0; 502 fPointer = (void*)value; 503 } 504 505 506 bool 507 BVariant::_SetTo(const char* value, uint32 flags) 508 { 509 fType = B_STRING_TYPE; 510 fFlags = 0; 511 512 if (value != NULL) { 513 if ((flags & B_VARIANT_DONT_COPY_DATA) == 0) { 514 fString = strdup(value); 515 fFlags |= B_VARIANT_OWNS_DATA; 516 if (fString == NULL) 517 return false; 518 } else { 519 fString = (char*)value; 520 fFlags |= flags & B_VARIANT_OWNS_DATA; 521 } 522 } else 523 fString = NULL; 524 525 return true; 526 } 527 528 529 void 530 BVariant::_SetTo(BReferenceable* value, type_code type) 531 { 532 fType = type; 533 fFlags = B_VARIANT_REFERENCEABLE_DATA; 534 fReferenceable = value; 535 536 if (fReferenceable != NULL) 537 fReferenceable->AcquireReference(); 538 } 539