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