xref: /haiku/src/kits/shared/Variant.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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