VAStruct.cpp 17.8 KB
Newer Older
Jonas Stienen's avatar
Jonas Stienen committed
1
/*
2
 *  --------------------------------------------------------------------------------------------
Jonas Stienen's avatar
Jonas Stienen committed
3
 *
4 5 6
 *    VVV        VVV A           Virtual Acoustics (VA) | http://www.virtualacoustics.org
 *     VVV      VVV AAA          Licensed under the Apache License, Version 2.0
 *      VVV    VVV   AAA
7
 *       VVV  VVV     AAA        Copyright 2015-2020
8 9
 *        VVVVVV       AAA       Institute of Technical Acoustics (ITA)
 *         VVVV         AAA      RWTH Aachen University
Jonas Stienen's avatar
Jonas Stienen committed
10
 *
11
 *  --------------------------------------------------------------------------------------------
Jonas Stienen's avatar
Jonas Stienen committed
12
 */
13

Jonas Stienen's avatar
Jonas Stienen committed
14 15 16 17 18 19 20 21 22 23 24 25
#include <VAStruct.h>

#include <VAException.h>

#include <cassert>
#include <sstream>
#include <cstring>

CVAStructValue m_kDummyKey;

CVAStruct::CVAStruct() {}

26
CVAStruct::CVAStruct( const CVAStruct& rhs )
Jonas Stienen's avatar
Jonas Stienen committed
27 28 29 30
{
	*this = rhs;
}

31 32
CVAStruct::~CVAStruct()
{
33 34 35 36
	// Recursively destruct associated keys
	CVAStruct::iterator it = Begin();
	while( it != End() )
		m_mData.erase( it++ );
37
}
Jonas Stienen's avatar
Jonas Stienen committed
38 39 40

int CVAStruct::Size() const
{
41
	return ( int ) m_mData.size();
Jonas Stienen's avatar
Jonas Stienen committed
42 43
}

44 45
bool CVAStruct::IsEmpty() const
{
Jonas Stienen's avatar
Jonas Stienen committed
46 47 48
	return m_mData.empty();
}

49 50
bool CVAStruct::HasKey( const std::string& sKey ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
51
	// Check if the key exists
52
	return m_mData.find( sKey ) != m_mData.end();
Jonas Stienen's avatar
Jonas Stienen committed
53 54
}

55 56
void CVAStruct::Clear()
{
Jonas Stienen's avatar
Jonas Stienen committed
57 58 59
	m_mData.clear();
}

60 61
bool CVAStruct::RemoveKey( const std::string& sKey )
{
Jonas Stienen's avatar
Jonas Stienen committed
62
	// Check if the key exists
63 64 65 66
	MapIt it = m_mData.find( sKey );
	if( it == m_mData.end() )
		return false; // Key not found
	m_mData.erase( it );
Jonas Stienen's avatar
Jonas Stienen committed
67 68 69
	return true;
}

70 71
CVAStructValue* CVAStruct::Traverse( const std::string& sPath, size_t iPathCursor, const char cPathSeparator )
{
Jonas Stienen's avatar
Jonas Stienen committed
72 73
	// Find next path element
	size_t n;
74 75 76
	n = sPath.find( cPathSeparator, iPathCursor );
	if( n == std::string::npos )
	{
Jonas Stienen's avatar
Jonas Stienen committed
77
		// Last element on path
78 79
		Map::iterator it = m_mData.find( sPath.substr( iPathCursor, sPath.length() - iPathCursor ) );
		return ( it != m_mData.end() ? &( it->second ) : nullptr );
80
	}
81 82
	else
	{
Jonas Stienen's avatar
Jonas Stienen committed
83
		// Next element on path (at least one more follows)
84 85 86 87
		std::string t = sPath.substr( iPathCursor, n - iPathCursor );
		Map::iterator it = m_mData.find( t );
		if( it == m_mData.end() )
			return nullptr; // Error: Path not found
88

Jonas Stienen's avatar
Jonas Stienen committed
89
		CVAStructValue& oNode = it->second;
90 91
		if( !oNode.IsStruct() )
			return nullptr;	// Error: Node is a leaf, paths goes further...
Jonas Stienen's avatar
Jonas Stienen committed
92 93

		// Traverse into subtree
94
		return oNode.GetStruct().Traverse( sPath, n + 1, cPathSeparator );
Jonas Stienen's avatar
Jonas Stienen committed
95 96 97
	}
}

