Home | History | Annotate | Download | only in common
      1 #ifndef _TCUFORMATUTIL_HPP
      2 #define _TCUFORMATUTIL_HPP
      3 /*-------------------------------------------------------------------------
      4  * drawElements Quality Program Tester Core
      5  * ----------------------------------------
      6  *
      7  * Copyright 2014 The Android Open Source Project
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief String format utilities.
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "tcuDefs.hpp"
     27 #include "deString.h"
     28 
     29 #include <ostream>
     30 #include <string>
     31 
     32 namespace tcu
     33 {
     34 namespace Format
     35 {
     36 
     37 // Hexadecimal value formatter.
     38 template <int NumDigits>
     39 class Hex
     40 {
     41 public:
     42 	Hex (deUint64 value_) : value(value_) {}
     43 
     44 	std::ostream& toStream (std::ostream& stream) const
     45 	{
     46 		return stream << this->toString();
     47 	}
     48 
     49 	std::string toString (void) const
     50 	{
     51 		DE_STATIC_ASSERT(0 < NumDigits && NumDigits <= 16);
     52 
     53 		const char longFmt[]	= {'0', 'x', '%', '0', '0' + NumDigits/10, '0' + NumDigits%10, 'l', 'l', 'x', 0};
     54 		const char shortFmt[]	= {'0', 'x', '%', '0', '0' + NumDigits, 'l', 'l', 'x', 0};
     55 
     56 		char buf[sizeof(deUint64)*2 + 3];
     57 		deSprintf(buf, sizeof(buf), NumDigits > 9 ? longFmt : shortFmt, value);
     58 
     59 		return std::string(buf);
     60 	}
     61 
     62 private:
     63 	deUint64 value;
     64 };
     65 
     66 template <int NumDigits>
     67 std::ostream& operator<< (std::ostream& stream, tcu::Format::Hex<NumDigits> hex)
     68 {
     69 	return hex.toStream(stream);
     70 }
     71 
     72 // Bitfield formatter.
     73 
     74 class BitDesc
     75 {
     76 public:
     77 	deUint64	bit;
     78 	const char*	name;
     79 
     80 	BitDesc (deUint64 bit_, const char* name_) : bit(bit_), name(name_) {}
     81 };
     82 
     83 #define TCU_BIT_DESC(BIT) tcu::Format::BitDesc(BIT, #BIT)
     84 
     85 template <int BitfieldSize>
     86 class Bitfield
     87 {
     88 public:
     89 	Bitfield (deUint64 value, const BitDesc* begin, const BitDesc* end)
     90 		: m_value	(value)
     91 		, m_begin	(begin)
     92 		, m_end		(end)
     93 	{
     94 	}
     95 
     96 	std::ostream& toStream (std::ostream& stream)
     97 	{
     98 		deUint64 bitsLeft = m_value;
     99 		for (const BitDesc* curDesc = m_begin; curDesc != m_end; curDesc++)
    100 		{
    101 			if (curDesc->bit & bitsLeft)
    102 			{
    103 				if (bitsLeft != m_value)
    104 					stream << "|";
    105 				stream << curDesc->name;
    106 				bitsLeft ^= curDesc->bit;
    107 			}
    108 		}
    109 
    110 		if (bitsLeft != 0)
    111 		{
    112 			if (bitsLeft != m_value)
    113 				stream << "|";
    114 			stream << Hex<BitfieldSize/4>(bitsLeft);
    115 		}
    116 
    117 		return stream;
    118 	}
    119 
    120 private:
    121 	deUint64			m_value;
    122 	const BitDesc*		m_begin;
    123 	const BitDesc*		m_end;
    124 };
    125 
    126 template <int BitfieldSize>
    127 inline std::ostream& operator<< (std::ostream& stream, Bitfield<BitfieldSize> decoder)
    128 {
    129 	return decoder.toStream(stream);
    130 }
    131 
    132 // Enum formatter.
    133 // \todo [2012-10-30 pyry] Use template for GetName.
    134 
    135 class Enum
    136 {
    137 public:
    138 	typedef const char* (*GetNameFunc) (int value);
    139 
    140 	Enum (GetNameFunc getName, int value)
    141 		: m_getName	(getName)
    142 		, m_value	(value)
    143 	{
    144 	}
    145 
    146 	std::ostream& toStream (std::ostream& stream) const
    147 	{
    148 		const char* name = m_getName(m_value);
    149 		if (name)
    150 			return stream << name;
    151 		else
    152 			return stream << Hex<sizeof(int)*2>(m_value);
    153 	}
    154 
    155 	std::string toString (void) const
    156 	{
    157 		const char* name = m_getName(m_value);
    158 		if (name)
    159 			return std::string(name);
    160 		else
    161 			return Hex<sizeof(int)*2>(m_value).toString();
    162 	}
    163 
    164 private:
    165 	GetNameFunc		m_getName;
    166 	int				m_value;
    167 };
    168 
    169 inline std::ostream& operator<< (std::ostream& stream, Enum fmt) { return fmt.toStream(stream); }
    170 
    171 // Array formatters.
    172 
    173 template <typename Iterator>
    174 class Array
    175 {
    176 public:
    177 	Iterator	begin;
    178 	Iterator	end;
    179 
    180 	Array (const Iterator& begin_, const Iterator& end_) : begin(begin_), end(end_) {}
    181 };
    182 
    183 template <typename T>
    184 class ArrayPointer
    185 {
    186 public:
    187 	const T*	arr;
    188 	int			size;
    189 
    190 	ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {}
    191 };
    192 
    193 template <typename Iterator>
    194 std::ostream& operator<< (std::ostream& str, const Array<Iterator>& fmt)
    195 {
    196 	str << "{ ";
    197 	for (Iterator cur = fmt.begin; cur != fmt.end; ++cur)
    198 	{
    199 		if (cur != fmt.begin)
    200 			str << ", ";
    201 		str << *cur;
    202 	}
    203 	str << " }";
    204 	return str;
    205 }
    206 
    207 template <typename T>
    208 std::ostream& operator<< (std::ostream& str, const ArrayPointer<T>& fmt)
    209 {
    210 	if (fmt.arr != DE_NULL)
    211 		return str << Array<const T*>(fmt.arr, fmt.arr+fmt.size);
    212 	else
    213 		return str << "(null)";
    214 }
    215 
    216 // Hex format iterator (useful for combining with ArrayFormatter).
    217 // \todo [2012-10-30 pyry] Implement more generic format iterator.
    218 
    219 template <typename T, typename Iterator = const T*>
    220 class HexIterator
    221 {
    222 public:
    223 										HexIterator			(Iterator iter) : m_iter(iter) {}
    224 
    225 	HexIterator<T, Iterator>&			operator++			(void)	{ ++m_iter; return *this;		}
    226 	HexIterator<T, Iterator>			operator++			(int)	{ return HexIterator(m_iter++);	}
    227 
    228 	bool								operator==			(const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; }
    229 	bool								operator!=			(const HexIterator<T, Iterator>& other) const { return m_iter != other.m_iter; }
    230 
    231 #if !defined(__INTELLISENSE__)
    232 	// Intellisense in VS2013 crashes when parsing this.
    233 	Hex<sizeof(T)*2>					operator*			(void) const { return Hex<sizeof(T)*2>(*m_iter);	}
    234 #endif
    235 
    236 private:
    237 	Iterator							m_iter;
    238 };
    239 
    240 } // Format
    241 
    242 template <int Bits>		inline deUint64 makeMask64			(void)				{ return (1ull<<Bits)-1;								}
    243 template <>				inline deUint64 makeMask64<64>		(void)				{ return ~0ull;											}
    244 template <typename T>	inline deUint64	toUint64			(T value)			{ return (deUint64)value & makeMask64<sizeof(T)*8>();	}
    245 
    246 /** Format value as hexadecimal number. */
    247 template <int NumDigits, typename T>
    248 inline Format::Hex<NumDigits> toHex (T value)
    249 {
    250 	return Format::Hex<NumDigits>(toUint64(value));
    251 }
    252 
    253 /** Format value as hexadecimal number. */
    254 template <typename T>
    255 inline Format::Hex<sizeof(T)*2> toHex (T value)
    256 {
    257 	return Format::Hex<sizeof(T)*2>(toUint64(value));
    258 }
    259 
    260 /** Decode and format bitfield. */
    261 template <typename T, size_t Size>
    262 inline Format::Bitfield<sizeof(T)*8> formatBitfield (T value, const Format::BitDesc (&desc)[Size])
    263 {
    264 	return Format::Bitfield<sizeof(T)*8>((deUint64)value, &desc[0], &desc[Size]);
    265 }
    266 
    267 /** Format array contents. */
    268 template <typename Iterator>
    269 inline Format::Array<Iterator> formatArray (const Iterator& begin, const Iterator& end)
    270 {
    271 	return Format::Array<Iterator>(begin, end);
    272 }
    273 
    274 /** Format array contents. */
    275 template <typename T>
    276 inline Format::ArrayPointer<T> formatArray (const T* arr, int size)
    277 {
    278 	return Format::ArrayPointer<T>(arr, size);
    279 }
    280 
    281 } // tcu
    282 
    283 #endif // _TCUFORMATUTIL_HPP
    284