--- /dev/null
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Template class that is either type of Left or Right.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuEither.hpp"
+
+namespace tcu
+{
+namespace
+{
+
+enum
+{
+ COPYCHECK_VALUE = 1637423219
+};
+
+class TestClassWithConstructor
+{
+public:
+ TestClassWithConstructor (int i)
+ : m_i (i)
+ , m_copyCheck (COPYCHECK_VALUE)
+ {
+ }
+
+ ~TestClassWithConstructor (void)
+ {
+ TCU_CHECK(m_copyCheck == COPYCHECK_VALUE);
+ }
+
+ TestClassWithConstructor (const TestClassWithConstructor& other)
+ : m_i (other.m_i)
+ , m_copyCheck (other.m_copyCheck)
+ {
+ }
+
+ TestClassWithConstructor& operator= (const TestClassWithConstructor& other)
+ {
+ TCU_CHECK(m_copyCheck == COPYCHECK_VALUE);
+
+ if (this == &other)
+ return *this;
+
+ m_i = other.m_i;
+ m_copyCheck = other.m_copyCheck;
+
+ TCU_CHECK(m_copyCheck == COPYCHECK_VALUE);
+
+ return *this;
+ }
+
+ int getValue (void) const
+ {
+ TCU_CHECK(m_copyCheck == COPYCHECK_VALUE);
+
+ return m_i;
+ }
+
+private:
+ int m_i;
+ int m_copyCheck;
+};
+
+} // anonymous
+
+void Either_selfTest (void)
+{
+ // Simple test for first
+ {
+ const int intValue = 1503457782;
+ const Either<int, float> either (intValue);
+
+ TCU_CHECK(either.isFirst());
+ TCU_CHECK(!either.isSecond());
+
+ TCU_CHECK(either.is<int>());
+ TCU_CHECK(!either.is<float>());
+
+ TCU_CHECK(either.getFirst() == intValue);
+ TCU_CHECK(either.get<int>() == intValue);
+ }
+
+ // Simple test for second
+ {
+ const float floatValue = 0.43223332995f;
+ const Either<int, float> either (floatValue);
+
+ TCU_CHECK(!either.isFirst());
+ TCU_CHECK(either.isSecond());
+
+ TCU_CHECK(!either.is<int>());
+ TCU_CHECK(either.is<float>());
+
+ TCU_CHECK(either.getSecond() == floatValue);
+ TCU_CHECK(either.get<float>() == floatValue);
+ }
+
+ // Assign first value
+ {
+ const int intValue = 1942092699;
+ const float floatValue = 0.43223332995f;
+ Either<int, float> either (floatValue);
+
+ either = intValue;
+
+ TCU_CHECK(either.isFirst());
+ TCU_CHECK(!either.isSecond());
+
+ TCU_CHECK(either.is<int>());
+ TCU_CHECK(!either.is<float>());
+
+ TCU_CHECK(either.getFirst() == intValue);
+ TCU_CHECK(either.get<int>() == intValue);
+ }
+
+ // Assign second value
+ {
+ const int intValue = 1942092699;
+ const float floatValue = 0.43223332995f;
+ Either<int, float> either (intValue);
+
+ either = floatValue;
+
+ TCU_CHECK(!either.isFirst());
+ TCU_CHECK(either.isSecond());
+
+ TCU_CHECK(!either.is<int>());
+ TCU_CHECK(either.is<float>());
+
+ TCU_CHECK(either.getSecond() == floatValue);
+ TCU_CHECK(either.get<float>() == floatValue);
+ }
+
+ // Assign first either value
+ {
+ const int intValue = 1942092699;
+ const float floatValue = 0.43223332995f;
+ Either<int, float> either (floatValue);
+ const Either<int, float> otherEither (intValue);
+
+ either = otherEither;
+
+ TCU_CHECK(either.isFirst());
+ TCU_CHECK(!either.isSecond());
+
+ TCU_CHECK(either.is<int>());
+ TCU_CHECK(!either.is<float>());
+
+ TCU_CHECK(either.getFirst() == intValue);
+ TCU_CHECK(either.get<int>() == intValue);
+ }
+
+ // Assign second either value
+ {
+ const int intValue = 1942092699;
+ const float floatValue = 0.43223332995f;
+ Either<int, float> either (intValue);
+ const Either<int, float> otherEither (floatValue);
+
+ either = otherEither;
+
+ TCU_CHECK(!either.isFirst());
+ TCU_CHECK(either.isSecond());
+
+ TCU_CHECK(!either.is<int>());
+ TCU_CHECK(either.is<float>());
+
+ TCU_CHECK(either.getSecond() == floatValue);
+ TCU_CHECK(either.get<float>() == floatValue);
+ }
+
+ // Simple test for first with constructor
+ {
+ const TestClassWithConstructor testObject (171899615);
+ const Either<TestClassWithConstructor, int> either (testObject);
+
+ TCU_CHECK(either.isFirst());
+ TCU_CHECK(!either.isSecond());
+
+ TCU_CHECK(either.is<TestClassWithConstructor>());
+ TCU_CHECK(!either.is<int>());
+
+ TCU_CHECK(either.getFirst().getValue() == testObject.getValue());
+ TCU_CHECK(either.get<TestClassWithConstructor>().getValue() == testObject.getValue());
+ }
+
+ // Simple test for second with constructor
+ {
+ const TestClassWithConstructor testObject (171899615);
+ const Either<int, TestClassWithConstructor> either (testObject);
+
+ TCU_CHECK(!either.isFirst());
+ TCU_CHECK(either.isSecond());
+
+ TCU_CHECK(either.is<TestClassWithConstructor>());
+ TCU_CHECK(!either.is<int>());
+
+ TCU_CHECK(either.getSecond().getValue() == testObject.getValue());
+ TCU_CHECK(either.get<TestClassWithConstructor>().getValue() == testObject.getValue());
+ }
+
+ // Assign first with constructor
+ {
+ const int intValue = 1942092699;
+ const TestClassWithConstructor testObject (171899615);
+ Either<TestClassWithConstructor, int> either (intValue);
+
+ either = testObject;
+
+ TCU_CHECK(either.isFirst());
+ TCU_CHECK(!either.isSecond());
+
+ TCU_CHECK(either.is<TestClassWithConstructor>());
+ TCU_CHECK(!either.is<int>());
+
+ TCU_CHECK(either.getFirst().getValue() == testObject.getValue());
+ TCU_CHECK(either.get<TestClassWithConstructor>().getValue() == testObject.getValue());
+ }
+
+ // Assign second with constructor
+ {
+ const int intValue = 1942092699;
+ const TestClassWithConstructor testObject (171899615);
+ Either<int, TestClassWithConstructor> either (intValue);
+
+ either = testObject;
+
+ TCU_CHECK(!either.isFirst());
+ TCU_CHECK(either.isSecond());
+
+ TCU_CHECK(either.is<TestClassWithConstructor>());
+ TCU_CHECK(!either.is<int>());
+
+ TCU_CHECK(either.getSecond().getValue() == testObject.getValue());
+ TCU_CHECK(either.get<TestClassWithConstructor>().getValue() == testObject.getValue());
+ }
+
+ // Assign first either with constructor
+ {
+ const int intValue = 1942092699;
+ const TestClassWithConstructor testObject (171899615);
+ Either<TestClassWithConstructor, int> either (intValue);
+ const Either<TestClassWithConstructor, int> otherEither (testObject);
+
+ either = otherEither;
+
+ TCU_CHECK(either.isFirst());
+ TCU_CHECK(!either.isSecond());
+
+ TCU_CHECK(either.is<TestClassWithConstructor>());
+ TCU_CHECK(!either.is<int>());
+
+ TCU_CHECK(either.getFirst().getValue() == testObject.getValue());
+ TCU_CHECK(either.get<TestClassWithConstructor>().getValue() == testObject.getValue());
+ }
+
+ // Assign second either with constructor
+ {
+ const int intValue = 1942092699;
+ const TestClassWithConstructor testObject (171899615);
+ Either<int, TestClassWithConstructor> either (intValue);
+ const Either<int, TestClassWithConstructor> otherEither (testObject);
+
+
+ either = testObject;
+
+ TCU_CHECK(!either.isFirst());
+ TCU_CHECK(either.isSecond());
+
+ TCU_CHECK(either.is<TestClassWithConstructor>());
+ TCU_CHECK(!either.is<int>());
+
+ TCU_CHECK(either.getSecond().getValue() == testObject.getValue());
+ TCU_CHECK(either.get<TestClassWithConstructor>().getValue() == testObject.getValue());
+ }
+}
+
+} // tcu
--- /dev/null
+#ifndef _TCUEITHER_HPP
+#define _TCUEITHER_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Template class that is either type of First or Second.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+
+namespace tcu
+{
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Object containing Either First or Second type of object
+ *
+ * \note Type First and Second are always aligned to same alignment as
+ * deUint64.
+ * \note This type always uses at least sizeof(bool) + max(sizeof(First*),
+ * sizeof(Second*)) + sizeof(deUint64) of memory.
+ *//*--------------------------------------------------------------------*/
+template<typename First, typename Second>
+class Either
+{
+public:
+ Either (const First& first);
+ Either (const Second& second);
+ ~Either (void);
+
+ Either (const Either<First, Second>& other);
+ Either& operator= (const Either<First, Second>& other);
+
+ Either& operator= (const First& first);
+ Either& operator= (const Second& second);
+
+ bool isFirst (void) const;
+ bool isSecond (void) const;
+
+ const First& getFirst (void) const;
+ const Second& getSecond (void) const;
+
+ template<typename Type>
+ const Type& get (void) const;
+
+ template<typename Type>
+ bool is (void) const;
+
+private:
+ void release (void);
+
+ bool m_isFirst;
+
+ union
+ {
+ First* m_first;
+ Second* m_second;
+ };
+
+ union
+ {
+ deUint8 m_data[sizeof(First) > sizeof(Second) ? sizeof(First) : sizeof(Second)];
+ deUint64 m_align;
+ };
+};
+
+namespace EitherDetail
+{
+
+template<typename Type, typename First, typename Second>
+struct Get;
+
+template<typename First, typename Second>
+struct Get<First, First, Second>
+{
+ static const First& get (const Either<First, Second>& either)
+ {
+ return either.getFirst();
+ }
+};
+
+template<typename First, typename Second>
+struct Get<Second, First, Second>
+{
+ static const Second& get (const Either<First, Second>& either)
+ {
+ return either.getSecond();
+ }
+};
+
+template<typename Type, typename First, typename Second>
+const Type& get (const Either<First, Second>& either)
+{
+ return Get<Type, First, Second>::get(either);
+}
+
+template<typename Type, typename First, typename Second>
+struct Is;
+
+template<typename First, typename Second>
+struct Is<First, First, Second>
+{
+ static bool is (const Either<First, Second>& either)
+ {
+ return either.isFirst();
+ }
+};
+
+template<typename First, typename Second>
+struct Is<Second, First, Second>
+{
+ static bool is (const Either<First, Second>& either)
+ {
+ return either.isSecond();
+ }
+};
+
+template<typename Type, typename First, typename Second>
+bool is (const Either<First, Second>& either)
+{
+ return Is<Type, First, Second>::is(either);
+}
+
+} // EitherDetail
+
+template<typename First, typename Second>
+void Either<First, Second>::release (void)
+{
+ if (m_isFirst)
+ m_first->~First();
+ else
+ m_second->~Second();
+
+ m_isFirst = true;
+ m_first = DE_NULL;
+}
+
+template<typename First, typename Second>
+Either<First, Second>::Either (const First& first)
+ : m_isFirst (true)
+{
+ m_first = new(m_data)First(first);
+}
+
+template<typename First, typename Second>
+Either<First, Second>::Either (const Second& second)
+ : m_isFirst (false)
+{
+ m_second = new(m_data)Second(second);
+}
+
+template<typename First, typename Second>
+Either<First, Second>::~Either (void)
+{
+ release();
+}
+
+template<typename First, typename Second>
+Either<First, Second>::Either (const Either<First, Second>& other)
+ : m_isFirst (other.m_isFirst)
+{
+ if (m_isFirst)
+ m_first = new(m_data)First(*other.m_first);
+ else
+ m_second = new(m_data)Second(*other.m_second);
+}
+
+template<typename First, typename Second>
+Either<First, Second>& Either<First, Second>::operator= (const Either<First, Second>& other)
+{
+ if (this == &other)
+ return *this;
+
+ release();
+
+ m_isFirst = other.m_isFirst;
+
+ if (m_isFirst)
+ m_first = new(m_data)First(*other.m_first);
+ else
+ m_second = new(m_data)Second(*other.m_second);
+
+ return *this;
+}
+
+template<typename First, typename Second>
+Either<First, Second>& Either<First, Second>::operator= (const First& first)
+{
+ release();
+
+ m_isFirst = true;
+ m_first = new(m_data)First(first);
+
+ return *this;
+}
+
+template<typename First, typename Second>
+Either<First, Second>& Either<First, Second>::operator= (const Second& second)
+{
+ release();
+
+ m_isFirst = false;
+ m_second = new(m_data)Second(second);
+
+ return *this;
+}
+
+template<typename First, typename Second>
+bool Either<First, Second>::isFirst (void) const
+{
+ return m_isFirst;
+}
+
+template<typename First, typename Second>
+bool Either<First, Second>::isSecond (void) const
+{
+ return !m_isFirst;
+}
+
+template<typename First, typename Second>
+const First& Either<First, Second>::getFirst (void) const
+{
+ DE_ASSERT(isFirst());
+ return *m_first;
+}
+
+template<typename First, typename Second>
+const Second& Either<First, Second>::getSecond (void) const
+{
+ DE_ASSERT(isSecond());
+ return *m_second;
+}
+
+template<typename First, typename Second>
+template<typename Type>
+const Type& Either<First, Second>::get (void) const
+{
+ return EitherDetail::get<Type, First, Second>(*this);
+}
+
+template<typename First, typename Second>
+template<typename Type>
+bool Either<First, Second>::is (void) const
+{
+ return EitherDetail::is<Type, First, Second>(*this);
+}
+
+void Either_selfTest (void);
+
+} // tcu
+
+#endif // _TCUEITHER_HPP