98 99
const CVAStructValue* CVAStruct::Traverse( const std::string& sPath, size_t iPathCursor, const char cPathSeparator ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
100 101
	// Find next path element
	size_t n;
102 103 104
	n = sPath.find( cPathSeparator, iPathCursor );
	if( n == std::string::npos )
	{
Jonas Stienen's avatar
Jonas Stienen committed
105
		// Last element on path
106 107
		Map::const_iterator it = m_mData.find( sPath.substr( iPathCursor, sPath.length() - iPathCursor ) );
		return ( it != m_mData.end() ? &( it->second ) : nullptr );
108
	}
109 110
	else
	{
Jonas Stienen's avatar
Jonas Stienen committed
111
		// Next element on path (at least one more follows)
112 113 114 115
		std::string t = sPath.substr( iPathCursor, n - iPathCursor );
		Map::const_iterator it = m_mData.find( t );
		if( it == m_mData.end() )
			return nullptr; // Error: Path not found
Jonas Stienen's avatar
Jonas Stienen committed
116 117

		const CVAStructValue& oNode = it->second;
118 119
		if( !oNode.IsStruct() )
			return nullptr;	// Error: Node is a leaf, paths goes further...
Jonas Stienen's avatar
Jonas Stienen committed
120 121

		// Traverse into subtree
122
		return oNode.GetStruct().Traverse( sPath, n + 1, cPathSeparator );
Jonas Stienen's avatar
Jonas Stienen committed
123 124 125
	}
}

126 127
const CVAStructValue* CVAStruct::GetValue( const std::string& sPath, const char cPathSeparator ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
128
	// Path resolution
129
	return Traverse( sPath, 0, cPathSeparator );
Jonas Stienen's avatar
Jonas Stienen committed
130 131
}

132 133
CVAStructValue* CVAStruct::GetValue( const std::string& sPath, const char cPathSeparator )
{
Jonas Stienen's avatar
Jonas Stienen committed
134
	// Path resolution
135
	return Traverse( sPath, 0, cPathSeparator );
Jonas Stienen's avatar
Jonas Stienen committed
136 137
}

138 139
const CVAStructValue& CVAStruct::operator[]( const char* pcKey ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
140
	// Check if the key exists
141
	Map::const_iterator cit = m_mData.find( pcKey );
Jonas Stienen's avatar
Jonas Stienen committed
142

143
	if( cit != m_mData.end() )
Jonas Stienen's avatar
Jonas Stienen committed
144
		return cit->second;
145

Jonas Stienen's avatar
Jonas Stienen committed
146
	// Key does not exist
147
	assert( false );
Jonas Stienen's avatar
Jonas Stienen committed
148 149 150 151 152
	return m_kDummyKey;

	// TODO: How to handle this
}

153
CVAStructValue& CVAStruct::operator[]( const char* pcKey )
Jonas Stienen's avatar
Jonas Stienen committed
154 155
{
	// Check if the key exists
156
	Map::iterator it = m_mData.find( pcKey );
Jonas Stienen's avatar
Jonas Stienen committed
157

158
	if( it != m_mData.end() )
Jonas Stienen's avatar
Jonas Stienen committed
159 160 161 162 163 164 165
	{
		// If the key already exists return this
		return it->second;
	}
	else
	{
		// Otherwise: create an unassigned key with the given name
166
		it = m_mData.insert( m_mData.begin(), std::pair<std::string, CVAStructValue>( pcKey, CVAStructValue() ) );
Jonas Stienen's avatar
Jonas Stienen committed
167 168 169 170 171
		it->second.psKey = &it->first;
		return it->second;
	}
}

