Add tcuEither that contains one of two different types.

tcuEither class contains one of two different types. Basicly it works
like union with two types, but also tracks which one it contains.

Change-Id: I2183c2dcc947b1a3c6af6abd6dca37318c32107e
diff --git a/Android.mk b/Android.mk
index 4d3e6d5..9a69f89 100644
--- a/Android.mk
+++ b/Android.mk
@@ -49,6 +49,7 @@
 	framework/common/tcuRenderTarget.cpp \
 	framework/common/tcuResource.cpp \
 	framework/common/tcuRGBA.cpp \
+	framework/common/tcuEither.cpp \
 	framework/common/tcuStringTemplate.cpp \
 	framework/common/tcuSurface.cpp \
 	framework/common/tcuTestCase.cpp \
diff --git a/framework/common/CMakeLists.txt b/framework/common/CMakeLists.txt
index 9f5bd47..4396797 100644
--- a/framework/common/CMakeLists.txt
+++ b/framework/common/CMakeLists.txt
@@ -77,6 +77,8 @@
 	tcuSeedBuilder.cpp
 	tcuMaybe.hpp
 	tcuMaybe.cpp
+	tcuEither.hpp
+	tcuEither.cpp
 	)
 
 set(TCUTIL_LIBS
diff --git a/framework/common/tcuEither.cpp b/framework/common/tcuEither.cpp
new file mode 100644
index 0000000..64b9737
--- /dev/null
+++ b/framework/common/tcuEither.cpp
@@ -0,0 +1,297 @@
+/*-------------------------------------------------------------------------
+ * 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
diff --git a/framework/common/tcuEither.hpp b/framework/common/tcuEither.hpp
new file mode 100644
index 0000000..47a3c49
--- /dev/null
+++ b/framework/common/tcuEither.hpp
@@ -0,0 +1,268 @@
+#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
diff --git a/modules/internal/ditFrameworkTests.cpp b/modules/internal/ditFrameworkTests.cpp
index 1061668..ec8f241 100644
--- a/modules/internal/ditFrameworkTests.cpp
+++ b/modules/internal/ditFrameworkTests.cpp
@@ -23,6 +23,7 @@
 
 #include "ditFrameworkTests.hpp"
 #include "tcuFloatFormat.hpp"
+#include "tcuEither.hpp"
 #include "tcuTestLog.hpp"
 #include "tcuCommandLine.hpp"
 
@@ -556,6 +557,8 @@
 	{
 		addChild(new SelfCheckCase(m_testCtx, "float_format","tcu::FloatFormat_selfTest()",
 								   tcu::FloatFormat_selfTest));
+		addChild(new SelfCheckCase(m_testCtx, "either","tcu::Either_selfTest()",
+								   tcu::Either_selfTest));
 	}
 };