variant.cpp 13.9 KB
Newer Older
1 2
/*
 * variant.cpp
Ronan's avatar
Ronan committed
3
 * Copyright (C) 2010-2018 Belledonne Communications SARL
4
 *
Ghislain MARY's avatar
Ghislain MARY committed
5 6 7 8
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
9 10
 *
 * This program is distributed in the hope that it will be useful,
Ghislain MARY's avatar
Ghislain MARY committed
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 13 14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
Ghislain MARY's avatar
Ghislain MARY committed
16 17
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 19
 */

Ronan's avatar
Ronan committed
20 21
#include "linphone/utils/utils.h"

22 23 24 25
#include "variant.h"

// =============================================================================

26 27
using namespace std;

28 29
LINPHONE_BEGIN_NAMESPACE

30 31
// -----------------------------------------------------------------------------

32 33 34 35 36
class VariantPrivate {
public:
	union Value {
		int i;
		unsigned int ui;
37 38
		short s;
		unsigned short us;
39 40 41 42
		long l;
		unsigned long ul;
		long long ll;
		unsigned long long ull;
43
		char c;
44 45 46
		bool b;
		double d;
		float f;
Ronan's avatar
Ronan committed
47 48
		string *str;
		void *g;
49 50
	};

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
	~VariantPrivate () {
		deleteString();
	}

	inline int getType () const {
		return type;
	}

	inline void setType (int newType) {
		L_ASSERT(newType >= Variant::Invalid && newType != Variant::MaxDefaultTypes);

		if (newType != Variant::String)
			deleteString();
		else if (type != Variant::String)
			value.str = new string();

		type = newType;
	}

	Value value = {};

private:
	inline void deleteString () {
		if (type == Variant::String)
75
			delete value.str;
76 77
	}

Ronan's avatar
Ronan committed
78 79
	// Integer, because type can be a custom type.
	int type = Variant::Invalid;
80 81
};

Ronan's avatar
Ronan committed
82 83
// -----------------------------------------------------------------------------

84
Variant::Variant () {
85
	// Private can exist. (placement new)
Ronan's avatar
Ronan committed
86 87
	if (!mPrivate)
		mPrivate = new VariantPrivate();
88 89
}

Ronan's avatar
Ronan committed
90
Variant::Variant (Type type) : Variant() {
91
	L_D();
92
	d->setType(type);
93 94
}

95
Variant::Variant (const Variant &other) {
96 97 98 99
	// Don't call placement new.
	L_ASSERT(!mPrivate);
	mPrivate = new VariantPrivate();

100
	L_D();
101

102
	int type = other.getPrivate()->getType();
103
	d->setType(type);
104

105
	const VariantPrivate::Value &value = other.getPrivate()->value;
106 107
	if (type == String)
		*d->value.str = *value.str;
108 109
	else
		d->value = value;
110 111
}

112
Variant::Variant (Variant &&other) {
113 114
	// Don't call placement new.
	L_ASSERT(!mPrivate);
115
	::swap(mPrivate, other.mPrivate);
116 117 118
}

Variant::Variant (int value) : Variant(Int) {
119
	L_D();
120 121 122
	d->value.i = value;
}

123
Variant::Variant (unsigned int value) : Variant(UnsignedInt) {
124
	L_D();
125 126 127
	d->value.ui = value;
}

128
Variant::Variant (short value) : Variant(Short) {
129
	L_D();
130 131 132 133
	d->value.s = value;
}

Variant::Variant (unsigned short value) : Variant(UnsignedShort) {
134
	L_D();
135 136 137 138
	d->value.us = value;
}

Variant::Variant (long value) : Variant(Long) {
139
	L_D();
140 141 142
	d->value.l = value;
}

143
Variant::Variant (unsigned long value) : Variant(UnsignedLong) {
144
	L_D();
145 146 147
	d->value.ul = value;
}

148
Variant::Variant (long long value) : Variant(LongLong) {
149
	L_D();
150 151 152
	d->value.ll = value;
}

153
Variant::Variant (unsigned long long value) : Variant(UnsignedLongLong) {
154
	L_D();
155 156 157
	d->value.ull = value;
}

158
Variant::Variant (char value) : Variant(Char) {
159
	L_D();
160 161 162 163
	d->value.c = value;
}

Variant::Variant (bool value) : Variant(Bool) {
164
	L_D();
165 166 167
	d->value.b = value;
}

168
Variant::Variant (double value) : Variant(Double) {
169
	L_D();
170 171 172
	d->value.d = value;
}

