VAStruct.h 14.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-2018
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
 */

14 15
#ifndef IW_VABASE_STRUCT
#define IW_VABASE_STRUCT
Jonas Stienen's avatar
Jonas Stienen committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

// VA includes
#include <VABaseDefinitions.h>
#include <VASamples.h>

// STL includes
#include <algorithm>
#include <iterator>
#include <map>
#include <ostream>
#include <cstring>

// Forward declarations
class VABASE_API CVAStruct;
class VABASE_API CVAStructValue;

//! Case insensitive string comparison
33
class VABASE_API CompareStringCaseInsensitive
Jonas Stienen's avatar
Jonas Stienen committed
34 35
{
public:
36 37 38 39 40 41
	//! Compare operator
	/**
	  * @param[in] a Left-hand string
	  * @param[in] b Left-hand string
	  * @return True, if strings are equal (ignoring case)
	  */
42
	inline bool operator()( const std::string& a, const std::string& b ) const
Jonas Stienen's avatar
Jonas Stienen committed
43
	{
44 45 46
		std::string la( a ), lb( b );
		std::transform( la.begin(), la.end(), la.begin(), ::tolower );
		std::transform( lb.begin(), lb.end(), lb.begin(), ::tolower );
Jonas Stienen's avatar
Jonas Stienen committed
47
		return la < lb;
48
	};
Jonas Stienen's avatar
Jonas Stienen committed
49 50 51 52
};

//! Associative array container
/**
53 54 55 56 57 58 59 60 61 62
  * Associative array container, mapping a unique collection of
  * string keys to values. A variety of key values is supported,
  * for instance primitive types (bool, int, double, string).
  * Nesting is also supported by assigning keys another
  * associative array. Keys names are case-insensitive.
  * The class features simple and effective use by defining
  * data access and cast operators.
  * It can be efficiently serialized/deserialized,
  * making it a suitable container for message mechanisms.
  */
Jonas Stienen's avatar
Jonas Stienen committed
63 64 65 66
class VABASE_API CVAStruct
{
public:
	// Type aliases
67 68
	typedef std::map< std::string, CVAStructValue, CompareStringCaseInsensitive >::iterator iterator;
	typedef std::map< std::string, CVAStructValue, CompareStringCaseInsensitive >::const_iterator const_iterator;
Jonas Stienen's avatar
Jonas Stienen committed
69

70
	const static char DEFAULT_PATH_SEPARATOR = '/'; //!< Literals
Jonas Stienen's avatar
Jonas Stienen committed
71 72 73 74 75

	//! Default constructor
	CVAStruct();

	//! Copy constructor
76 77 78 79
	/**
	  * @param[in] oOther Other struct
	  */
	CVAStruct( const CVAStruct& oOther );
Jonas Stienen's avatar
Jonas Stienen committed
80 81 82 83 84

	//! Destructor
	virtual ~CVAStruct();

	//! Returns the number of keys (elements)
85 86 87
	/**
	  * @return Number of keys / elements
	  */
Jonas Stienen's avatar
Jonas Stienen committed
88 89 90
	int Size() const;

	//! Returns if the container is empty
91 92 93
	/**
	  * @return True, if there are no keys
	  */
Jonas Stienen's avatar
Jonas Stienen committed
94 95 96
	bool IsEmpty() const;

	//! Returns if the given key exists
97 98 99 100
	/**
	  * @param[in] sKey Key as string
	  * @return True, if key is present
	  */
101
	bool HasKey( const std::string& sKey ) const;
Jonas Stienen's avatar
Jonas Stienen committed
102 103 104

	//! Deletes all keys
	void Clear();
105

Jonas Stienen's avatar
Jonas Stienen committed
106
	//! Removes a key and its value (supports paths)
107 108 109 110
	/**
	  * @param[in] sKey Key as string
	  * @return True, if key could be removed
	  */
111
	bool RemoveKey( const std::string& sKey );
Jonas Stienen's avatar
Jonas Stienen committed
112 113 114

