VAStruct.h 8.77 KB
Newer Older
Jonas Stienen's avatar
Jonas Stienen committed
1
/*
2
 *  --------------------------------------------------------------------------------------------
Jonas Stienen's avatar
Jonas Stienen committed
3
 *
4 5 6 7 8 9
 *    VVV        VVV A           Virtual Acoustics (VA) | http://www.virtualacoustics.org
 *     VVV      VVV AAA          Licensed under the Apache License, Version 2.0
 *      VVV    VVV   AAA
 *       VVV  VVV     AAA        Copyright 2015-2017
 *        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 33 34 35

// 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
class VABASE_API compareStringCaseInsensitive
{
public:
36
	inline bool operator()( const std::string& a, const std::string& b ) const
Jonas Stienen's avatar
Jonas Stienen committed
37
	{
38 39 40
		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
41 42 43 44 45 46 47 48 49 50
		return la < lb;
	}
};

//! Associative array container
/**
 * 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
51 52
 * associative array. Keys names are case-insensitive.
 * The class features simple and effective use by defining
Jonas Stienen's avatar
Jonas Stienen committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
 * data access and cast operators.
 * It can be efficiently serialized/deserialized,
 * making it a suitable container for message mechanisms.
 */
class VABASE_API CVAStruct
{
public:
	// Type aliases
	typedef std::map< std::string, CVAStructValue, compareStringCaseInsensitive >::iterator iterator;
	typedef std::map< std::string, CVAStructValue, compareStringCaseInsensitive >::const_iterator const_iterator;

	// Literals
	const static char DEFAULT_PATH_SEPARATOR = '/';

	//! Default constructor
	CVAStruct();

	//! Copy constructor
71
	CVAStruct( const CVAStruct& );
Jonas Stienen's avatar
Jonas Stienen committed
72 73 74 75 76 77 78 79 80 81 82

	//! Destructor
	virtual ~CVAStruct();

	//! Returns the number of keys (elements)
	int Size() const;

	//! Returns if the container is empty
	bool IsEmpty() const;

	//! Returns if the given key exists
83
	bool HasKey( const std::string& sKey ) const;
Jonas Stienen's avatar
Jonas Stienen committed
84 85 86 87

	//! Deletes all keys
	void Clear();
	//! Removes a key and its value (supports paths)
88
	bool RemoveKey( const std::string& sKey );
Jonas Stienen's avatar
Jonas Stienen committed
89 90 91 92 93 94

	//! Return the pointer to a key  (read-only)
	/**
	 * The key can be specified either by a name or a path.
	 * In the latter case the method traverses through the structure.
	 *
95
	 * \note This functions never creates a non-existent key
Jonas Stienen's avatar
Jonas Stienen committed
96 97 98 99 100
	 * \note This functions is more complex than GetKey(const std::string&)
	 *
	 * \return Valid pointer, if the given key exists,
	 *         nullptr, otherwise
	 */
101
	const CVAStructValue* GetValue( const std::string& sPath, const char cPathSeparator = DEFAULT_PATH_SEPARATOR ) const;
Jonas Stienen's avatar
Jonas Stienen committed
102 103 104 105 106 107 108 109 110 111 112 113

	//! Return the pointer to a key (read-write)
	/**
	 * 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&)
	 *
	 * \return Valid pointer, if the given key exists,
	 *         nullptr, otherwise
	 */
114
	CVAStructValue* GetValue( const std::string& sPath, const char cPathSeparator = DEFAULT_PATH_SEPARATOR );
Jonas Stienen's avatar
Jonas Stienen committed
115 116

	//! Read-only data access
117
	const CVAStructValue& operator[]( const char* pcKey ) const;
118 119 120 121
	inline const CVAStructValue& operator[]( const std::string& sKey ) const
	{
		return ( *this )[ sKey.c_str() ]; 
	};
Jonas Stienen's avatar
Jonas Stienen committed
122 123

	//! Read/write data access
124
	CVAStructValue& operator[]( const char* pcKey );
125 126 127 128
	inline CVAStructValue& operator[]( const std::string& sKey )
	{
		return ( *this )[ sKey.c_str() ];
	};
Jonas Stienen's avatar
Jonas Stienen committed
129 130

	//! Assignment
131
	CVAStruct& operator=( const CVAStruct& rhs );
Jonas Stienen's avatar
Jonas Stienen committed
132 133 134 135 136 137 138 139

	//! Iterator pattern
	CVAStruct::iterator Begin();
	CVAStruct::const_iterator Begin() const;
	CVAStruct::iterator End();
	CVAStruct::const_iterator End() const;

	//! Merge struct with another one
140
	void Merge( const CVAStruct& rhs, const bool bUnique = true );
Jonas Stienen's avatar
Jonas Stienen committed
141 142

	//! Return a string representation of the container
143
	std::string ToString( const int iIndent = 0 ) const;
Jonas Stienen's avatar
Jonas Stienen committed
144 145 146 147 148 149 150
private:
	typedef std::map<std::string, CVAStructValue, compareStringCaseInsensitive> Map;
	typedef Map::const_iterator MapCit;
	typedef Map::iterator MapIt;
	Map m_mData;