173
Variant::Variant (float value) : Variant(Float) {
174
	L_D();
175 176 177
	d->value.f = value;
}

178
Variant::Variant (const string &value) : Variant(String) {
179
	L_D();
Ronan's avatar
Ronan committed
180
	*d->value.str = value;
181 182 183
}

Variant::~Variant () {
184
	L_D();
Ronan's avatar
Ronan committed
185

186 187 188
	// Note: Private data can be stolen by copy operator (r-value).
	// It can be null, but it useless to test it.
	delete d;
189 190
}

191
Variant &Variant::operator= (const Variant &other) {
192
	L_D();
193

194
	if (this != &other) {
195
		// Update type.
196
		int type = other.getPrivate()->getType();
197 198 199
		d->setType(type);

		// Update value.
200
		const VariantPrivate::Value &value = other.getPrivate()->value;
201 202 203 204 205 206
		if (type == String)
			*d->value.str = *value.str;
		else
			d->value = value;
	}

207 208 209
	return *this;
}

210 211
Variant &Variant::operator= (Variant &&other) {
	::swap(mPrivate, other.mPrivate);
212 213 214 215
	return *this;
}

bool Variant::isValid () const {
216
	L_D();
217
	return d->getType() != Invalid;
218 219 220
}

void Variant::clear () {
221
	L_D();
222
	d->setType(Invalid);
223 224
}

225
void Variant::swap (const Variant &other) {
226 227 228
	// TODO.
}

Ronan's avatar
Ronan committed
229 230 231 232 233
// -----------------------------------------------------------------------------
// Number helpers.
// -----------------------------------------------------------------------------

static inline long long getAssumedNumber (const VariantPrivate &p) {
234 235
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);
Ronan's avatar
Ronan committed
236

237
	switch (static_cast<Variant::Type>(type)) {
Ronan's avatar
Ronan committed
238 239 240 241 242 243 244 245 246 247 248
		case Variant::Int:
			return p.value.i;
		case Variant::Short:
			return p.value.s;
		case Variant::Long:
			return p.value.l;
		case Variant::LongLong:
			return p.value.ll;
		case Variant::Char:
			return p.value.c;
		case Variant::Double:
Ronan's avatar
Ronan committed
249
			return static_cast<long long>(p.value.d);
Ronan's avatar
Ronan committed
250
		case Variant::Float:
Ronan's avatar
Ronan committed
251
			return static_cast<long long>(p.value.f);
Ronan's avatar
Ronan committed
252 253 254 255 256 257 258 259 260

		default:
			L_ASSERT(false);
	}

	return 0;
}

static inline unsigned long long getAssumedUnsignedNumber (const VariantPrivate &p) {
261 262
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);
Ronan's avatar
Ronan committed
263

264
	switch (static_cast<Variant::Type>(type)) {
Ronan's avatar
Ronan committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
		case Variant::UnsignedInt:
			return p.value.ui;
		case Variant::UnsignedShort:
			return p.value.us;
		case Variant::UnsignedLong:
			return p.value.ul;
		case Variant::UnsignedLongLong:
			return p.value.ull;

		default:
			L_ASSERT(false);
	}

	return 0;
}

281
// -----------------------------------------------------------------------------
282 283 284 285
// Number conversions.
// -----------------------------------------------------------------------------

static inline long long getValueAsNumber (const VariantPrivate &p, bool *soFarSoGood) {
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);

	switch (static_cast<Variant::Type>(type)) {
		case Variant::Int:
		case Variant::Short:
		case Variant::Long:
		case Variant::LongLong:
		case Variant::Char:
		case Variant::Double:
		case Variant::Float:
			return getAssumedNumber(p);

		case Variant::UnsignedInt:
		case Variant::UnsignedShort:
		case Variant::UnsignedLong:
		case Variant::UnsignedLongLong:
			return static_cast<long long>(getAssumedUnsignedNumber(p));

		case Variant::Bool:
			return static_cast<long long>(p.value.b);

		case Variant::String:
			return Utils::stoll(*p.value.str);

		case Variant::Generic:
			return static_cast<long long>(!!p.value.g);

		default:
			*soFarSoGood = false;
	}

318 319 320 321
	return 0;
}