	//! Return the pointer to a key  (read-only)
	/**
115 116 117 118 119 120 121 122 123 124 125
	  * The key can be specified either by a name or a path.
	  * In the latter case the method traverses through the structure.
	  *
	  * @note This functions never creates a non-existent key
	  * @note This functions is more complex than GetKey(const std::string&)
	  *
	  * @param[in] sPath Path
	  * @param[in] cPathSeparator Path seperator, either "/" (default) or "\"
	  *
	  * @return Valid pointer, if the given key exists, nullptr otherwise
	  */
126
	const CVAStructValue* GetValue( const std::string& sPath, const char cPathSeparator = DEFAULT_PATH_SEPARATOR ) const;
Jonas Stienen's avatar
Jonas Stienen committed
127 128 129

	//! Return the pointer to a key (read-write)
	/**
130 131 132 133 134 135 136 137 138 139
	  * The key can be specified either by a name or a path.
	  * In the latter case the method traverses through the structure.
	  *
	  * @param[in] sPath Path
	  * @param[in] cPathSeparator Path seperator, either "/" (default) or "\"
	  * @note This functions never creates a non-existent key
	  * @note This functions is more complex than GetKey(const std::string&)
	  *
	  * @return Valid pointer, if the given key exists, nullptr otherwise
	  */
140
	CVAStructValue* GetValue( const std::string& sPath, const char cPathSeparator = DEFAULT_PATH_SEPARATOR );
Jonas Stienen's avatar
Jonas Stienen committed
141 142

	//! Read-only data access
143 144 145 146 147
	/**
	  * @param[in] pcKey Key as character pointer
	  * @return Struct value of this key
	  * @note Will raise CVAEception on error
	  */
148
	const CVAStructValue& operator[]( const char* pcKey ) const;
149 150 151 152 153 154 155

	//! Read-only data access
	/**
	  * @param[in] sKey Key as string
	  * @return Struct value of this key
	  * @note Will raise CVAEception on error
	  */
156 157
	inline const CVAStructValue& operator[]( const std::string& sKey ) const
	{
158
		return ( *this )[ sKey.c_str() ];
159
	};
Jonas Stienen's avatar
Jonas Stienen committed
160 161

	//! Read/write data access
162 163 164 165 166
	/**
	  * @param[in] pcKey Key as character pointer
	  * @return Struct value of this key
	  * @note Will raise CVAEception on error
	  */
167
	CVAStructValue& operator[]( const char* pcKey );
168 169 170 171 172 173 174

	//! Read/write data access
	/**
	  * @param[in] sKey Key as string
	  * @return Struct value of this key
	  * @note Will raise CVAEception on error
	  */
175 176 177 178
	inline CVAStructValue& operator[]( const std::string& sKey )
	{
		return ( *this )[ sKey.c_str() ];
	};
Jonas Stienen's avatar
Jonas Stienen committed
179 180

	//! Assignment
181 182 183 184
	/**
	  * @param[in] rhs Right hand side struct
	  * @return Assigned struct
	  */
185
	CVAStruct& operator=( const CVAStruct& rhs );
Jonas Stienen's avatar
Jonas Stienen committed
186

187 188 189 190
	//! Iterator pattern begin
	/**
	  * @return Iterator beginning
	  */
Jonas Stienen's avatar
Jonas Stienen committed
191
	CVAStruct::iterator Begin();
192 193 194 195 196

	//! Const iterator pattern begin
	/**
	  * @return Const iterator beginning
	  */
Jonas Stienen's avatar
Jonas Stienen committed
197
	CVAStruct::const_iterator Begin() const;
198 199 200 201 202

	//! Iterator pattern end
	/**
	  * @return Const iterator end
	  */
Jonas Stienen's avatar
Jonas Stienen committed
203
	CVAStruct::iterator End();
204 205 206 207 208

	//! Const iterator pattern end
	/**
	  * @return Const iterator end
	  */
Jonas Stienen's avatar
Jonas Stienen committed
209 210 211
	CVAStruct::const_iterator End() const;

	//! Merge struct with another one
212 213 214 215
	/**
	  * @param[in] rhs Right hand side struct where to merge from
	  * @param[in] bUnique Raise exception in case uniqueness is violated
	  */
216
	void Merge( const CVAStruct& rhs, const bool bUnique = true );
Jonas Stienen's avatar
Jonas Stienen committed
217 218

