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 <size_t 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 <size_t 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 <size_t 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 <size_t 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 template <typename T, size_t NumBytes = sizeof(T)>
    135 class Enum
    136 {
    137 public:
    138 	typedef const char* (*GetNameFunc) (T value);
    139 
    140 	Enum (GetNameFunc getName, T 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<NumBytes*2>((deUint64)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<NumBytes*2>((deUint64)m_value).toString();
    162 	}
    163 
    164 private:
    165 	const GetNameFunc	m_getName;
    166 	const T				m_value;
    167 };
    168 
    169 template <typename T, size_t NumBytes>
    170 inline std::ostream& operator<< (std::ostream& stream, const Enum<T, NumBytes>& fmt) { return fmt.toStream(stream); }
    171 
    172 // Array formatters.
    173 
    174 template <typename Iterator>
    175 class Array
    176 {
    177 public:
    178 	Iterator	begin;
    179 	Iterator	end;
    180 
    181 	Array (const Iterator& begin_, const Iterator& end_) : begin(begin_), end(end_) {}
    182 };
    183 
    184 template <typename T>
    185 class ArrayPointer
    186 {
    187 public:
    188 	const T*	arr;
    189 	int			size;
    190 
    191 	ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {}
    192 };
    193 
    194 template <typename Iterator>
    195 std::ostream& operator<< (std::ostream& str, const Array<Iterator>& fmt)
    196 {
    197 	str << "{ ";
    198 	for (Iterator cur = fmt.begin; cur != fmt.end; ++cur)
    199 	{
    200 		if (cur != fmt.begin)
    201 			str << ", ";
    202 		str << *cur;
    203 	}
    204 	str << " }";
    205 	return str;
    206 }
    207 
    208 template <typename T>
    209 std::ostream& operator<< (std::ostream& str, const ArrayPointer<T>& fmt)
    210 {
    211 	if (fmt.arr != DE_NULL)
    212 		return str << Array<const T*>(fmt.arr, fmt.arr+fmt.size);
    213 	else
    214 		return str << "(null)";
    215 }
    216 
    217 // Hex format iterator (useful for combining with ArrayFormatter).
    218 // \todo [2012-10-30 pyry] Implement more generic format iterator.
    219 
    220 template <typename T, typename Iterator = const T*>
    221 class HexIterator
    222 {
    223 public:
    224 										HexIterator			(Iterator iter) : m_iter(iter) {}
    225 
    226 	HexIterator<T, Iterator>&			operator++			(void)	{ ++m_iter; return *this;		}
    227 	HexIterator<T, Iterator>			operator++			(int)	{ return HexIterator(m_iter++);	}
    228 
    229 	bool								operator==			(const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; }
    230 	bool								operator!=			(const HexIterator<T, Iterator>& other) const { return m_iter != other.m_iter; }
    231 
    232 #if !defined(__INTELLISENSE__)
    233 	// Intellisense in VS2013 crashes when parsing this.
    234 	Hex<sizeof(T)*2>					operator*			(void) const { return Hex<sizeof(T)*2>(*m_iter);	}
    235 #endif
    236 
    237 private:
    238 	Iterator							m_iter;
    239 };
    240 
    241 } // Format
    242 
    243 template <int Bits>		inline deUint64 makeMask64			(void)				{ return (1ull<<Bits)-1;								}
    244 template <>				inline deUint64 makeMask64<64>		(void)				{ return ~0ull;											}
    245 template <typename T>	inline deUint64	toUint64			(T value)			{ return (deUint64)value & makeMask64<sizeof(T)*8>();	}
    246 
    247 /** Format value as hexadecimal number. */
    248 template <size_t NumDigits, typename T>
    249 inline Format::Hex<NumDigits> toHex (T value)
    250 {
    251 	return Format::Hex<NumDigits>(toUint64(value));
    252 }
    253 
    254 /** Format value as hexadecimal number. */
    255 template <typename T>
    256 inline Format::Hex<sizeof(T)*2> toHex (T value)
    257 {
    258 	return Format::Hex<sizeof(T)*2>(toUint64(value));
    259 }
    260 
    261 /** Decode and format bitfield. */
    262 template <typename T, size_t Size>
    263 inline Format::Bitfield<sizeof(T)*8> formatBitfield (T value, const Format::BitDesc (&desc)[Size])
    264 {
    265 	return Format::Bitfield<sizeof(T)*8>((deUint64)value, &desc[0], &desc[Size]);
    266 }
    267 
    268 /** Format array contents. */
    269 template <typename Iterator>
    270 inline Format::Array<Iterator> formatArray (const Iterator& begin, const Iterator& end)
    271 {
    272 	return Format::Array<Iterator>(begin, end);
    273 }
    274 
    275 /** Format array contents. */
    276 template <typename T>
    277 inline Format::ArrayPointer<T> formatArray (const T* arr, int size)
    278 {
    279 	return Format::ArrayPointer<T>(arr, size);
    280 }
    281 
    282 /** Format array contents. */
    283 template <typename T, int Size>
    284 inline Format::ArrayPointer<T> formatArray (const T (&arr)[Size])
    285 {
    286 	return Format::ArrayPointer<T>(arr, Size);
    287 }
    288 
    289 } // tcu
    290 
    291 #endif // _TCUFORMATUTIL_HPP
    292