	// Traversal methods
151 152
	const CVAStructValue* Traverse( const std::string& sPath, size_t iPathCursor = 0, const char cPathSeparator = DEFAULT_PATH_SEPARATOR ) const;
	CVAStructValue* Traverse( const std::string& sPath, size_t iPathCursor = 0, const char cPathSeparator = DEFAULT_PATH_SEPARATOR );
Jonas Stienen's avatar
Jonas Stienen committed
153 154 155 156 157 158 159 160 161 162 163
};

//! Associative array value class
/**
 * This class realized keys is the associative array CVAStruct
 */

class VABASE_API CVAStructValue
{
public:
	//! Key types
164 165 166 167
	enum KeyType
	{
		UNASSIGNED = -1,	//!< Uninitialized key without a type
		BOOL = 0,			//!< Boolean key
Jonas Stienen's avatar
Jonas Stienen committed
168 169 170 171 172 173 174 175 176 177 178 179
		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
180 181 182
	CVAStructValue( const bool value );
	CVAStructValue( const int value );
	CVAStructValue( const double value );
183 184 185
	CVAStructValue( const char* value );
	CVAStructValue( const std::string& value );
	CVAStructValue( const CVAStruct& value );
186
	CVAStructValue( void* pData, const int iBytes );
Jonas Stienen's avatar
Jonas Stienen committed
187 188 189
	CVAStructValue( const CVASampleBuffer& );

	//! Copy constructor
190
	CVAStructValue( const CVAStructValue& );
Jonas Stienen's avatar
Jonas Stienen committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

	//! Destructor
	virtual ~CVAStructValue();

	//! Returns the datatype of the key
	int GetDatatype() const;

	//! Returns the data size in bytes (only for datatype DATA)
	int GetDataSize() const;

	//! Returns a pointer to the data (only for datatype DATA)
	const void* GetData() const;
	void* GetData();

	//! Sets the data (only for datatype DATA)
206
	void SetData( void* pData, const int iBytes );
Jonas Stienen's avatar
Jonas Stienen committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

	//! Returns a pointer to the struct value (only for datatype STRUCT)
	const CVAStruct& GetStruct() const;
	CVAStruct& GetStruct();

	//! Test functions for datatypes
	bool IsAssigned() const; // Datatype has been assigned
	bool IsBool() const;
	bool IsInt() const;
	bool IsDouble() const;
	bool IsString() const;
	bool IsStruct() const;
	bool IsNumeric() const; // Int | Double
	bool IsData() const;
	bool IsSampleBuffer() const;

	//! Assignment operators
224
	CVAStructValue& operator=( const CVAStructValue& );
225 226 227
	CVAStructValue& operator=( const bool );
	CVAStructValue& operator=( const int );
	CVAStructValue& operator=( const double );
228 229
	CVAStructValue& operator=( const char* );
	CVAStructValue& operator=( const std::string& );
Jonas Stienen's avatar
Jonas Stienen committed
230 231 232 233
	CVAStructValue& operator=( const CVASampleBuffer& );

	//! Read-only data access
	// Note: Is applicable only for struct keys
234
	const CVAStructValue& operator[]( const char* pcKey ) const;
Jonas Stienen's avatar
Jonas Stienen committed
235 236 237

	//! Read/write data access
	// Note: Is applicable only for struct keys
238
	CVAStructValue& operator[]( const char* pcKey );
239 240 241 242
	inline CVAStructValue& operator[]( const std::string& sKey )
	{
		return ( *this )[ sKey.c_str() ];
	};
Jonas Stienen's avatar
Jonas Stienen committed
243 244 245 246 247 248 249 250 251 252 253 254

	//! 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;
255

Jonas Stienen's avatar
Jonas Stienen committed
256
	//! Cast to void pointer (required for assignments of the form 'void* = CVAStructKey')
257
	operator void*( ) const;
Jonas Stienen's avatar
Jonas Stienen committed
258 259

	//! Cast to sample buffer
260
	operator const CVASampleBuffer&( ) const;
Jonas Stienen's avatar
Jonas Stienen committed
261 262

	//! Cast to sample buffer
263
	operator CVASampleBuffer&( );
Jonas Stienen's avatar
Jonas Stienen committed
264 265

	//! Cast to CVAStruct (required for assignments of the form 'CVAStruct = CVAStructKey')
266 267
	operator const CVAStruct&( ) const;
	operator CVAStruct&( );
Jonas Stienen's avatar
Jonas Stienen committed
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

	//! Return a string representation of the key
	std::string ToString() const;

private:
	int iDatatype;
	const std::string* psKey;	// Back-reference to the keys name

	bool bValue;
	int iValue;
	double dValue;
	std::string sValue;
	CVAStruct* xValue;
	void* pData;
	int iDataSize;
	CVASampleBuffer sbValue;
284

Jonas Stienen's avatar
Jonas Stienen committed
285 286 287 288
	friend class CVAStruct;
};

//! STL stream output operator
289
VABASE_API std::ostream& operator<<( std::ostream& os, const CVAStruct& s );
Jonas Stienen's avatar
Jonas Stienen committed
290 291

//! STL stream output operator
292
VABASE_API std::ostream& operator<<( std::ostream& os, const CVAStructValue& key );
Jonas Stienen's avatar
Jonas Stienen committed
293

294
#endif // IW_VABASE_STRUCT