1/*
2---------------------------------------------------------------------------
3Open Asset Import Library (assimp)
4---------------------------------------------------------------------------
5
6Copyright (c) 2006-2017, assimp team
7
8
9All rights reserved.
10
11Redistribution and use of this software in source and binary forms,
12with or without modification, are permitted provided that the following
13conditions are met:
14
15* Redistributions of source code must retain the above
16 copyright notice, this list of conditions and the
17 following disclaimer.
18
19* Redistributions in binary form must reproduce the above
20 copyright notice, this list of conditions and the
21 following disclaimer in the documentation and/or other
22 materials provided with the distribution.
23
24* Neither the name of the assimp team, nor the names of its
25 contributors may be used to endorse or promote products
26 derived from this software without specific prior
27 written permission of the assimp team.
28
29THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40---------------------------------------------------------------------------
41*/
42
43/** @file metadata.h
44 * @brief Defines the data structures for holding node meta information.
45 */
46#pragma once
47#ifndef AI_METADATA_H_INC
48#define AI_METADATA_H_INC
49
50#if defined(_MSC_VER) && (_MSC_VER <= 1500)
51# include "Compiler/pstdint.h"
52#else
53# include <stdint.h>
54#endif
55
56// -------------------------------------------------------------------------------
57/**
58 * Enum used to distinguish data types
59 */
60 // -------------------------------------------------------------------------------
61typedef enum aiMetadataType {
62 AI_BOOL = 0,
63 AI_INT32 = 1,
64 AI_UINT64 = 2,
65 AI_FLOAT = 3,
66 AI_DOUBLE = 4,
67 AI_AISTRING = 5,
68 AI_AIVECTOR3D = 6,
69
70#ifndef SWIG
71 FORCE_32BIT = INT_MAX
72#endif
73} aiMetadataType;
74
75// -------------------------------------------------------------------------------
76/**
77 * Metadata entry
78 *
79 * The type field uniquely identifies the underlying type of the data field
80 */
81 // -------------------------------------------------------------------------------
82struct aiMetadataEntry {
83 aiMetadataType mType;
84 void* mData;
85};
86
87#ifdef __cplusplus
88
89#include <string>
90
91// -------------------------------------------------------------------------------
92/**
93 * Helper functions to get the aiType enum entry for a type
94 */
95 // -------------------------------------------------------------------------------
96
97inline aiMetadataType GetAiType( bool ) { return AI_BOOL; }
98inline aiMetadataType GetAiType( int32_t ) { return AI_INT32; }
99inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; }
100inline aiMetadataType GetAiType( float ) { return AI_FLOAT; }
101inline aiMetadataType GetAiType( double ) { return AI_DOUBLE; }
102inline aiMetadataType GetAiType( const aiString & ) { return AI_AISTRING; }
103inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
104
105#endif // __cplusplus
106
107// -------------------------------------------------------------------------------
108/**
109 * Container for holding metadata.
110 *
111 * Metadata is a key-value store using string keys and values.
112 */
113 // -------------------------------------------------------------------------------
114struct aiMetadata {
115 /** Length of the mKeys and mValues arrays, respectively */
116 unsigned int mNumProperties;
117
118 /** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
119 C_STRUCT aiString* mKeys;
120
121 /** Arrays of values, may not be NULL. Entries in this array may be NULL if the
122 * corresponding property key has no assigned value. */
123 C_STRUCT aiMetadataEntry* mValues;
124
125#ifdef __cplusplus
126
127 /**
128 * @brief The default constructor, set all members to zero by default.
129 */
130 aiMetadata()
131 : mNumProperties(0)
132 , mKeys(NULL)
133 , mValues(NULL) {
134 // empty
135 }
136
137 /**
138 * @brief The destructor.
139 */
140 ~aiMetadata() {
141 delete [] mKeys;
142 mKeys = NULL;
143 if (mValues) {
144 // Delete each metadata entry
145 for (unsigned i=0; i<mNumProperties; ++i) {
146 void* data = mValues[i].mData;
147 switch (mValues[i].mType) {
148 case AI_BOOL:
149 delete static_cast<bool*>(data);
150 break;
151 case AI_INT32:
152 delete static_cast<int32_t*>(data);
153 break;
154 case AI_UINT64:
155 delete static_cast<uint64_t*>(data);
156 break;
157 case AI_FLOAT:
158 delete static_cast<float*>(data);
159 break;
160 case AI_DOUBLE:
161 delete static_cast<double*>(data);
162 break;
163 case AI_AISTRING:
164 delete static_cast<aiString*>(data);
165 break;
166 case AI_AIVECTOR3D:
167 delete static_cast<aiVector3D*>(data);
168 break;
169#ifndef SWIG
170 case FORCE_32BIT:
171#endif
172 default:
173 break;
174 }
175 }
176
177 // Delete the metadata array
178 delete [] mValues;
179 mValues = NULL;
180 }
181 }
182
183 /**
184 * @brief Allocates property fields + keys.
185 * @param numProperties Number of requested properties.
186 */
187 static inline
188 aiMetadata *Alloc( unsigned int numProperties ) {
189 if ( 0 == numProperties ) {
190 return nullptr;
191 }
192
193 aiMetadata *data = new aiMetadata;
194 data->mNumProperties = numProperties;
195 data->mKeys = new aiString[ data->mNumProperties ]();
196 data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
197
198 return data;
199 }
200
201 /**
202 * @brief Deallocates property fields + keys.
203 */
204 static inline
205 void Dealloc( aiMetadata *metadata ) {
206 delete metadata;
207 }
208
209 template<typename T>
210 inline void Add(const std::string& key, const T& value)
211 {
212 aiString* new_keys = new aiString[mNumProperties + 1];
213 aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
214
215 for(unsigned int i = 0; i < mNumProperties; ++i)
216 {
217 new_keys[i] = mKeys[i];
218 new_values[i] = mValues[i];
219 }
220
221 delete mKeys;
222 delete mValues;
223
224 mKeys = new_keys;
225 mValues = new_values;
226
227 mNumProperties++;
228
229 Set(mNumProperties - 1, key, value);
230 }
231
232 template<typename T>
233 inline
234 bool Set( unsigned index, const std::string& key, const T& value ) {
235 // In range assertion
236 if ( index >= mNumProperties ) {
237 return false;
238 }
239
240 // Ensure that we have a valid key.
241 if ( key.empty() ) {
242 return false;
243 }
244
245 // Set metadata key
246 mKeys[index] = key;
247
248 // Set metadata type
249 mValues[index].mType = GetAiType(value);
250 // Copy the given value to the dynamic storage
251 mValues[index].mData = new T(value);
252
253 return true;
254 }
255
256 template<typename T>
257 inline
258 bool Get( unsigned index, T& value ) {
259 // In range assertion
260 if ( index >= mNumProperties ) {
261 return false;
262 }
263
264 // Return false if the output data type does
265 // not match the found value's data type
266 if ( GetAiType( value ) != mValues[ index ].mType ) {
267 return false;
268 }
269
270 // Otherwise, output the found value and
271 // return true
272 value = *static_cast<T*>(mValues[index].mData);
273
274 return true;
275 }
276
277 template<typename T>
278 inline
279 bool Get( const aiString& key, T& value ) {
280 // Search for the given key
281 for ( unsigned int i = 0; i < mNumProperties; ++i ) {
282 if ( mKeys[ i ] == key ) {
283 return Get( i, value );
284 }
285 }
286 return false;
287 }
288
289 template<typename T>
290 inline bool Get( const std::string& key, T& value ) {
291 return Get(aiString(key), value);
292 }
293
294 /// Return metadata entry for analyzing it by user.
295 /// \param [in] pIndex - index of the entry.
296 /// \param [out] pKey - pointer to the key value.
297 /// \param [out] pEntry - pointer to the entry: type and value.
298 /// \return false - if pIndex is out of range, else - true.
299 inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) {
300 if ( index >= mNumProperties ) {
301 return false;
302 }
303
304 key = &mKeys[index];
305 entry = &mValues[index];
306
307 return true;
308 }
309
310#endif // __cplusplus
311
312};
313
314#endif // AI_METADATA_H_INC
315