172 173
CVAStruct& CVAStruct::operator=( const CVAStruct& rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
174 175 176
	m_mData.clear();

	// Autonome Kopien aller Schlssel einfgen
177 178 179
	for( Map::const_iterator cit = rhs.Begin(); cit != rhs.End(); ++cit )
	{
		CVAStructValue& oKey = m_mData[ cit->first ];
Jonas Stienen's avatar
Jonas Stienen committed
180 181 182 183 184 185 186
		oKey.psKey = &cit->first;
		oKey = cit->second;
	}

	return *this;
}

187 188 189 190 191 192 193 194 195 196 197 198 199 200
CVAStruct::iterator CVAStruct::Begin()
{
	return m_mData.begin();
}

CVAStruct::const_iterator CVAStruct::Begin() const
{
	return m_mData.begin();
}

CVAStruct::iterator CVAStruct::End()
{
	return m_mData.end();
}
Jonas Stienen's avatar
Jonas Stienen committed
201

202 203 204 205 206 207 208 209 210 211
CVAStruct::const_iterator CVAStruct::End() const
{
	return m_mData.end();
}

void CVAStruct::Merge( const CVAStruct& rhs, const bool bUnique )
{
	for( CVAStruct::const_iterator cit = rhs.Begin(); cit != rhs.End(); ++cit )
	{
		MapIt it = m_mData.find( cit->first );
Jonas Stienen's avatar
Jonas Stienen committed
212

213 214
		if( bUnique && it != m_mData.end() )
			VA_EXCEPT1( "Failed to merge structs. Keys not disjoint." );
Jonas Stienen's avatar
Jonas Stienen committed
215

216
		m_mData[ cit->first ] = cit->second;
Jonas Stienen's avatar
Jonas Stienen committed
217 218 219
	}
}

220 221
std::string CVAStruct::ToString( const int iIndent ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
222
	std::stringstream ss;
223
	std::string margin( iIndent, ' ' );
Jonas Stienen's avatar
Jonas Stienen committed
224

225 226
	for( Map::const_iterator cit = m_mData.begin(); cit != m_mData.end(); ++cit )
	{
Jonas Stienen's avatar
Jonas Stienen committed
227
		const CVAStructValue& k = cit->second;
228 229
		switch( k.iDatatype )
		{
Jonas Stienen's avatar
Jonas Stienen committed
230
		case CVAStructValue::BOOL:
231
		{
Jonas Stienen's avatar
Jonas Stienen committed
232 233
			ss << margin << cit->first << " = " << cit->second.ToString() << " [bool]" << std::endl;
			break;
234
		}
Jonas Stienen's avatar
Jonas Stienen committed
235
		case CVAStructValue::INT:
236
		{
Jonas Stienen's avatar
Jonas Stienen committed
237 238
			ss << margin << cit->first << " = " << cit->second.ToString() << " [int]" << std::endl;
			break;
239
		}
Jonas Stienen's avatar
Jonas Stienen committed
240
		case CVAStructValue::DOUBLE:
241
		{
Jonas Stienen's avatar
Jonas Stienen committed
242 243
			ss << margin << cit->first << " = " << cit->second.ToString() << " [double]" << std::endl;
			break;
244
		}
Jonas Stienen's avatar
Jonas Stienen committed
245
		case CVAStructValue::STRING:
246
		{
Jonas Stienen's avatar
Jonas Stienen committed
247 248
			ss << margin << cit->first << " = \"" << cit->second.ToString() << "\" [string]" << std::endl;
			break;
249
		}
Jonas Stienen's avatar
Jonas Stienen committed
250
		case CVAStructValue::STRUCT:
251 252 253
		{
			const CVAStruct& oKey = cit->second;
			ss << margin << cit->first << " = [struct] { " << std::endl
254
				<< margin << oKey.ToString( iIndent + 4 )
255
				<< margin << "}" << std::endl;
256
			break;
257
		}
Jonas Stienen's avatar
Jonas Stienen committed
258
		case CVAStructValue::DATA:
259
		{
Jonas Stienen's avatar
Jonas Stienen committed
260
			ss << margin << cit->first << " = [data: " << cit->second.GetDataSize() << " bytes]" << std::endl;
261 262
			break;
		}
Jonas Stienen's avatar
Jonas Stienen committed
263
		case CVAStructValue::SAMPLEBUFFER:
264 265
		{
			ss << margin << cit->first << " = [samplebuffer: " << cit->second.ToString() << " samples]" << std::endl;
266
			break;
267
		}
Jonas Stienen's avatar
Jonas Stienen committed
268 269 270 271 272 273 274 275 276
		}
	}

	return ss.str();
}

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

