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 #include <sstream>
32 #include <iomanip>
33
34 namespace tcu
35 {
36 namespace Format
37 {
38
39 // Hexadecimal value formatter.
40 template <size_t NumDigits>
41 class Hex
42 {
43 public:
Hex(deUint64 value_)44 Hex (deUint64 value_) : value(value_) {}
45
toStream(std::ostream & stream) const46 std::ostream& toStream (std::ostream& stream) const
47 {
48 DE_STATIC_ASSERT(0 < NumDigits && NumDigits <= 16);
49
50 return stream << "0x"
51 << std::right
52 << std::setfill('0')
53 << std::setw(NumDigits)
54 << std::hex
55 << value;
56 }
57
toString(void) const58 std::string toString (void) const
59 {
60 std::stringstream stream;
61
62 toStream(stream);
63 return stream.str();
64 }
65
66 private:
67 deUint64 value;
68 };
69
70 template <size_t NumDigits>
operator <<(std::ostream & stream,tcu::Format::Hex<NumDigits> hex)71 std::ostream& operator<< (std::ostream& stream, tcu::Format::Hex<NumDigits> hex)
72 {
73 return hex.toStream(stream);
74 }
75
76 // Bitfield formatter.
77
78 class BitDesc
79 {
80 public:
81 deUint64 bit;
82 const char* name;
83
BitDesc(deUint64 bit_,const char * name_)84 BitDesc (deUint64 bit_, const char* name_) : bit(bit_), name(name_) {}
85 };
86
87 #define TCU_BIT_DESC(BIT) tcu::Format::BitDesc(BIT, #BIT)
88
89 template <size_t BitfieldSize>
90 class Bitfield
91 {
92 public:
Bitfield(deUint64 value,const BitDesc * begin,const BitDesc * end)93 Bitfield (deUint64 value, const BitDesc* begin, const BitDesc* end)
94 : m_value (value)
95 , m_begin (begin)
96 , m_end (end)
97 {
98 }
99
toStream(std::ostream & stream)100 std::ostream& toStream (std::ostream& stream)
101 {
102 deUint64 bitsLeft = m_value;
103 for (const BitDesc* curDesc = m_begin; curDesc != m_end; curDesc++)
104 {
105 if (curDesc->bit & bitsLeft)
106 {
107 if (bitsLeft != m_value)
108 stream << "|";
109 stream << curDesc->name;
110 bitsLeft ^= curDesc->bit;
111 }
112 }
113
114 if (bitsLeft != 0)
115 {
116 if (bitsLeft != m_value)
117 stream << "|";
118 stream << Hex<BitfieldSize/4>(bitsLeft);
119 }
120
121 return stream;
122 }
123
124 private:
125 deUint64 m_value;
126 const BitDesc* m_begin;
127 const BitDesc* m_end;
128 };
129
130 template <size_t BitfieldSize>
operator <<(std::ostream & stream,Bitfield<BitfieldSize> decoder)131 inline std::ostream& operator<< (std::ostream& stream, Bitfield<BitfieldSize> decoder)
132 {
133 return decoder.toStream(stream);
134 }
135
136 // Enum formatter.
137 // \todo [2012-10-30 pyry] Use template for GetName.
138 template <typename T, size_t NumBytes = sizeof(T)>
139 class Enum
140 {
141 public:
142 typedef const char* (*GetNameFunc) (T value);
143
Enum(GetNameFunc getName,T value)144 Enum (GetNameFunc getName, T value)
145 : m_getName (getName)
146 , m_value (value)
147 {
148 }
149
toStream(std::ostream & stream) const150 std::ostream& toStream (std::ostream& stream) const
151 {
152 const char* name = m_getName(m_value);
153 if (name)
154 return stream << name;
155 else
156 return stream << Hex<NumBytes*2>((deUint64)m_value);
157 }
158
toString(void) const159 std::string toString (void) const
160 {
161 const char* name = m_getName(m_value);
162 if (name)
163 return std::string(name);
164 else
165 return Hex<NumBytes*2>((deUint64)m_value).toString();
166 }
167
168 private:
169 const GetNameFunc m_getName;
170 const T m_value;
171 };
172
173 template <typename T, size_t NumBytes>
operator <<(std::ostream & stream,const Enum<T,NumBytes> & fmt)174 inline std::ostream& operator<< (std::ostream& stream, const Enum<T, NumBytes>& fmt) { return fmt.toStream(stream); }
175
176 // Array formatters.
177
178 template <typename Iterator>
179 class Array
180 {
181 public:
182 Iterator begin;
183 Iterator end;
184
Array(const Iterator & begin_,const Iterator & end_)185 Array (const Iterator& begin_, const Iterator& end_) : begin(begin_), end(end_) {}
186 };
187
188 template <typename T>
189 class ArrayPointer
190 {
191 public:
192 const T* arr;
193 int size;
194
ArrayPointer(const T * arr_,int size_)195 ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {}
196 };
197
198 template <typename Iterator>
operator <<(std::ostream & str,const Array<Iterator> & fmt)199 std::ostream& operator<< (std::ostream& str, const Array<Iterator>& fmt)
200 {
201 str << "{ ";
202 for (Iterator cur = fmt.begin; cur != fmt.end; ++cur)
203 {
204 if (cur != fmt.begin)
205 str << ", ";
206 str << *cur;
207 }
208 str << " }";
209 return str;
210 }
211
212 template <typename T>
operator <<(std::ostream & str,const ArrayPointer<T> & fmt)213 std::ostream& operator<< (std::ostream& str, const ArrayPointer<T>& fmt)
214 {
215 if (fmt.arr != DE_NULL)
216 return str << Array<const T*>(fmt.arr, fmt.arr+fmt.size);
217 else
218 return str << "(null)";
219 }
220
221 // Hex format iterator (useful for combining with ArrayFormatter).
222 // \todo [2012-10-30 pyry] Implement more generic format iterator.
223
224 template <typename T, typename Iterator = const T*>
225 class HexIterator
226 {
227 public:
HexIterator(Iterator iter)228 HexIterator (Iterator iter) : m_iter(iter) {}
229
operator ++(void)230 HexIterator<T, Iterator>& operator++ (void) { ++m_iter; return *this; }
operator ++(int)231 HexIterator<T, Iterator> operator++ (int) { return HexIterator(m_iter++); }
232
operator ==(const HexIterator<T,Iterator> & other) const233 bool operator== (const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; }
operator !=(const HexIterator<T,Iterator> & other) const234 bool operator!= (const HexIterator<T, Iterator>& other) const { return m_iter != other.m_iter; }
235
236 #if !defined(__INTELLISENSE__)
237 // Intellisense in VS2013 crashes when parsing this.
operator *(void) const238 Hex<sizeof(T)*2> operator* (void) const { return Hex<sizeof(T)*2>(*m_iter); }
239 #endif
240
241 private:
242 Iterator m_iter;
243 };
244
245 } // Format
246
makeMask64(void)247 template <int Bits> inline deUint64 makeMask64 (void) { return (1ull<<Bits)-1; }
makeMask64(void)248 template <> inline deUint64 makeMask64<64> (void) { return ~0ull; }
toUint64(T value)249 template <typename T> inline deUint64 toUint64 (T value) { return (deUint64)value & makeMask64<sizeof(T)*8>(); }
250
251 /** Format value as hexadecimal number. */
252 template <size_t NumDigits, typename T>
toHex(T value)253 inline Format::Hex<NumDigits> toHex (T value)
254 {
255 return Format::Hex<NumDigits>(toUint64(value));
256 }
257
258 /** Format value as hexadecimal number. */
259 template <typename T>
toHex(T value)260 inline Format::Hex<sizeof(T)*2> toHex (T value)
261 {
262 return Format::Hex<sizeof(T)*2>(toUint64(value));
263 }
264
265 /** Decode and format bitfield. */
266 template <typename T, size_t Size>
formatBitfield(T value,const Format::BitDesc (& desc)[Size])267 inline Format::Bitfield<sizeof(T)*8> formatBitfield (T value, const Format::BitDesc (&desc)[Size])
268 {
269 return Format::Bitfield<sizeof(T)*8>((deUint64)value, &desc[0], &desc[Size]);
270 }
271
272 /** Format array contents. */
273 template <typename Iterator>
formatArray(const Iterator & begin,const Iterator & end)274 inline Format::Array<Iterator> formatArray (const Iterator& begin, const Iterator& end)
275 {
276 return Format::Array<Iterator>(begin, end);
277 }
278
279 /** Format array contents. */
280 template <typename T>
formatArray(const T * arr,int size)281 inline Format::ArrayPointer<T> formatArray (const T* arr, int size)
282 {
283 return Format::ArrayPointer<T>(arr, size);
284 }
285
286 /** Format array contents. */
287 template <typename T, int Size>
formatArray(const T (& arr)[Size])288 inline Format::ArrayPointer<T> formatArray (const T (&arr)[Size])
289 {
290 return Format::ArrayPointer<T>(arr, Size);
291 }
292
293 } // tcu
294
295 #endif // _TCUFORMATUTIL_HPP
296