	//! Return a string representation of the container
219 220 221 222
	/**
	  * @param[in] iIndent Indentation for printing
	  * @return Formatted string
	  */
223
	std::string ToString( const int iIndent = 0 ) const;
Jonas Stienen's avatar
Jonas Stienen committed
224
private:
225 226 227 228 229
	typedef std::map<std::string, CVAStructValue, CompareStringCaseInsensitive> Map; //!< Key-value map typedef
	typedef Map::const_iterator MapCit; //!< Map const iterator typedef
	typedef Map::iterator MapIt; //!< Map iterator typedef

	Map m_mData; //!< Internal key-value data map
Jonas Stienen's avatar
Jonas Stienen committed
230

231 232 233 234 235 236 237
	//! Traversal methods for read-only access
	/**
	  * @param[in] sPath Path
	  * @param[in] iPathCursor Path cursor
	  * @param[in] cPathSeparator Path separator
	  * @return Pointer to struct value
	  */
238
	const CVAStructValue* Traverse( const std::string& sPath, size_t iPathCursor = 0, const char cPathSeparator = DEFAULT_PATH_SEPARATOR ) const;
239 240 241 242 243 244 245 246

	//! Traversal methods
	/**
	  * @param[in] sPath Path
	  * @param[in] iPathCursor Path cursor
	  * @param[in] cPathSeparator Path separator
	  * @return Pointer to struct value
	  */
247
	CVAStructValue* Traverse( const std::string& sPath, size_t iPathCursor = 0, const char cPathSeparator = DEFAULT_PATH_SEPARATOR );
Jonas Stienen's avatar
Jonas Stienen committed
248 249 250 251
};

//! Associative array value class
/**
252 253
  * This class realized keys is the associative array CVAStruct
  */
Jonas Stienen's avatar
Jonas Stienen committed
254 255 256 257
class VABASE_API CVAStructValue
{
public:
	//! Key types
258 259 260 261
	enum KeyType
	{
		UNASSIGNED = -1,	//!< Uninitialized key without a type
		BOOL = 0,			//!< Boolean key
Jonas Stienen's avatar
Jonas Stienen committed
262 263 264 265 266 267 268 269 270 271 272 273
		INT,			//!< Integer key
		DOUBLE,			//!< Double-precision floating-point key
		STRING,			//!< String key
		STRUCT,			//!< Associative array key (CVAStruct key)
		DATA,			//!< Binary data (BLOB)
		SAMPLEBUFFER,	//!< VA sample buffer
	};

	//! Default constructor. Creates an uninitialized key without a type
	CVAStructValue();

	//! Initialization constructors
274 275 276
	/**
	  * @param[in] value Value as bool
	  */
277
	CVAStructValue( const bool value );
278 279 280 281 282

	//! Initialization constructors
	/**
	  * @param[in] value Value as int
	  */
283
	CVAStructValue( const int value );
284 285 286 287 288

	//! Initialization constructors
	/**
	  * @param[in] value Value as double
	  */
289
	CVAStructValue( const double value );
290 291 292 293 294

	//! Initialization constructors
	/**
	  * @param[in] value Value as character pointer
	  */
295
	CVAStructValue( const char* value );
296 297 298 299 300

	//! Initialization constructors
	/**
	  * @param[in] value Value as string
	  */
301
	CVAStructValue( const std::string& value );
302 303 304 305 306

	//! Initialization constructors
	/**
	  * @param[in] value Value as another struct (nested object)
	  */
307
	CVAStructValue( const CVAStruct& value );
308 309 310 311 312 313

	//! Initialization constructors
	/**
	  * @param[in] pData Value as byte array (data pointer)
	  * @param[in] iBytes Value byte count
	  */
314
	CVAStructValue( void* pData, const int iBytes );
315 316 317 318 319 320

	//! Initialization constructors
	/**
	  * @param[in] value Value
	  */
	CVAStructValue( const CVASampleBuffer& value );
Jonas Stienen's avatar
Jonas Stienen committed
321 322

	//! Copy constructor
323 324 325 326
	/**
	  * @param[in] oOther Copy from struct value
	  */
	CVAStructValue( const CVAStructValue& oOther );
Jonas Stienen's avatar
Jonas Stienen committed
327 328 329 330 331

	//! Destructor
	virtual ~CVAStructValue();

	//! Returns the datatype of the key
332 333 334
	/**
	  * @return Data type identifier
	  */
Jonas Stienen's avatar
Jonas Stienen committed
335 336 337
	int GetDatatype() const;

