1//===-- MIUtilVariant.h -----------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#pragma once
11
12// In-house headers:
13#include "MIDataTypes.h"
14
15//++ ============================================================================
16// Details: MI common code utility class. The class implements behaviour of a
17//          variant object which holds any data object of type T. A copy of the
18//          data object specified is made and stored in *this wrapper. When the
19//          *this object is destroyed the data object hold within calls its
20//          destructor should it have one.
21//--
22class CMIUtilVariant
23{
24    // Methods:
25  public:
26    /* ctor */ CMIUtilVariant();
27    /* ctor */ CMIUtilVariant(const CMIUtilVariant &vrOther);
28    /* ctor */ CMIUtilVariant(CMIUtilVariant &vrOther);
29    /* ctor */ CMIUtilVariant(CMIUtilVariant &&vrwOther);
30    /* dtor */ ~CMIUtilVariant();
31
32    template <typename T> void Set(const T &vArg);
33    template <typename T> T *Get() const;
34
35    CMIUtilVariant &operator=(const CMIUtilVariant &vrOther);
36    CMIUtilVariant &operator=(CMIUtilVariant &&vrwOther);
37
38    // Classes:
39  private:
40    //++ ----------------------------------------------------------------------
41    // Details: Base class wrapper to hold the variant's data object when
42    //          assigned to it by the Set() function. Do not use the CDataObjectBase
43    //          to create objects, use only CDataObjectBase derived objects,
44    //          see CDataObject() class.
45    //--
46    class CDataObjectBase
47    {
48        // Methods:
49      public:
50        /* ctor */ CDataObjectBase();
51        /* ctor */ CDataObjectBase(const CDataObjectBase &vrOther);
52        /* ctor */ CDataObjectBase(CDataObjectBase &vrOther);
53        /* ctor */ CDataObjectBase(CDataObjectBase &&vrwOther);
54        //
55        CDataObjectBase &operator=(const CDataObjectBase &vrOther);
56        CDataObjectBase &operator=(CDataObjectBase &&vrwOther);
57
58        // Overrideable:
59      public:
60        virtual ~CDataObjectBase();
61        virtual CDataObjectBase *CreateCopyOfSelf();
62        virtual bool GetIsDerivedClass() const;
63
64        // Overrideable:
65      protected:
66        virtual void Copy(const CDataObjectBase &vrOther);
67        virtual void Destroy();
68    };
69
70    //++ ----------------------------------------------------------------------
71    // Details: Derived from CDataObjectBase, this class is the wrapper for the
72    //          data object as it has an aggregate of type T which is a copy
73    //          of the data object assigned to the variant object.
74    //--
75    template <typename T> class CDataObject : public CDataObjectBase
76    {
77        // Methods:
78      public:
79        /* ctor */ CDataObject();
80        /* ctor */ CDataObject(const T &vArg);
81        /* ctor */ CDataObject(const CDataObject &vrOther);
82        /* ctor */ CDataObject(CDataObject &vrOther);
83        /* ctor */ CDataObject(CDataObject &&vrwOther);
84        //
85        CDataObject &operator=(const CDataObject &vrOther);
86        CDataObject &operator=(CDataObject &&vrwOther);
87        //
88        T &GetDataObject();
89
90        // Overridden:
91      public:
92        // From CDataObjectBase
93        ~CDataObject() override;
94        CDataObjectBase *CreateCopyOfSelf() override;
95        bool GetIsDerivedClass() const override;
96
97        // Overrideable:
98      private:
99        virtual void Duplicate(const CDataObject &vrOther);
100
101        // Overridden:
102      private:
103        // From CDataObjectBase
104        void Destroy() override;
105
106        // Attributes:
107      private:
108        T m_dataObj;
109    };
110
111    // Methods
112  private:
113    void Destroy();
114    void Copy(const CMIUtilVariant &vrOther);
115
116    // Attributes:
117  private:
118    CDataObjectBase *m_pDataObject;
119};
120
121//---------------------------------------------------------------------------------------
122//---------------------------------------------------------------------------------------
123//---------------------------------------------------------------------------------------
124
125//++ ------------------------------------------------------------------------------------
126// Details: CDataObject constructor.
127// Type:    Method.
128// Args:    T   - The object's type.
129// Return:  None.
130// Throws:  None.
131//--
132template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject()
133{
134}
135
136//++ ------------------------------------------------------------------------------------
137// Details: CDataObject constructor.
138// Type:    Method.
139// Args:    T       - The object's type.
140//          vArg    - (R) The data object to be stored in the variant object.
141// Return:  None.
142// Throws:  None.
143//--
144template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(const T &vArg)
145{
146    m_dataObj = vArg;
147}
148
149//++ ------------------------------------------------------------------------------------
150// Details: CDataObject destructor.
151// Type:    Overridden.
152// Args:    T   - The object's type.
153// Return:  None.
154// Throws:  None.
155//--
156template <typename T> CMIUtilVariant::CDataObject<T>::~CDataObject()
157{
158    Destroy();
159}
160
161//++ ------------------------------------------------------------------------------------
162// Details: Retrieve the data object hold by *this object wrapper.
163// Type:    Method.
164// Args:    T   - The object's type.
165// Return:  T & - Reference to the data object.
166// Throws:  None.
167//--
168template <typename T>
169T &
170CMIUtilVariant::CDataObject<T>::GetDataObject()
171{
172    return m_dataObj;
173}
174
175//++ ------------------------------------------------------------------------------------
176// Details: Create a new copy of *this class.
177// Type:    Overridden.
178// Args:    T   - The object's type.
179// Return:  CDataObjectBase *   - Pointer to a new object.
180// Throws:  None.
181//--
182template <typename T>
183CMIUtilVariant::CDataObjectBase *
184CMIUtilVariant::CDataObject<T>::CreateCopyOfSelf()
185{
186    CDataObject *pCopy = new CDataObject<T>(m_dataObj);
187
188    return pCopy;
189}
190
191//++ ------------------------------------------------------------------------------------
192// Details: Determine if *this object is a derived from CDataObjectBase.
193// Type:    Overridden.
194// Args:    T   - The object's type.
195// Return:  bool    - True = *this is derived from CDataObjectBase
196//                  - False = *this is an instance of the base class.
197// Throws:  None.
198//--
199template <typename T>
200bool
201CMIUtilVariant::CDataObject<T>::GetIsDerivedClass() const
202{
203    return true;
204}
205
206//++ ------------------------------------------------------------------------------------
207// Details: Perform a bitwise copy of *this object.
208// Type:    Overrideable.
209// Args:    T       - The object's type.
210//          vrOther - (R) The other object.
211// Return:  None.
212// Throws:  None.
213//--
214template <typename T>
215void
216CMIUtilVariant::CDataObject<T>::Duplicate(const CDataObject &vrOther)
217{
218    CDataObjectBase::Copy(vrOther);
219    m_dataObj = vrOther.m_dataObj;
220}
221
222//++ ------------------------------------------------------------------------------------
223// Details: Release any resources used by *this object.
224// Type:    Overridden.
225// Args:    None.
226// Return:  None.
227// Throws:  None.
228//--
229template <typename T>
230void
231CMIUtilVariant::CDataObject<T>::Destroy()
232{
233    CDataObjectBase::Destroy();
234}
235
236//---------------------------------------------------------------------------------------
237//---------------------------------------------------------------------------------------
238//---------------------------------------------------------------------------------------
239
240//++ ------------------------------------------------------------------------------------
241// Details: Assign to the variant an object of a specified type.
242// Type:    Template method.
243// Args:    T       - The object's type.
244//          vArg    - (R) The object to store.
245// Return:  None.
246// Throws:  None.
247//--
248template <typename T>
249void
250CMIUtilVariant::Set(const T &vArg)
251{
252    m_pDataObject = new CDataObject<T>(vArg);
253}
254
255//++ ------------------------------------------------------------------------------------
256// Details: Retrieve the data object from *this variant.
257// Type:    Template method.
258// Args:    T   - The object's type.
259// Return:  T * - Pointer the data object, NULL = data object not assigned to *this variant.
260// Throws:  None.
261//--
262template <typename T>
263T *
264CMIUtilVariant::Get() const
265{
266    if ((m_pDataObject != nullptr) && m_pDataObject->GetIsDerivedClass())
267    {
268        CDataObject<T> *pDataObj = static_cast<CDataObject<T> *>(m_pDataObject);
269        return &pDataObj->GetDataObject();
270    }
271
272    // Do not use a CDataObjectBase object, use only CDataObjectBase derived objects
273    return nullptr;
274}
275