// Constructors
277 278 279 280 281 282 283
CVAStructValue::CVAStructValue() : iDatatype( UNASSIGNED ), pStruct( NULL ) {};
CVAStructValue::CVAStructValue( const bool value ) : iDatatype( BOOL ), bValue( value ), pStruct( NULL ) {};
CVAStructValue::CVAStructValue( const int value ) : iDatatype( INT ), iValue( value ), pStruct( NULL ) {};
CVAStructValue::CVAStructValue( const double value ) : iDatatype( DOUBLE ), dValue( value ), pStruct( NULL ) {};
CVAStructValue::CVAStructValue( const char* value ) : iDatatype( STRING ), sValue( value ), pStruct( NULL ) {};
CVAStructValue::CVAStructValue( const std::string& value ) : iDatatype( STRING ), sValue( value ), pStruct( NULL ) {};
CVAStructValue::CVAStructValue( const CVAStruct& value ) : iDatatype( STRUCT ), pStruct( new CVAStruct( value ) ) {};
284 285 286

CVAStructValue::CVAStructValue( void* pData, const int iBytes )
	: iDatatype( DATA )
287
	, pStruct( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
288
{
289
	SetData( pData, iBytes );
Jonas Stienen's avatar
Jonas Stienen committed
290 291
}

292 293 294
CVAStructValue::CVAStructValue( const CVASampleBuffer& oSampleBuffer )
	: iDatatype( SAMPLEBUFFER )
	, sbValue( oSampleBuffer )
Jonas Stienen's avatar
Jonas Stienen committed
295 296
{}

297 298
CVAStructValue::CVAStructValue( const CVAStructValue& rhs )
	: iDatatype( UNASSIGNED )
299
	, pStruct( NULL )
Jonas Stienen's avatar
Jonas Stienen committed
300 301 302 303 304 305
{
	*this = rhs;
}

CVAStructValue::~CVAStructValue()
{
306
	delete pStruct;
Jonas Stienen's avatar
Jonas Stienen committed
307 308
}

309 310
int CVAStructValue::GetDatatype() const
{
Jonas Stienen's avatar
Jonas Stienen committed
311 312 313
	return iDatatype;
}

314 315
int CVAStructValue::GetDataSize() const
{
Jonas Stienen's avatar
Jonas Stienen committed
316 317 318
	return iDataSize;
}

319 320 321 322 323 324
const void* CVAStructValue::GetData() const
{
	if( iDatatype != DATA )
		VA_EXCEPT1( "Key value is no binary data" );

	return &( vcData[ 0 ] );
Jonas Stienen's avatar
Jonas Stienen committed
325 326
}

327 328 329 330 331 332
void* CVAStructValue::GetData()
{
	if( iDatatype != DATA )
		VA_EXCEPT1( "Key value is no binary data" );

	return &( vcData[ 0 ] );
Jonas Stienen's avatar
Jonas Stienen committed
333 334
}

335 336
void CVAStructValue::SetData( const void* pIncomingData, const int iIncomingBytes )
{
337
	assert( iDatatype == DATA );
Jonas Stienen's avatar
Jonas Stienen committed
338

339 340 341 342
	if( iDatatype != DATA )
		return;

	if( pIncomingData == NULL )
343
	{
344
		assert( iIncomingBytes == 0 );
345
	}
346 347
	else
	{
348
		assert( iIncomingBytes > 0 );
Jonas Stienen's avatar
Jonas Stienen committed
349 350 351
	}

	// Free previous data
352
	vcData.clear();
Jonas Stienen's avatar
Jonas Stienen committed
353 354

	// Allocate new buffer and copy the data
355
	if( pIncomingData )
356
	{
357 358 359 360 361 362 363 364
		if( vcData.size() < iIncomingBytes )
			vcData.resize( iIncomingBytes );

		iDataSize = iIncomingBytes;
		//for( size_t i = 0; i < vcData.size(); i++ )
		//vcData[ i ] = pData[ i ];

		memcpy( GetData(), pIncomingData, iIncomingBytes );
Jonas Stienen's avatar
Jonas Stienen committed
365 366 367
	}
}

368 369
const CVAStruct& CVAStructValue::GetStruct() const
{
370
	if( iDatatype != STRUCT )
371
		VA_EXCEPT1( "Key value is not a structure" );
372 373
	assert( pStruct );
	return *pStruct;
Jonas Stienen's avatar
Jonas Stienen committed
374 375
}

376 377
CVAStruct& CVAStructValue::GetStruct()
{
378
	if( iDatatype != STRUCT )
379
		VA_EXCEPT1( "Key value is not a structure" );
380 381
	assert( pStruct );
	return *pStruct;
Jonas Stienen's avatar
Jonas Stienen committed
382 383
}

384 385 386
bool CVAStructValue::IsAssigned() const
{
	return ( iDatatype != UNASSIGNED );
Jonas Stienen's avatar
Jonas Stienen committed
387 388
}

389 390 391
bool CVAStructValue::IsBool() const
{
	return ( iDatatype == BOOL );
Jonas Stienen's avatar
Jonas Stienen committed
392 393
}

394 395 396
bool CVAStructValue::IsInt() const
{
	return ( iDatatype == INT );
Jonas Stienen's avatar
Jonas Stienen committed
397 398
}

399 400 401
bool CVAStructValue::IsDouble() const
{
	return ( iDatatype == DOUBLE );
Jonas Stienen's avatar
Jonas Stienen committed
402 403
}

404 405 406
bool CVAStructValue::IsString() const
{
	return ( iDatatype == STRING );
Jonas Stienen's avatar
Jonas Stienen committed
407 408
}

409 410 411
bool CVAStructValue::IsStruct() const
{
	return ( iDatatype == STRUCT );
Jonas Stienen's avatar
Jonas Stienen committed
412 413
}

414 415 416
bool CVAStructValue::IsNumeric() const
{
	return ( ( iDatatype == INT ) || ( iDatatype == DOUBLE ) );
Jonas Stienen's avatar
Jonas Stienen committed
417 418
}

419 420 421
bool CVAStructValue::IsData() const
{
	return ( iDatatype == DATA );
Jonas Stienen's avatar
Jonas Stienen committed
422 423 424 425
}

bool CVAStructValue::IsSampleBuffer() const
{
426
	return ( iDatatype == SAMPLEBUFFER );
Jonas Stienen's avatar
Jonas Stienen committed
427 428
}

429 430
CVAStructValue& CVAStructValue::operator=( const CVAStructValue& rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
431
	// Take care of self-assignment!
432 433
	if( this == &rhs )
		return *this;
Jonas Stienen's avatar
Jonas Stienen committed
434

435 436
	// Free associated struct first
	delete pStruct;
Jonas Stienen's avatar
Jonas Stienen committed
437
	iDataSize = 0;
438

Jonas Stienen's avatar
Jonas Stienen committed
439 440
	// Fast assignment. Copy only what is necessary ...
	iDatatype = rhs.iDatatype;
441 442
	switch( iDatatype )
	{
Jonas Stienen's avatar
Jonas Stienen committed
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
	case BOOL:
		bValue = rhs.bValue;
		break;

	case INT:
		iValue = rhs.iValue;
		break;

	case DOUBLE:
		dValue = rhs.dValue;
		break;

	case STRING:
		sValue = rhs.sValue;
		break;

	case STRUCT:
		// Autonome Kopie der Schssel Struktur erzeugen
461
		pStruct = new CVAStruct( *rhs.pStruct );
Jonas Stienen's avatar
Jonas Stienen committed
462 463 464 465
		break;

	case DATA:
		// Autonome Kopie des Schssel BLOBs erzeugen
466
		SetData( rhs.GetData(), rhs.iDataSize );
Jonas Stienen's avatar
Jonas Stienen committed
467 468 469 470 471 472 473 474 475 476
		break;

	case SAMPLEBUFFER:
		sbValue = rhs.sbValue;
		break;
	}

	return *this;
}

477 478
CVAStructValue& CVAStructValue::operator=( const bool rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
479 480 481 482 483
	iDatatype = BOOL;
	bValue = rhs;
	return *this;
}

484 485
CVAStructValue& CVAStructValue::operator=( const int rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
486 487 488 489 490
	iDatatype = INT;
	iValue = rhs;
	return *this;
}

491 492
CVAStructValue& CVAStructValue::operator=( const double rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
493 494 495 496 497
	iDatatype = DOUBLE;
	dValue = rhs;
	return *this;
}

498 499
CVAStructValue& CVAStructValue::operator=( const char* rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
500
	iDatatype = STRING;
501
	sValue = std::string( rhs );
Jonas Stienen's avatar
Jonas Stienen committed
502 503 504
	return *this;
}

505 506
CVAStructValue& CVAStructValue::operator=( const std::string& rhs )
{
Jonas Stienen's avatar
Jonas Stienen committed
507 508 509 510 511
	iDatatype = STRING;
	sValue = rhs;
	return *this;
}

512
CVAStructValue& CVAStructValue::operator=( const CVASampleBuffer& rhs )
Jonas Stienen's avatar
Jonas Stienen committed
513 514 515 516 517 518
{
	iDatatype = SAMPLEBUFFER;
	sbValue = rhs;
	return *this;
}

519
const CVAStructValue& CVAStructValue::operator[]( const char* pcKey ) const
520
{
521 522
	if( !IsStruct() )
		VA_EXCEPT1( "Key is not a structure" );
523
	return ( *pStruct )[ pcKey ];
Jonas Stienen's avatar
Jonas Stienen committed
524 525
}

526
CVAStructValue& CVAStructValue::operator[]( const char* pcKey )
527
{
528 529
	if( !IsStruct() )
		VA_EXCEPT1( "Key is not a structure" );
530
	return ( *pStruct )[ pcKey ];
Jonas Stienen's avatar
Jonas Stienen committed
531 532
}

533 534 535 536
CVAStructValue::operator bool() const
{
	switch( iDatatype )
	{
Jonas Stienen's avatar
Jonas Stienen committed
537 538 539 540 541 542
	case BOOL:
		// bool = Key[bool] obligatory.
		return bValue;

	case INT:
		// bool = Key[int] is allowed. Default semantic like in C/C++ (false == 0).
543
		return ( iValue != 0 );
Jonas Stienen's avatar
Jonas Stienen committed
544 545 546

	case DOUBLE:
		// bool = Key[double] is imprecise and but not forbidden. Same is for int.
547
		return ( dValue != 0 );
Jonas Stienen's avatar
Jonas Stienen committed
548 549 550

	case STRING:
		// bool = Key[string] may be possible.
551
	{
552 553 554 555
		std::string s( sValue );
		std::transform( s.begin(), s.end(), s.begin(), ( int( *)( int ) ) ::toupper );
		if( ( s == "no" ) || ( s == "false" ) )
			return false;
556
		if( ( s == "yes" ) || ( s == "true" ) )
557
			return true;
558
	}
Jonas Stienen's avatar
Jonas Stienen committed
559

560
	VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" cannot be interpreted as an logical value" ) );
Jonas Stienen's avatar
Jonas Stienen committed
561 562

	case SAMPLEBUFFER:
563
		return ( sbValue.GetNumSamples() > 0 );
Jonas Stienen's avatar
Jonas Stienen committed
564 565
	case STRUCT:
		// bool = Key[struct] is not possible.
566
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
567 568 569

	case UNASSIGNED:
		// Key is unassigned
570
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
571 572 573
	}

	// Invalid datatype.
