You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
6.0 KiB
269 lines
6.0 KiB
#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;
|
|
};
|
|
} DE_WARN_UNUSED_TYPE;
|
|
|
|
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
|