296 lines
6.8 KiB
C++
296 lines
6.8 KiB
C++
#ifndef _TCUFORMATUTIL_HPP
|
|
#define _TCUFORMATUTIL_HPP
|
|
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program Tester Core
|
|
* ----------------------------------------
|
|
*
|
|
* Copyright 2014 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 String format utilities.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "tcuDefs.hpp"
|
|
#include "deString.h"
|
|
|
|
#include <ostream>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
|
|
namespace tcu
|
|
{
|
|
namespace Format
|
|
{
|
|
|
|
// Hexadecimal value formatter.
|
|
template <size_t NumDigits>
|
|
class Hex
|
|
{
|
|
public:
|
|
Hex (deUint64 value_) : value(value_) {}
|
|
|
|
std::ostream& toStream (std::ostream& stream) const
|
|
{
|
|
DE_STATIC_ASSERT(0 < NumDigits && NumDigits <= 16);
|
|
|
|
return stream << "0x"
|
|
<< std::right
|
|
<< std::setfill('0')
|
|
<< std::setw(NumDigits)
|
|
<< std::hex
|
|
<< value;
|
|
}
|
|
|
|
std::string toString (void) const
|
|
{
|
|
std::stringstream stream;
|
|
|
|
toStream(stream);
|
|
return stream.str();
|
|
}
|
|
|
|
private:
|
|
deUint64 value;
|
|
};
|
|
|
|
template <size_t NumDigits>
|
|
std::ostream& operator<< (std::ostream& stream, tcu::Format::Hex<NumDigits> hex)
|
|
{
|
|
return hex.toStream(stream);
|
|
}
|
|
|
|
// Bitfield formatter.
|
|
|
|
class BitDesc
|
|
{
|
|
public:
|
|
deUint64 bit;
|
|
const char* name;
|
|
|
|
BitDesc (deUint64 bit_, const char* name_) : bit(bit_), name(name_) {}
|
|
};
|
|
|
|
#define TCU_BIT_DESC(BIT) tcu::Format::BitDesc(BIT, #BIT)
|
|
|
|
template <size_t BitfieldSize>
|
|
class Bitfield
|
|
{
|
|
public:
|
|
Bitfield (deUint64 value, const BitDesc* begin, const BitDesc* end)
|
|
: m_value (value)
|
|
, m_begin (begin)
|
|
, m_end (end)
|
|
{
|
|
}
|
|
|
|
std::ostream& toStream (std::ostream& stream)
|
|
{
|
|
deUint64 bitsLeft = m_value;
|
|
for (const BitDesc* curDesc = m_begin; curDesc != m_end; curDesc++)
|
|
{
|
|
if (curDesc->bit & bitsLeft)
|
|
{
|
|
if (bitsLeft != m_value)
|
|
stream << "|";
|
|
stream << curDesc->name;
|
|
bitsLeft ^= curDesc->bit;
|
|
}
|
|
}
|
|
|
|
if (bitsLeft != 0)
|
|
{
|
|
if (bitsLeft != m_value)
|
|
stream << "|";
|
|
stream << Hex<BitfieldSize/4>(bitsLeft);
|
|
}
|
|
|
|
return stream;
|
|
}
|
|
|
|
private:
|
|
deUint64 m_value;
|
|
const BitDesc* m_begin;
|
|
const BitDesc* m_end;
|
|
};
|
|
|
|
template <size_t BitfieldSize>
|
|
inline std::ostream& operator<< (std::ostream& stream, Bitfield<BitfieldSize> decoder)
|
|
{
|
|
return decoder.toStream(stream);
|
|
}
|
|
|
|
// Enum formatter.
|
|
// \todo [2012-10-30 pyry] Use template for GetName.
|
|
template <typename T, size_t NumBytes = sizeof(T)>
|
|
class Enum
|
|
{
|
|
public:
|
|
typedef const char* (*GetNameFunc) (T value);
|
|
|
|
Enum (GetNameFunc getName, T value)
|
|
: m_getName (getName)
|
|
, m_value (value)
|
|
{
|
|
}
|
|
|
|
std::ostream& toStream (std::ostream& stream) const
|
|
{
|
|
const char* name = m_getName(m_value);
|
|
if (name)
|
|
return stream << name;
|
|
else
|
|
return stream << Hex<NumBytes*2>((deUint64)m_value);
|
|
}
|
|
|
|
std::string toString (void) const
|
|
{
|
|
const char* name = m_getName(m_value);
|
|
if (name)
|
|
return std::string(name);
|
|
else
|
|
return Hex<NumBytes*2>((deUint64)m_value).toString();
|
|
}
|
|
|
|
private:
|
|
const GetNameFunc m_getName;
|
|
const T m_value;
|
|
};
|
|
|
|
template <typename T, size_t NumBytes>
|
|
inline std::ostream& operator<< (std::ostream& stream, const Enum<T, NumBytes>& fmt) { return fmt.toStream(stream); }
|
|
|
|
// Array formatters.
|
|
|
|
template <typename Iterator>
|
|
class Array
|
|
{
|
|
public:
|
|
Iterator begin;
|
|
Iterator end;
|
|
|
|
Array (const Iterator& begin_, const Iterator& end_) : begin(begin_), end(end_) {}
|
|
};
|
|
|
|
template <typename T>
|
|
class ArrayPointer
|
|
{
|
|
public:
|
|
const T* arr;
|
|
int size;
|
|
|
|
ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {}
|
|
};
|
|
|
|
template <typename Iterator>
|
|
std::ostream& operator<< (std::ostream& str, const Array<Iterator>& fmt)
|
|
{
|
|
str << "{ ";
|
|
for (Iterator cur = fmt.begin; cur != fmt.end; ++cur)
|
|
{
|
|
if (cur != fmt.begin)
|
|
str << ", ";
|
|
str << *cur;
|
|
}
|
|
str << " }";
|
|
return str;
|
|
}
|
|
|
|
template <typename T>
|
|
std::ostream& operator<< (std::ostream& str, const ArrayPointer<T>& fmt)
|
|
{
|
|
if (fmt.arr != DE_NULL)
|
|
return str << Array<const T*>(fmt.arr, fmt.arr+fmt.size);
|
|
else
|
|
return str << "(null)";
|
|
}
|
|
|
|
// Hex format iterator (useful for combining with ArrayFormatter).
|
|
// \todo [2012-10-30 pyry] Implement more generic format iterator.
|
|
|
|
template <typename T, typename Iterator = const T*>
|
|
class HexIterator
|
|
{
|
|
public:
|
|
HexIterator (Iterator iter) : m_iter(iter) {}
|
|
|
|
HexIterator<T, Iterator>& operator++ (void) { ++m_iter; return *this; }
|
|
HexIterator<T, Iterator> operator++ (int) { return HexIterator(m_iter++); }
|
|
|
|
bool operator== (const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; }
|
|
bool operator!= (const HexIterator<T, Iterator>& other) const { return m_iter != other.m_iter; }
|
|
|
|
#if !defined(__INTELLISENSE__)
|
|
// Intellisense in VS2013 crashes when parsing this.
|
|
Hex<sizeof(T)*2> operator* (void) const { return Hex<sizeof(T)*2>(*m_iter); }
|
|
#endif
|
|
|
|
private:
|
|
Iterator m_iter;
|
|
};
|
|
|
|
} // Format
|
|
|
|
template <int Bits> inline deUint64 makeMask64 (void) { return (1ull<<Bits)-1; }
|
|
template <> inline deUint64 makeMask64<64> (void) { return ~0ull; }
|
|
template <typename T> inline deUint64 toUint64 (T value) { return (deUint64)value & makeMask64<sizeof(T)*8>(); }
|
|
|
|
/** Format value as hexadecimal number. */
|
|
template <size_t NumDigits, typename T>
|
|
inline Format::Hex<NumDigits> toHex (T value)
|
|
{
|
|
return Format::Hex<NumDigits>(toUint64(value));
|
|
}
|
|
|
|
/** Format value as hexadecimal number. */
|
|
template <typename T>
|
|
inline Format::Hex<sizeof(T)*2> toHex (T value)
|
|
{
|
|
return Format::Hex<sizeof(T)*2>(toUint64(value));
|
|
}
|
|
|
|
/** Decode and format bitfield. */
|
|
template <typename T, size_t Size>
|
|
inline Format::Bitfield<sizeof(T)*8> formatBitfield (T value, const Format::BitDesc (&desc)[Size])
|
|
{
|
|
return Format::Bitfield<sizeof(T)*8>((deUint64)value, &desc[0], &desc[Size]);
|
|
}
|
|
|
|
/** Format array contents. */
|
|
template <typename Iterator>
|
|
inline Format::Array<Iterator> formatArray (const Iterator& begin, const Iterator& end)
|
|
{
|
|
return Format::Array<Iterator>(begin, end);
|
|
}
|
|
|
|
/** Format array contents. */
|
|
template <typename T>
|
|
inline Format::ArrayPointer<T> formatArray (const T* arr, int size)
|
|
{
|
|
return Format::ArrayPointer<T>(arr, size);
|
|
}
|
|
|
|
/** Format array contents. */
|
|
template <typename T, int Size>
|
|
inline Format::ArrayPointer<T> formatArray (const T (&arr)[Size])
|
|
{
|
|
return Format::ArrayPointer<T>(arr, Size);
|
|
}
|
|
|
|
} // tcu
|
|
|
|
#endif // _TCUFORMATUTIL_HPP
|