574
	assert( false );
Jonas Stienen's avatar
Jonas Stienen committed
575 576 577 578
	return false;
}

//! Cast to int operator (required for assignments of the form 'int = Key')
579 580 581 582
CVAStructValue::operator int() const
{
	switch( iDatatype )
	{
Jonas Stienen's avatar
Jonas Stienen committed
583 584 585 586 587 588 589 590 591 592
	case BOOL:
		// int = Key[bool] allowed. Results in 0 or 1.
		return iValue;

	case INT:
		// int = Key[int] obligatory.
		return iValue;

	case DOUBLE:
		// int = Key[double] is dangerous (loss of precision) and but not forbidden.
593
		return ( int ) dValue;
Jonas Stienen's avatar
Jonas Stienen committed
594 595 596

	case STRING:
		// int = Key[string] may be possible.
597
	{
598
		std::istringstream ss( sValue );
599
		int i;
600
		if( !( ss >> i ).fail() )
601 602
			return i;
		else
603
			VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" cannot be interpreted as an integer number" ) );
604
	}
Jonas Stienen's avatar
Jonas Stienen committed
605 606 607

	case STRUCT:
		// int = Key[struct] is not possible.
608
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
609 610 611

	case UNASSIGNED:
		// Key is unassigned
612
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
613 614 615
	}

	// Invalid datatype.
