1 // Copyright (c) 2017 Intel Corporation 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in all 11 // copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 // SOFTWARE. 20 21 #pragma once 22 23 #include "mfx_config.h" 24 #include "mfx_trace.h" 25 26 #if defined(MFX_TRACE_ENABLE_REFLECT) 27 28 #include <memory> 29 #include <string> 30 #include <string.h> //for memcmp on Linux 31 #include <list> 32 #include <vector> 33 #include <map> 34 #include <stdexcept> 35 36 #include <typeindex> 37 38 namespace mfx_reflect 39 { 40 class ReflectedField; 41 class ReflectedType; 42 class ReflectedTypesCollection; 43 44 class ReflectedField 45 { 46 public: 47 typedef std::shared_ptr<ReflectedField> SP; 48 typedef std::vector<ReflectedField::SP> FieldsCollection; 49 typedef FieldsCollection::const_iterator FieldsCollectionCI; 50 51 52 ReflectedType* FieldType; 53 ReflectedType* AggregatingType; 54 const std::string & FieldTypeName; //single C++ type may have several typedef aliases. This is original name that was used for this field declaration. 55 size_t Offset; 56 const std::string FieldName; 57 size_t Count; 58 ReflectedTypesCollection * m_pCollection; 59 GetAddress(void * pBase)60 void * GetAddress(void *pBase) 61 { 62 return ((unsigned char*)pBase) + Offset; 63 } 64 65 protected: ReflectedField(ReflectedTypesCollection * pCollection,ReflectedType * aggregatingType,ReflectedType * fieldType,const std::string & fieldTypeName,size_t offset,const std::string & fieldName,size_t count)66 ReflectedField(ReflectedTypesCollection *pCollection, ReflectedType* aggregatingType, ReflectedType* fieldType, const std::string& fieldTypeName, size_t offset, const std::string& fieldName, size_t count) 67 : FieldType(fieldType) 68 , AggregatingType(aggregatingType) 69 , FieldTypeName(fieldTypeName) 70 , Offset(offset) 71 , FieldName(fieldName) 72 , Count(count) 73 , m_pCollection(pCollection) 74 { 75 } 76 77 friend class ReflectedType; 78 }; 79 80 class ReflectedType 81 { 82 public: 83 std::type_index m_TypeIndex; 84 std::list< std::string > TypeNames; 85 size_t Size; 86 ReflectedTypesCollection *m_pCollection; 87 bool m_bIsPointer; 88 unsigned int ExtBufferId; 89 90 ReflectedType(ReflectedTypesCollection *pCollection, std::type_index typeIndex, const std::string& typeName, size_t size, bool isPointer, unsigned int extBufferId); 91 92 ReflectedField::SP AddField(std::type_index typeIndex, const std::string &typeName, size_t typeSize, bool isPointer, size_t offset, const std::string &fieldName, size_t count, unsigned int extBufferId); 93 94 ReflectedField::FieldsCollectionCI FindField(const std::string& fieldName) const; 95 96 ReflectedField::FieldsCollection m_Fields; 97 typedef std::shared_ptr<ReflectedType> SP; 98 typedef std::list< std::string> StringList; 99 100 }; 101 102 class ReflectedTypesCollection 103 { 104 public: 105 typedef std::map<std::type_index, ReflectedType::SP> Container; 106 107 Container m_KnownTypes; 108 FindExistingType()109 template <class T> ReflectedType::SP FindExistingType() 110 { 111 return FindExistingType(std::type_index(typeid(T))); 112 } 113 114 ReflectedType::SP FindExistingByTypeInfoName(const char* name); 115 116 ReflectedType::SP FindExistingType(std::type_index typeIndex); 117 ReflectedType::SP FindExtBufferTypeById(unsigned int ExtBufferId); 118 119 ReflectedType::SP DeclareType(std::type_index typeIndex, const std::string& typeName, size_t typeSize, bool isPointer, unsigned int extBufferId); 120 121 ReflectedType::SP FindOrDeclareType(std::type_index typeIndex, const std::string& typeName, size_t typeSize, bool isPointer, unsigned int extBufferId); 122 123 void DeclareMsdkStructs(); 124 }; 125 126 template <class T> 127 class AccessorBase 128 { 129 public: 130 void * m_P; 131 const T* m_pReflection; AccessorBase(void * p,const T & reflection)132 AccessorBase(void *p, const T &reflection) 133 : m_P(p) 134 , m_pReflection(&reflection) 135 {} 136 typedef std::shared_ptr<T> P; 137 138 template <class ORIGINAL_TYPE> Get()139 const ORIGINAL_TYPE& Get() const 140 { 141 return *((const ORIGINAL_TYPE*)m_P); 142 } 143 }; 144 145 template <class T, class I> 146 class IterableAccessor : public AccessorBase < T > 147 { 148 public: 149 I m_Iterator; 150 IterableAccessor(void * p,I iterator)151 IterableAccessor(void *p, I iterator) 152 : AccessorBase<T>(p, *(*iterator)) 153 , m_Iterator(iterator) 154 {} 155 }; 156 157 class AccessorType; 158 159 class AccessorField : public IterableAccessor < ReflectedField, ReflectedField::FieldsCollectionCI > 160 { 161 public: AccessorField(const AccessorType & baseStruct,ReflectedField::FieldsCollectionCI iterator)162 AccessorField(const AccessorType &baseStruct, ReflectedField::FieldsCollectionCI iterator) 163 : IterableAccessor(NULL, iterator) 164 , m_BaseStruct(baseStruct) 165 { 166 m_IndexElement = 0; 167 SetFieldAddress(); 168 } 169 GetIndexElement()170 size_t GetIndexElement() const 171 { 172 return m_IndexElement; 173 } 174 SetIndexElement(size_t index)175 void SetIndexElement(size_t index) 176 { 177 if (index >= m_pReflection->Count) 178 { 179 throw std::invalid_argument(std::string("Index is not valid")); 180 } 181 182 m_IndexElement = index; 183 SetFieldAddress(); 184 } 185 Move(std::ptrdiff_t delta)186 void Move(std::ptrdiff_t delta) 187 { 188 this->m_P = (char*)this->m_P + delta; 189 } 190 191 AccessorField& operator++(); 192 Equal(const AccessorField & field)193 bool Equal(const AccessorField& field) const 194 { 195 if (field.m_pReflection != m_pReflection) 196 { 197 throw std::invalid_argument(std::string("Types mismatch")); 198 } 199 200 if (field.m_IndexElement != m_IndexElement) 201 { 202 throw std::invalid_argument(std::string("Indices mismatch")); 203 } 204 205 size_t size = m_pReflection->FieldType->Size; 206 return (0 == memcmp(m_P, field.m_P, size)); 207 } 208 209 AccessorType AccessSubtype() const; 210 211 bool IsValid() const; 212 213 protected: 214 void SetFieldAddress(); 215 const AccessorType &m_BaseStruct; 216 size_t m_IndexElement; 217 SetIterator(ReflectedField::FieldsCollectionCI iterator)218 void SetIterator(ReflectedField::FieldsCollectionCI iterator) 219 { 220 m_Iterator = iterator; 221 m_pReflection = (*m_Iterator).get(); 222 SetFieldAddress(); 223 } 224 }; 225 226 class AccessorType : public AccessorBase < ReflectedType > 227 { 228 public: AccessorType(void * p,const ReflectedType & reflection)229 AccessorType(void *p, const ReflectedType &reflection) : AccessorBase(p, reflection) {} 230 231 AccessorField AccessField(ReflectedField::FieldsCollectionCI iter) const; 232 AccessorField AccessField(const std::string& fieldName) const; 233 AccessorField AccessFirstField() const; 234 AccessorType AccessSubtype(const std::string& fieldName) const; 235 }; 236 237 class AccessibleTypesCollection : public ReflectedTypesCollection 238 { 239 public: AccessibleTypesCollection()240 AccessibleTypesCollection() 241 : m_bIsInitialized(false) 242 {} 243 bool m_bIsInitialized; 244 template <class T> Access(T * p)245 AccessorType Access(T *p) 246 { 247 ReflectedType::SP pType = FindExistingType(std::type_index(typeid(T))); 248 if (pType == NULL) 249 { 250 throw std::invalid_argument(std::string("Unknown type")); 251 } 252 else 253 { 254 return AccessorType(p, *pType); 255 } 256 } 257 258 static void Initialize(); 259 }; 260 261 class TypeComparisonResult; 262 typedef std::shared_ptr<TypeComparisonResult> TypeComparisonResultP; 263 264 struct FieldComparisonResult 265 { 266 AccessorField accessorField1; 267 AccessorField accessorField2; 268 TypeComparisonResultP subtypeComparisonResultP; 269 }; 270 271 class TypeComparisonResult : public std::list < FieldComparisonResult > 272 { 273 public: 274 list<unsigned int> extBufferIdList; 275 }; 276 277 typedef std::shared_ptr<AccessorType> AccessorTypeP; 278 279 TypeComparisonResultP CompareTwoStructs(AccessorType data1, AccessorType data2); 280 281 std::string CompareStructsToString(AccessorType data1, AccessorType data2); 282 void PrintStuctsComparisonResult(std::ostream& comparisonResult, const std::string& prefix, const TypeComparisonResultP& result); 283 284 template <class T> bool PrintFieldIfTypeMatches(std::ostream& stream, AccessorField field); 285 void PrintFieldValue(std::ostream &stream, AccessorField field); 286 std::ostream& operator<< (std::ostream& stream, AccessorField field); 287 std::ostream& operator<< (std::ostream& stream, AccessorType data); 288 289 template <class T> ReflectedType::SP DeclareTypeT(ReflectedTypesCollection& collection, const std::string typeName); 290 291 mfx_reflect::AccessibleTypesCollection GetReflection(); 292 } // namespace mfx_reflect 293 294 #endif // #if defined(MFX_TRACE_ENABLE_REFLECT) 295