static inline unsigned long long getValueAsUnsignedNumber (const VariantPrivate &p, bool *soFarSoGood) {
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);

	switch (static_cast<Variant::Type>(type)) {
		case Variant::Int:
		case Variant::Short:
		case Variant::Long:
		case Variant::LongLong:
		case Variant::Char:
		case Variant::Double:
		case Variant::Float:
			return static_cast<unsigned long long>(getAssumedNumber(p));

		case Variant::UnsignedInt:
		case Variant::UnsignedShort:
		case Variant::UnsignedLong:
		case Variant::UnsignedLongLong:
			return getAssumedUnsignedNumber(p);

		case Variant::Bool:
			return static_cast<unsigned long long>(p.value.b);

		case Variant::String:
			return Utils::stoull(*p.value.str);

		case Variant::Generic:
			return static_cast<unsigned long long>(!!p.value.g);

		default:
			*soFarSoGood = false;
	}

354 355 356 357 358 359 360 361
	return 0;
}

// -----------------------------------------------------------------------------
// Specific conversions.
// -----------------------------------------------------------------------------

static inline bool getValueAsBool (const VariantPrivate &p, bool *soFarSoGood) {
362 363
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);
Ronan's avatar
Ronan committed
364

365
	switch (static_cast<Variant::Type>(type)) {
Ronan's avatar
Ronan committed
366 367 368 369 370 371 372
		case Variant::Int:
		case Variant::Short:
		case Variant::Long:
		case Variant::LongLong:
		case Variant::Char:
		case Variant::Double:
		case Variant::Float:
373
			return!!getAssumedNumber(p);
Ronan's avatar
Ronan committed
374 375 376 377 378

		case Variant::UnsignedInt:
		case Variant::UnsignedShort:
		case Variant::UnsignedLong:
		case Variant::UnsignedLongLong:
379
			return !!getAssumedUnsignedNumber(p);
Ronan's avatar
Ronan committed
380 381 382 383 384

		case Variant::Bool:
			return p.value.b;

		case Variant::String:
385
			return Utils::stob(*p.value.str);
Ronan's avatar
Ronan committed
386 387

		case Variant::Generic:
388
			return !!p.value.g;
Ronan's avatar
Ronan committed
389 390 391 392 393 394

		default:
			*soFarSoGood = false;
			break;
	}

395 396 397 398
	return false;
}

static inline double getValueAsDouble (const VariantPrivate &p, bool *soFarSoGood) {
399 400
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);
401

402
	switch (static_cast<Variant::Type>(type)) {
403 404 405 406 407 408 409 410 411 412 413 414 415
		case Variant::Int:
		case Variant::Short:
		case Variant::Long:
		case Variant::LongLong:
		case Variant::Char:
			return static_cast<double>(getAssumedNumber(p));

		case Variant::UnsignedInt:
		case Variant::UnsignedShort:
		case Variant::UnsignedLong:
		case Variant::UnsignedLongLong:
			return static_cast<double>(getAssumedUnsignedNumber(p));

416 417 418
		case Variant::Float:
			return static_cast<double>(p.value.f);

419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
		case Variant::Double:
			return p.value.d;

		case Variant::Bool:
			return static_cast<double>(p.value.b);

		case Variant::String:
			return Utils::stod(*p.value.str);

		case Variant::Generic:
			return static_cast<double>(!!p.value.g);

		default:
			*soFarSoGood = false;
			break;
	}

436 437
	return 0.0;
}
438

439
static inline float getValueAsFloat (const VariantPrivate &p, bool *soFarSoGood) {
440 441 442 443 444 445 446 447 448
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);

	switch (static_cast<Variant::Type>(type)) {
		case Variant::Int:
		case Variant::Short:
		case Variant::Long:
		case Variant::LongLong:
		case Variant::Char:
Ronan's avatar
Ronan committed
449
			return static_cast<float>(getAssumedNumber(p));
450 451 452 453 454

		case Variant::UnsignedInt:
		case Variant::UnsignedShort:
		case Variant::UnsignedLong:
		case Variant::UnsignedLongLong:
Ronan's avatar
Ronan committed
455
			return static_cast<float>(getAssumedUnsignedNumber(p));
456 457 458 459 460 461 462 463

		case Variant::Float:
			return p.value.f;

		case Variant::Double:
			return static_cast<float>(p.value.d);

		case Variant::Bool:
Ronan's avatar
Ronan committed
464
			return static_cast<float>(p.value.b);
465 466 467 468 469

		case Variant::String:
			return Utils::stof(*p.value.str);

		case Variant::Generic:
Ronan's avatar
Ronan committed
470
			return static_cast<float>(!!p.value.g);
471 472 473 474 475 476

		default:
			*soFarSoGood = false;
			break;
	}