616
	assert( false );
Jonas Stienen's avatar
Jonas Stienen committed
617 618 619 620
	return 0;
}

//! Cast to double operator (required for assignments of the form 'double = Key')
621 622 623 624
CVAStructValue::operator double() const
{
	switch( iDatatype )
	{
Jonas Stienen's avatar
Jonas Stienen committed
625 626
	case BOOL:
		// double = Key[bool] allowed. Results in 0 or 1.
627
		return ( bValue ? 1 : 0 );
Jonas Stienen's avatar
Jonas Stienen committed
628 629 630

	case INT:
		// double = Key[int] is valid.
631
		return ( double ) iValue;
Jonas Stienen's avatar
Jonas Stienen committed
632 633 634 635 636 637 638 639

	case DOUBLE:
		// double = Key[double] obligatory.
		return dValue;

	case STRING:
		// double = Key[string] may be possible.
		// int = Key[string] may be possible.
640
	{
641
		std::istringstream ss( sValue );
642
		double d;
643
		if( !( ss >> d ).fail() )
644 645
			return d;
		else
646
			VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" cannot be interpreted as a number" ) );
647
	}
Jonas Stienen's avatar
Jonas Stienen committed
648 649 650

	case STRUCT:
		// double = Key[struct] is not possible.
651
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
652 653 654 655

	case UNASSIGNED:
		// Key is unassigned
		//VA_EXCEPT1("Key does not exist");
