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:
Hex(deUint64 value_)42 	Hex (deUint64 value_) : value(value_) {}
43 
toStream(std::ostream & stream) const44 	std::ostream& toStream (std::ostream& stream) const
45 	{
46 		return stream << this->toString();
47 	}
48 
toString(void) const49 	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>
operator <<(std::ostream & stream,tcu::Format::Hex<NumDigits> hex)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 
BitDesc(deUint64 bit_,const char * name_)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:
Bitfield(deUint64 value,const BitDesc * begin,const BitDesc * end)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 
toStream(std::ostream & stream)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>
operator <<(std::ostream & stream,Bitfield<BitfieldSize> decoder)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, int NumBytes = sizeof(T)>
135 class Enum
136 {
137 public:
138 	typedef const char* (*GetNameFunc) (T value);
139 
Enum(GetNameFunc getName,T value)140 	Enum (GetNameFunc getName, T value)
141 		: m_getName	(getName)
142 		, m_value (value)
143 	{
144 	}
145 
toStream(std::ostream & stream) const146 	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>(m_value);
153 	}
154 
toString(void) const155 	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>(m_value).toString();
162 	}
163 
164 private:
165 	const GetNameFunc	m_getName;
166 	const T				m_value;
167 };
168 
169 template <typename T, int NumBytes>
operator <<(std::ostream & stream,const Enum<T,NumBytes> & fmt)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 
Array(const Iterator & begin_,const Iterator & end_)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 
ArrayPointer(const T * arr_,int size_)191 	ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {}
192 };
193 
194 template <typename Iterator>
operator <<(std::ostream & str,const Array<Iterator> & fmt)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>
operator <<(std::ostream & str,const ArrayPointer<T> & fmt)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:
HexIterator(Iterator iter)224 										HexIterator			(Iterator iter) : m_iter(iter) {}
225 
operator ++(void)226 	HexIterator<T, Iterator>&			operator++			(void)	{ ++m_iter; return *this;		}
operator ++(int)227 	HexIterator<T, Iterator>			operator++			(int)	{ return HexIterator(m_iter++);	}
228 
operator ==(const HexIterator<T,Iterator> & other) const229 	bool								operator==			(const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; }
operator !=(const HexIterator<T,Iterator> & other) const230 	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.
operator *(void) const234 	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 
makeMask64(void)243 template <int Bits>		inline deUint64 makeMask64			(void)				{ return (1ull<<Bits)-1;								}
makeMask64(void)244 template <>				inline deUint64 makeMask64<64>		(void)				{ return ~0ull;											}
toUint64(T value)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 <int NumDigits, typename T>
toHex(T value)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>
toHex(T value)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>
formatBitfield(T value,const Format::BitDesc (& desc)[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>
formatArray(const Iterator & begin,const Iterator & end)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>
formatArray(const T * arr,int size)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>
formatArray(const T (& arr)[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