btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / shared / Variant.cpp
blob7d32e42c1db4f78224dbba104a28b284d5828055
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 */
8 #include <Variant.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include <ByteOrder.h>
14 #include <Message.h>
17 template<typename NumberType>
18 inline NumberType
19 BVariant::_ToNumber() const
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;
50 BVariant::~BVariant()
52 Unset();
56 status_t
57 BVariant::SetToTypedData(const void* data, type_code type)
59 Unset();
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:
102 BRect *rect = (BRect *)data;
103 _SetTo(rect->left, rect->top, rect->right, rect->bottom);
104 break;
106 default:
107 return B_BAD_TYPE;
110 fType = type;
111 return B_OK;
115 void
116 BVariant::Unset()
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;
126 } else if ((fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0) {
127 if (fReferenceable != NULL)
128 fReferenceable->ReleaseReference();
131 fType = 0;
132 fFlags = 0;
136 bool
137 BVariant::operator==(const BVariant& other) const
139 if (fType == 0)
140 return other.fType == 0;
141 if (other.fType == 0)
142 return false;
144 // TODO: The number comparisons are not really accurate. Particularly a
145 // conversion between signed and unsigned integers might actually change the
146 // value.
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;
189 size_t
190 BVariant::Size() const
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);
200 const uint8*
201 BVariant::Bytes() const
203 if (fType == B_STRING_TYPE)
204 return (const uint8*)fString;
205 return fBytes;
209 bool
210 BVariant::ToBool() const
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;
247 int8
248 BVariant::ToInt8() const
250 return _ToNumber<int8>();
254 uint8
255 BVariant::ToUInt8() const
257 return _ToNumber<uint8>();
261 int16
262 BVariant::ToInt16() const
264 return _ToNumber<int16>();
268 uint16
269 BVariant::ToUInt16() const
271 return _ToNumber<uint16>();
275 int32
276 BVariant::ToInt32() const
278 return _ToNumber<int32>();
282 uint32
283 BVariant::ToUInt32() const
285 return _ToNumber<uint32>();
289 int64
290 BVariant::ToInt64() const
292 return _ToNumber<int64>();
296 uint64
297 BVariant::ToUInt64() const
299 return _ToNumber<uint64>();
303 float
304 BVariant::ToFloat() const
306 return _ToNumber<float>();
310 double
311 BVariant::ToDouble() const
313 return _ToNumber<double>();
317 BRect
318 BVariant::ToRect() const
320 return BRect(fRect.left, fRect.top, fRect.right, fRect.bottom);
324 void*
325 BVariant::ToPointer() const
327 return fType == B_POINTER_TYPE ? fString : NULL;
331 const char*
332 BVariant::ToString() const
334 return fType == B_STRING_TYPE ? fString : NULL;
338 void
339 BVariant::_SetTo(const BVariant& other)
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;
351 } else if ((other.fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0) {
352 if (other.fReferenceable != NULL)
353 other.fReferenceable->AcquireReference();
356 memcpy(this, &other, sizeof(BVariant));
360 BReferenceable*
361 BVariant::ToReferenceable() const
363 return (fFlags & B_VARIANT_REFERENCEABLE_DATA) != 0
364 ? fReferenceable : NULL;
368 void
369 BVariant::SwapEndianess()
371 if (!IsNumber() || fType == B_POINTER_TYPE)
372 return;
374 swap_data(fType, fBytes, Size(), B_SWAP_ALWAYS);
378 status_t
379 BVariant::AddToMessage(BMessage& message, const char* fieldName) const
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;
417 status_t
418 BVariant::SetFromMessage(const BMessage& message, const char* fieldName)
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;
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;
434 // init the object
435 return SetToTypedData(data, type);
439 /*static*/ size_t
440 BVariant::SizeOfType(type_code type)
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;
475 /*static*/ bool
476 BVariant::TypeIsNumber(type_code type)
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;
496 /*static*/ bool
497 BVariant::TypeIsInteger(type_code type, bool* _isSigned)
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;
520 /*static*/ bool
521 BVariant::TypeIsFloat(type_code type)
523 switch (type) {
524 case B_FLOAT_TYPE:
525 case B_DOUBLE_TYPE:
526 return true;
527 default:
528 return false;
533 void
534 BVariant::_SetTo(bool value)
536 fType = B_BOOL_TYPE;
537 fFlags = 0;
538 fBool = value;
542 void
543 BVariant::_SetTo(int8 value)
545 fType = B_INT8_TYPE;
546 fFlags = 0;
547 fInt8 = value;
551 void
552 BVariant::_SetTo(uint8 value)
554 fType = B_UINT8_TYPE;
555 fFlags = 0;
556 fUInt8 = value;
560 void
561 BVariant::_SetTo(int16 value)
563 fType = B_INT16_TYPE;
564 fFlags = 0;
565 fInt16 = value;
569 void
570 BVariant::_SetTo(uint16 value)
572 fType = B_UINT16_TYPE;
573 fFlags = 0;
574 fUInt16 = value;
578 void
579 BVariant::_SetTo(int32 value)
581 fType = B_INT32_TYPE;
582 fFlags = 0;
583 fInt32 = value;
587 void
588 BVariant::_SetTo(uint32 value)
590 fType = B_UINT32_TYPE;
591 fFlags = 0;
592 fUInt32 = value;
596 void
597 BVariant::_SetTo(int64 value)
599 fType = B_INT64_TYPE;
600 fFlags = 0;
601 fInt64 = value;
605 void
606 BVariant::_SetTo(uint64 value)
608 fType = B_UINT64_TYPE;
609 fFlags = 0;
610 fUInt64 = value;
614 void
615 BVariant::_SetTo(float value)
617 fType = B_FLOAT_TYPE;
618 fFlags = 0;
619 fFloat = value;
623 void
624 BVariant::_SetTo(double value)
626 fType = B_DOUBLE_TYPE;
627 fFlags = 0;
628 fDouble = value;
632 void
633 BVariant::_SetTo(float left, float top, float right, float bottom)
635 fType = B_RECT_TYPE;
636 fFlags = 0;
637 fRect.left = left;
638 fRect.top = top;
639 fRect.right = right;
640 fRect.bottom = bottom;
644 void
645 BVariant::_SetTo(const void* value)
647 fType = B_POINTER_TYPE;
648 fFlags = 0;
649 fPointer = (void*)value;
653 bool
654 BVariant::_SetTo(const char* value, uint32 flags)
656 fType = B_STRING_TYPE;
657 fFlags = 0;
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;
669 } else
670 fString = NULL;
672 return true;
676 void
677 BVariant::_SetTo(BReferenceable* value, type_code type)
679 fType = type;
680 fFlags = B_VARIANT_REFERENCEABLE_DATA;
681 fReferenceable = value;
683 if (fReferenceable != NULL)
684 fReferenceable->AcquireReference();