656
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
657 658 659
	}

	// Invalid datatype.
660
	assert( false );
Jonas Stienen's avatar
Jonas Stienen committed
661 662 663 664
	return 0;
}

//! Cast to std::string operator (required for assignments of the form 'std::string = Key')
665 666 667 668
CVAStructValue::operator std::string() const
{
	switch( iDatatype )
	{
Jonas Stienen's avatar
Jonas Stienen committed
669 670
	case BOOL:
		// std::string = Key[bool] allowed. Implicit conversion.
671
		return ( bValue ? "true" : "false" );
Jonas Stienen's avatar
Jonas Stienen committed
672 673

	case INT:
674 675 676 677 678 679
	{
		// std::string = Key[int] allowed. Implicit conversion.
		std::stringstream ss;
		ss << iValue;
		return ss.str();
	}
Jonas Stienen's avatar
Jonas Stienen committed
680 681

	case DOUBLE:
682 683 684 685 686 687
	{
		// std::string = Key[double] allowed. Implicit conversion.
		std::stringstream ss;
		ss << dValue;
		return ss.str();
	}
Jonas Stienen's avatar
Jonas Stienen committed
688 689 690 691 692 693 694

	case STRING:
		// std::string = Key[string] obligatory.
		return sValue;

	case STRUCT:
		// std::string = Key[struct] is not possible.
695
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
696 697 698

	case UNASSIGNED:
		// Key is unassigned
699
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
700 701 702
	}

	// Invalid datatype.
703
	assert( false );
Jonas Stienen's avatar
Jonas Stienen committed
704 705 706
	return "";
}

