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 28namespace 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 *//*--------------------------------------------------------------------*/ 39template<typename First, typename Second> 40class Either 41{ 42public: 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 65private: 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 83namespace EitherDetail 84{ 85 86template<typename Type, typename First, typename Second> 87struct Get; 88 89template<typename First, typename Second> 90struct Get<First, First, Second> 91{ 92 static const First& get (const Either<First, Second>& either) 93 { 94 return either.getFirst(); 95 } 96}; 97 98template<typename First, typename Second> 99struct Get<Second, First, Second> 100{ 101 static const Second& get (const Either<First, Second>& either) 102 { 103 return either.getSecond(); 104 } 105}; 106 107template<typename Type, typename First, typename Second> 108const Type& get (const Either<First, Second>& either) 109{ 110 return Get<Type, First, Second>::get(either); 111} 112 113template<typename Type, typename First, typename Second> 114struct Is; 115 116template<typename First, typename Second> 117struct Is<First, First, Second> 118{ 119 static bool is (const Either<First, Second>& either) 120 { 121 return either.isFirst(); 122 } 123}; 124 125template<typename First, typename Second> 126struct Is<Second, First, Second> 127{ 128 static bool is (const Either<First, Second>& either) 129 { 130 return either.isSecond(); 131 } 132}; 133 134template<typename Type, typename First, typename Second> 135bool is (const Either<First, Second>& either) 136{ 137 return Is<Type, First, Second>::is(either); 138} 139 140} // EitherDetail 141 142template<typename First, typename Second> 143void 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 154template<typename First, typename Second> 155Either<First, Second>::Either (const First& first) 156 : m_isFirst (true) 157{ 158 m_first = new(m_data)First(first); 159} 160 161template<typename First, typename Second> 162Either<First, Second>::Either (const Second& second) 163 : m_isFirst (false) 164{ 165 m_second = new(m_data)Second(second); 166} 167 168template<typename First, typename Second> 169Either<First, Second>::~Either (void) 170{ 171 release(); 172} 173 174template<typename First, typename Second> 175Either<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 184template<typename First, typename Second> 185Either<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 202template<typename First, typename Second> 203Either<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 213template<typename First, typename Second> 214Either<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 224template<typename First, typename Second> 225bool Either<First, Second>::isFirst (void) const 226{ 227 return m_isFirst; 228} 229 230template<typename First, typename Second> 231bool Either<First, Second>::isSecond (void) const 232{ 233 return !m_isFirst; 234} 235 236template<typename First, typename Second> 237const First& Either<First, Second>::getFirst (void) const 238{ 239 DE_ASSERT(isFirst()); 240 return *m_first; 241} 242 243template<typename First, typename Second> 244const Second& Either<First, Second>::getSecond (void) const 245{ 246 DE_ASSERT(isSecond()); 247 return *m_second; 248} 249 250template<typename First, typename Second> 251template<typename Type> 252const Type& Either<First, Second>::get (void) const 253{ 254 return EitherDetail::get<Type, First, Second>(*this); 255} 256 257template<typename First, typename Second> 258template<typename Type> 259bool Either<First, Second>::is (void) const 260{ 261 return EitherDetail::is<Type, First, Second>(*this); 262} 263 264void Either_selfTest (void); 265 266} // tcu 267 268#endif // _TCUEITHER_HPP 269