	//! Returns the data size in bytes (only for datatype DATA)
338 339 340
	/**
	  * @return Data size number (bytes)
	  */
Jonas Stienen's avatar
Jonas Stienen committed
341 342 343
	int GetDataSize() const;

	//! Returns a pointer to the data (only for datatype DATA)
344 345 346
	/**
	  * @return Generic pointer in data (read-only)
	  */
Jonas Stienen's avatar
Jonas Stienen committed
347
	const void* GetData() const;
348 349 350 351 352

	//! Returns a pointer to the data (only for datatype DATA)
	/**
	  * @return Generic pointer in data
	  */
Jonas Stienen's avatar
Jonas Stienen committed
353 354 355
	void* GetData();

	//! Sets the data (only for datatype DATA)
356 357 358 359
	/**
	  * @param[in] pData Data pointer
	  * @param[in] iBytes Number of bytes
	  */
360
	void SetData( void* pData, const int iBytes );
Jonas Stienen's avatar
Jonas Stienen committed
361 362

	//! Returns a pointer to the struct value (only for datatype STRUCT)
363 364 365
	/**
	  * @return Struct value read-only
	  */
Jonas Stienen's avatar
Jonas Stienen committed
366
	const CVAStruct& GetStruct() const;
367 368 369 370 371

	//! Returns a const pointer to the struct value (only for datatype STRUCT)
	/**
	  * @return Struct value
	  */
Jonas Stienen's avatar
Jonas Stienen committed
372 373 374
	CVAStruct& GetStruct();

	//! Test functions for datatypes
375 376 377 378 379 380 381 382 383
	/**
	  * @return True, if data type has been assigned
	  */
	bool IsAssigned() const;

	//! Data type is boolean
	/**
	  * @return True, if type matches
	  */
Jonas Stienen's avatar
Jonas Stienen committed
384
	bool IsBool() const;
385 386 387 388 389

	//! Data type is integer
	/**
	  * @return True, if type matches
	  */
Jonas Stienen's avatar
Jonas Stienen committed
390
	bool IsInt() const;
391 392 393 394 395

	//! Data type is double
	/**
	  * @return True, if type matches
	  */
Jonas Stienen's avatar
Jonas Stienen committed
396
	bool IsDouble() const;
397 398 399 400 401

	//! Data type is string
	/**
	  * @return True, if type matches
	  */
Jonas Stienen's avatar
Jonas Stienen committed
402
	bool IsString() const;
403 404 405 406 407

	//! Data type is struct
	/**
	  * @return True, if type matches
	  */
Jonas Stienen's avatar
Jonas Stienen committed
408
	bool IsStruct() const;
409 410 411 412 413 414 415 416 417 418 419

	//! Data type is integer or double
	/**
	  * @return True, if type matches
	  */
	bool IsNumeric() const;

	//! Data type is data
	/**
	  * @return True, if type matches
	  */
Jonas Stienen's avatar
Jonas Stienen committed
420
	bool IsData() const;
421 422 423 424 425

	//! Data type is sample buffer
	/**
	  * @return True, if type matches
	  */
Jonas Stienen's avatar
Jonas Stienen committed
426 427
	bool IsSampleBuffer() const;

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
	//! Assignment operators for type struct value
	/**
	  * @param[in] v Value as struct
	  * @return Struct value
	  */
	CVAStructValue& operator=( const CVAStructValue& v );

	//! Assignment operators for type bool value
	/**
	  * @param[in] v Value as bool
	  * @return Struct value
	  */
	CVAStructValue& operator=( const bool v );

	//! Assignment operators for type int value
	/**
	  * @param[in] v Value as int
	  * @return Struct value
	  */
	CVAStructValue& operator=( const int v );

	//! Assignment operators for type double value
	/**
	  * @param[in] v Value as double
	  * @return Struct value
	  */
	CVAStructValue& operator=( const double v );

	//! Assignment operators for type character pointer value
	/**
	  * @param[in] v Value as character pointer
	  * @return Struct value
	  */
	CVAStructValue& operator=( const char* v );

	//! Assignment operators for type string value
	/**
	  * @param[in] v Value as string
	  * @return Struct value
	  */
	CVAStructValue& operator=( const std::string& v );