707 708
CVAStructValue::operator void*( ) const
{
Jonas Stienen's avatar
Jonas Stienen committed
709 710
	// Note: Assignment only allowed for data keys!

711 712
	if( iDatatype == UNASSIGNED )
	{
Jonas Stienen's avatar
Jonas Stienen committed
713
		// Key is unassigned
714
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
715 716
	}

717 718
	if( iDatatype != DATA )
	{
Jonas Stienen's avatar
Jonas Stienen committed
719
		// Key is unassigned
720
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
721 722
	}

723
	return ( void* ) GetData();
Jonas Stienen's avatar
Jonas Stienen committed
724 725
}

726
CVAStructValue::operator const CVASampleBuffer&( ) const
Jonas Stienen's avatar
Jonas Stienen committed
727
{
728 729
	if( iDatatype == UNASSIGNED )
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
730

731 732
	if( iDatatype != SAMPLEBUFFER )
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
733 734 735 736

	return sbValue;
}

737
CVAStructValue::operator CVASampleBuffer&( )
Jonas Stienen's avatar
Jonas Stienen committed
738
{
739 740
	if( iDatatype == UNASSIGNED )
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
741

742 743
	if( iDatatype != SAMPLEBUFFER )
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
744 745 746 747

	return sbValue;
}

748 749 750 751
CVAStructValue::operator const CVAStruct&( ) const
{
	if( iDatatype == UNASSIGNED )
	{
Jonas Stienen's avatar
Jonas Stienen committed
752
		// Key is unassigned
753
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
754 755
	}

756 757
	if( iDatatype != STRUCT )
	{
Jonas Stienen's avatar
Jonas Stienen committed
758
		// Key is unassigned
759
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
760 761
	}

762
	return *pStruct;
Jonas Stienen's avatar
Jonas Stienen committed
763 764
}

765 766 767 768
CVAStructValue::operator CVAStruct&( )
{
	if( iDatatype == UNASSIGNED )
	{
Jonas Stienen's avatar
Jonas Stienen committed
769
		// Key is unassigned
770
		VA_EXCEPT1( std::string( "Key \"" ) + ( *psKey ) + std::string( "\" does not exist" ) );
Jonas Stienen's avatar
Jonas Stienen committed
771 772
	}

773 774
	if( iDatatype != STRUCT )
	{
Jonas Stienen's avatar
Jonas Stienen committed
775
		// Key is unassigned
776
		VA_EXCEPT1( "Types cannot be converted" );
Jonas Stienen's avatar
Jonas Stienen committed
777 778
	}

779
	return *pStruct;
Jonas Stienen's avatar
Jonas Stienen committed
780 781
}

782 783
std::string CVAStructValue::ToString() const
{
Jonas Stienen's avatar
Jonas Stienen committed
784 785 786
	std::stringstream ss;

	// Just output the value, not name and type
787
	switch( iDatatype )
Jonas Stienen's avatar
Jonas Stienen committed
788 789
	{
	case BOOL:
790
		return ( bValue ? "TRUE" : "FALSE" );
Jonas Stienen's avatar
Jonas Stienen committed
791 792 793 794 795 796 797 798 799 800 801 802 803

	case INT:
		ss << iValue;
		break;

	case DOUBLE:
		ss << dValue;
		break;

	case STRING:
		return sValue;

	case STRUCT:
804
		return pStruct->ToString();
Jonas Stienen's avatar
Jonas Stienen committed
805 806 807 808 809 810 811 812 813 814 815 816

	case SAMPLEBUFFER:
		ss << sbValue.GetNumSamples();
		break;

	case UNASSIGNED:
		return "";
	}

	return ss.str();
}

817 818
std::ostream& operator<<( std::ostream& os, const CVAStruct& s )
{
Jonas Stienen's avatar
Jonas Stienen committed
819 820 821
	return os << s.ToString();
}

822 823
std::ostream& operator<<( std::ostream& os, const CVAStructValue& key )
{
Jonas Stienen's avatar
Jonas Stienen committed
824 825
	return os << key.ToString();
}