477 478 479
	return 0.f;
}

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
static inline string getValueAsString (const VariantPrivate &p, bool *soFarSoGood) {
	const int type = p.getType();
	L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes);

	switch (static_cast<Variant::Type>(type)) {
		case Variant::Int:
		case Variant::Short:
		case Variant::Long:
		case Variant::LongLong:
			return Utils::toString(getAssumedNumber(p));

		case Variant::UnsignedInt:
		case Variant::UnsignedShort:
		case Variant::UnsignedLong:
		case Variant::UnsignedLongLong:
			return Utils::toString(getAssumedUnsignedNumber(p));

		case Variant::Char:
			return string(1, p.value.c);

		case Variant::Bool:
			return string(p.value.b ? "true" : "false");

		case Variant::Double:
			return Utils::toString(p.value.d);

		case Variant::Float:
			return Utils::toString(p.value.f);

		case Variant::String:
			return *p.value.str;

		case Variant::Generic:
			return Utils::toString(p.value.g);

		default:
			*soFarSoGood = false;
	}

	return string();
520
}
521

522
static inline void *getValueAsGeneric (const VariantPrivate &p, bool *soFarSoGood) {
523
	if (p.getType() == Variant::Generic)
524 525 526
		return p.value.g;

	*soFarSoGood = false;
527 528 529 530 531 532
	return nullptr;
}

// -----------------------------------------------------------------------------

void Variant::getValue (int type, void *value, bool *soFarSoGood) const {
Ronan's avatar
Ronan committed
533 534
	L_ASSERT(type > Invalid && type != MaxDefaultTypes);

535
	L_D();
536

537 538
	*soFarSoGood = true;

Ronan's avatar
Ronan committed
539
	if (type > MaxDefaultTypes) {
540
		*soFarSoGood = false;
Ronan's avatar
Ronan committed
541
		// TODO: Unable to get value. It will be great to support custom types.
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
		return;
	}

	switch (static_cast<Type>(type)) {
		// Cast as Number.
		case Int:
			*static_cast<int *>(value) = static_cast<int>(getValueAsNumber(*d, soFarSoGood));
			break;
		case Short:
			*static_cast<short *>(value) = static_cast<short>(getValueAsNumber(*d, soFarSoGood));
			break;
		case Long:
			*static_cast<long *>(value) = static_cast<long>(getValueAsNumber(*d, soFarSoGood));
			break;
		case LongLong:
			*static_cast<long long *>(value) = getValueAsNumber(*d, soFarSoGood);
			break;
		case Char:
			*static_cast<char *>(value) = static_cast<char>(getValueAsNumber(*d, soFarSoGood));
			break;

		// Cast as Unsigned number.
		case UnsignedInt:
565
			*static_cast<unsigned int *>(value) = static_cast<unsigned int>(getValueAsUnsignedNumber(*d, soFarSoGood));
566 567
			break;
		case UnsignedShort:
568
			*static_cast<unsigned short *>(value) = static_cast<unsigned short>(getValueAsUnsignedNumber(*d, soFarSoGood));
569 570
			break;
		case UnsignedLong:
571
			*static_cast<unsigned long *>(value) = static_cast<unsigned long>(getValueAsUnsignedNumber(*d, soFarSoGood));
572 573
			break;
		case UnsignedLongLong:
574
			*static_cast<unsigned long long *>(value) = getValueAsUnsignedNumber(*d, soFarSoGood);
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
			break;

		// Cast as specific value.
		case Bool:
			*static_cast<bool *>(value) = getValueAsBool(*d, soFarSoGood);
			break;
		case Double:
			*static_cast<double *>(value) = getValueAsDouble(*d, soFarSoGood);
			break;
		case Float:
			*static_cast<float *>(value) = getValueAsFloat(*d, soFarSoGood);
			break;
		case String:
			*static_cast<string *>(value) = getValueAsString(*d, soFarSoGood);
			break;
		case Generic:
			*static_cast<void **>(value) = getValueAsGeneric(*d, soFarSoGood);
			break;

		case Invalid:
		case MaxDefaultTypes:
			*soFarSoGood = false;
			break;
	}
599 600
}

601 602 603 604 605 606
Variant Variant::createGeneric (void *value) {
	Variant variant(Generic);
	variant.getPrivate()->value.g = value;
	return variant;
}

607
LINPHONE_END_NAMESPACE