Home | History | Annotate | Download | only in common
      1 #ifndef _TCUEITHER_HPP
      2 #define _TCUEITHER_HPP
      3 /*-------------------------------------------------------------------------
      4  * drawElements Quality Program Tester Core
      5  * ----------------------------------------
      6  *
      7  * Copyright 2015 The Android Open Source Project
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief Template class that is either type of First or Second.
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "tcuDefs.hpp"
     27 
     28 namespace tcu
     29 {
     30 
     31 /*--------------------------------------------------------------------*//*!
     32  * \brief Object containing Either First or Second type of object
     33  *
     34  * \note Type First and Second are always aligned to same alignment as
     35  *		 deUint64.
     36  * \note This type always uses at least sizeof(bool) + max(sizeof(First*),
     37  *		 sizeof(Second*)) + sizeof(deUint64) of memory.
     38  *//*--------------------------------------------------------------------*/
     39 template<typename First, typename Second>
     40 class Either
     41 {
     42 public:
     43 					Either		(const First& first);
     44 					Either		(const Second& second);
     45 					~Either		(void);
     46 
     47 					Either		(const Either<First, Second>& other);
     48 	Either&			operator=	(const Either<First, Second>& other);
     49 
     50 	Either&			operator=	(const First& first);
     51 	Either&			operator=	(const Second& second);
     52 
     53 	bool			isFirst		(void) const;
     54 	bool			isSecond	(void) const;
     55 
     56 	const First&	getFirst	(void) const;
     57 	const Second&	getSecond	(void) const;
     58 
     59 	template<typename Type>
     60 	const Type&		get			(void) const;
     61 
     62 	template<typename Type>
     63 	bool			is			(void) const;
     64 
     65 private:
     66 	void			release		(void);
     67 
     68 	bool			m_isFirst;
     69 
     70 	union
     71 	{
     72 		First*		m_first;
     73 		Second*		m_second;
     74 	};
     75 
     76 	union
     77 	{
     78 		deUint8		m_data[sizeof(First) > sizeof(Second) ? sizeof(First) : sizeof(Second)];
     79 		deUint64	m_align;
     80 	};
     81 } DE_WARN_UNUSED_TYPE;
     82 
     83 namespace EitherDetail
     84 {
     85 
     86 template<typename Type, typename First, typename Second>
     87 struct Get;
     88 
     89 template<typename First, typename Second>
     90 struct Get<First, First, Second>
     91 {
     92 	static const First& get (const Either<First, Second>& either)
     93 	{
     94 		return either.getFirst();
     95 	}
     96 };
     97 
     98 template<typename First, typename Second>
     99 struct Get<Second, First, Second>
    100 {
    101 	static const Second& get (const Either<First, Second>& either)
    102 	{
    103 		return either.getSecond();
    104 	}
    105 };
    106 
    107 template<typename Type, typename First, typename Second>
    108 const Type& get (const Either<First, Second>& either)
    109 {
    110 	return Get<Type, First, Second>::get(either);
    111 }
    112 
    113 template<typename Type, typename First, typename Second>
    114 struct Is;
    115 
    116 template<typename First, typename Second>
    117 struct Is<First, First, Second>
    118 {
    119 	static bool is (const Either<First, Second>& either)
    120 	{
    121 		return either.isFirst();
    122 	}
    123 };
    124 
    125 template<typename First, typename Second>
    126 struct Is<Second, First, Second>
    127 {
    128 	static bool is (const Either<First, Second>& either)
    129 	{
    130 		return either.isSecond();
    131 	}
    132 };
    133 
    134 template<typename Type, typename First, typename Second>
    135 bool is (const Either<First, Second>& either)
    136 {
    137 	return Is<Type, First, Second>::is(either);
    138 }
    139 
    140 } // EitherDetail
    141 
    142 template<typename First, typename Second>
    143 void Either<First, Second>::release (void)
    144 {
    145 	if (m_isFirst)
    146 		m_first->~First();
    147 	else
    148 		m_second->~Second();
    149 
    150 	m_isFirst	= true;
    151 	m_first		= DE_NULL;
    152 }
    153 
    154 template<typename First, typename Second>
    155 Either<First, Second>::Either (const First& first)
    156 	: m_isFirst	(true)
    157 {
    158 	m_first = new(m_data)First(first);
    159 }
    160 
    161 template<typename First, typename Second>
    162 Either<First, Second>::Either (const Second& second)
    163 	: m_isFirst (false)
    164 {
    165 	m_second = new(m_data)Second(second);
    166 }
    167 
    168 template<typename First, typename Second>
    169 Either<First, Second>::~Either (void)
    170 {
    171 	release();
    172 }
    173 
    174 template<typename First, typename Second>
    175 Either<First, Second>::Either (const Either<First, Second>& other)
    176 	: m_isFirst	(other.m_isFirst)
    177 {
    178 	if (m_isFirst)
    179 		m_first = new(m_data)First(*other.m_first);
    180 	else
    181 		m_second = new(m_data)Second(*other.m_second);
    182 }
    183 
    184 template<typename First, typename Second>
    185 Either<First, Second>& Either<First, Second>::operator= (const Either<First, Second>& other)
    186 {
    187 	if (this == &other)
    188 		return *this;
    189 
    190 	release();
    191 
    192 	m_isFirst = other.m_isFirst;
    193 
    194 	if (m_isFirst)
    195 		m_first = new(m_data)First(*other.m_first);
    196 	else
    197 		m_second = new(m_data)Second(*other.m_second);
    198 
    199 	return *this;
    200 }
    201 
    202 template<typename First, typename Second>
    203 Either<First, Second>& Either<First, Second>::operator= (const First& first)
    204 {
    205 	release();
    206 
    207 	m_isFirst = true;
    208 	m_first = new(m_data)First(first);
    209 
    210 	return *this;
    211 }
    212 
    213 template<typename First, typename Second>
    214 Either<First, Second>& Either<First, Second>::operator= (const Second& second)
    215 {
    216 	release();
    217 
    218 	m_isFirst = false;
    219 	m_second = new(m_data)Second(second);
    220 
    221 	return *this;
    222 }
    223 
    224 template<typename First, typename Second>
    225 bool Either<First, Second>::isFirst (void) const
    226 {
    227 	return m_isFirst;
    228 }
    229 
    230 template<typename First, typename Second>
    231 bool Either<First, Second>::isSecond (void) const
    232 {
    233 	return !m_isFirst;
    234 }
    235 
    236 template<typename First, typename Second>
    237 const First& Either<First, Second>::getFirst (void) const
    238 {
    239 	DE_ASSERT(isFirst());
    240 	return *m_first;
    241 }
    242 
    243 template<typename First, typename Second>
    244 const Second& Either<First, Second>::getSecond (void) const
    245 {
    246 	DE_ASSERT(isSecond());
    247 	return *m_second;
    248 }
    249 
    250 template<typename First, typename Second>
    251 template<typename Type>
    252 const Type& Either<First, Second>::get (void) const
    253 {
    254 	return EitherDetail::get<Type, First, Second>(*this);
    255 }
    256 
    257 template<typename First, typename Second>
    258 template<typename Type>
    259 bool Either<First, Second>::is (void) const
    260 {
    261 	return EitherDetail::is<Type, First, Second>(*this);
    262 }
    263 
    264 void Either_selfTest (void);
    265 
    266 } // tcu
    267 
    268 #endif // _TCUEITHER_HPP
    269