#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>
|
|
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
|
{
|
return stream << this->toString();
|
}
|
|
std::string toString (void) const
|
{
|
DE_STATIC_ASSERT(0 < NumDigits && NumDigits <= 16);
|
|
const char longFmt[] = {'0', 'x', '%', '0', '0' + NumDigits/10, '0' + NumDigits%10, 'l', 'l', 'x', 0};
|
const char shortFmt[] = {'0', 'x', '%', '0', '0' + NumDigits, 'l', 'l', 'x', 0};
|
|
char buf[sizeof(deUint64)*2 + 3];
|
deSprintf(buf, sizeof(buf), NumDigits > 9 ? longFmt : shortFmt, value);
|
|
return std::string(buf);
|
}
|
|
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
|