	//! Assignment operators for type sample buffer value
	/**
	  * @param[in] v Value as sample buffer
	  * @return Struct value
	  */
	CVAStructValue& operator=( const CVASampleBuffer& v );
Jonas Stienen's avatar
Jonas Stienen committed
476 477

	//! Read-only data access
478 479 480 481 482
	/**
	  * @note Is applicable only for struct keys. Also raises CVAException on error.
	  * @param[in] pcKey Key as char pointer
	  * @return Struct value
	  */
483
	const CVAStructValue& operator[]( const char* pcKey ) const;
Jonas Stienen's avatar
Jonas Stienen committed
484 485

	//! Read/write data access
486 487 488 489 490
	/**
	  * @note Is applicable only for struct keys. Also raises CVAException on error.
	  * @param[in] pcKey Key as char pointer
	  * @return Struct value
	  */
491
	CVAStructValue& operator[]( const char* pcKey );
492 493 494 495 496 497 498 499
	
	//! Read/write data access via string key
	/**
	  * @note Is applicable only for struct keys. Also raises CVAException on error.
	  }
	  * @param[in] sKey Key as string
	  * @return Struct value
	  */
500 501 502 503
	inline CVAStructValue& operator[]( const std::string& sKey )
	{
		return ( *this )[ sKey.c_str() ];
	};
Jonas Stienen's avatar
Jonas Stienen committed
504 505 506 507 508 509 510 511 512 513 514 515

	//! Cast to bool operator (required for assignments of the form 'bool = CVAStructKey')
	operator bool() const;

	//! Cast to int operator (required for assignments of the form 'int = CVAStructKey')
	operator int() const;

	//! Cast to double operator (required for assignments of the form 'double = CVAStructKey')
	operator double() const;

	//! Cast to std::string operator (required for assignments of the form 'std::string = CVAStructKey')
	operator std::string() const;
516

Jonas Stienen's avatar
Jonas Stienen committed
517
	//! Cast to void pointer (required for assignments of the form 'void* = CVAStructKey')
518
	operator void*( ) const;
Jonas Stienen's avatar
Jonas Stienen committed
519 520

	//! Cast to sample buffer
521
	operator const CVASampleBuffer&( ) const;
Jonas Stienen's avatar
Jonas Stienen committed
522 523

	//! Cast to sample buffer
524
	operator CVASampleBuffer&( );
Jonas Stienen's avatar
Jonas Stienen committed
525

526
	//! Cast to const CVAStruct (required for assignments of the form 'CVAStruct = CVAStructKey')
527
	operator const CVAStruct&( ) const;
528 529

	//! Cast to CVAStruct (required for assignments of the form 'CVAStruct = CVAStructKey')
530
	operator CVAStruct&( );
Jonas Stienen's avatar
Jonas Stienen committed
531 532

	//! Return a string representation of the key
533 534 535
	/**
	  * @return Formatted string
	  */
Jonas Stienen's avatar
Jonas Stienen committed
536 537 538
	std::string ToString() const;

private:
539 540 541 542 543 544 545 546 547 548 549
	int iDatatype; //!< Data type
	const std::string* psKey;	//!< Back-reference to the keys name

	bool bValue; //!< Value if type is bool
	int iValue; //!< Value if type is int
	double dValue; //!< Value if type is double
	std::string sValue; //!< Value if type is string
	CVAStruct* xValue; //!< Value if type is struct
	void* pData; //!< Value if type is data
	int iDataSize; //!< Value byte number if type is data
	CVASampleBuffer sbValue; //!< Value if type is sample buffer
550

Jonas Stienen's avatar
Jonas Stienen committed
551 552 553 554
	friend class CVAStruct;
};

//! STL stream output operator
555 556 557 558 559
/**
  * @param[in] os Outstream object
  * @param[in] s Struct value
  * @return Outstream with info attached
  */
560
VABASE_API std::ostream& operator<<( std::ostream& os, const CVAStruct& s );
Jonas Stienen's avatar
Jonas Stienen committed
561 562

//! STL stream output operator
563 564 565 566 567
/**
  * @param[in] os Outstream object
  * @param[in] key Struct value read-only
  * @return Outstream with info attached
  */
568
VABASE_API std::ostream& operator<<( std::ostream& os, const CVAStructValue& key );
Jonas Stienen's avatar
Jonas Stienen committed
569

570
#endif // IW_VABASE_STRUCT