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(uint64_t value_)44 Hex(uint64_t value_) : value(value_)
45 {
46 }
47
toStream(std::ostream & stream) const48 std::ostream &toStream(std::ostream &stream) const
49 {
50 DE_STATIC_ASSERT(0 < NumDigits && NumDigits <= 16);
51
52 return stream << "0x" << std::right << std::setfill('0') << std::setw(NumDigits) << std::hex << value;
53 }
54
toString(void) const55 std::string toString(void) const
56 {
57 std::stringstream stream;
58
59 toStream(stream);
60 return stream.str();
61 }
62
63 private:
64 uint64_t value;
65 };
66
67 template <size_t NumDigits>
operator <<(std::ostream & stream,tcu::Format::Hex<NumDigits> hex)68 std::ostream &operator<<(std::ostream &stream, tcu::Format::Hex<NumDigits> hex)
69 {
70 return hex.toStream(stream);
71 }
72
73 // Bitfield formatter.
74
75 class BitDesc
76 {
77 public:
78 uint64_t bit;
79 const char *name;
80
BitDesc(uint64_t bit_,const char * name_)81 BitDesc(uint64_t bit_, const char *name_) : bit(bit_), name(name_)
82 {
83 }
84 };
85
86 #define TCU_BIT_DESC(BIT) tcu::Format::BitDesc(BIT, #BIT)
87
88 template <size_t BitfieldSize>
89 class Bitfield
90 {
91 public:
Bitfield(uint64_t value,const BitDesc * begin,const BitDesc * end)92 Bitfield(uint64_t value, const BitDesc *begin, const BitDesc *end) : m_value(value), m_begin(begin), m_end(end)
93 {
94 }
95
toStream(std::ostream & stream)96 std::ostream &toStream(std::ostream &stream)
97 {
98 uint64_t 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 uint64_t m_value;
122 const BitDesc *m_begin;
123 const BitDesc *m_end;
124 };
125
126 template <size_t 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, size_t 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) : m_getName(getName), m_value(value)
141 {
142 }
143
toStream(std::ostream & stream) const144 std::ostream &toStream(std::ostream &stream) const
145 {
146 const char *name = m_getName(m_value);
147 if (name)
148 return stream << name;
149 else
150 return stream << Hex<NumBytes * 2>((uint64_t)m_value);
151 }
152
toString(void) const153 std::string toString(void) const
154 {
155 const char *name = m_getName(m_value);
156 if (name)
157 return std::string(name);
158 else
159 return Hex<NumBytes * 2>((uint64_t)m_value).toString();
160 }
161
162 private:
163 const GetNameFunc m_getName;
164 const T m_value;
165 };
166
167 template <typename T, size_t NumBytes>
operator <<(std::ostream & stream,const Enum<T,NumBytes> & fmt)168 inline std::ostream &operator<<(std::ostream &stream, const Enum<T, NumBytes> &fmt)
169 {
170 return fmt.toStream(stream);
171 }
172
173 // Array formatters.
174
175 template <typename Iterator>
176 class Array
177 {
178 public:
179 Iterator begin;
180 Iterator end;
181
Array(const Iterator & begin_,const Iterator & end_)182 Array(const Iterator &begin_, const Iterator &end_) : begin(begin_), end(end_)
183 {
184 }
185 };
186
187 template <typename T>
188 class ArrayPointer
189 {
190 public:
191 const T *arr;
192 int size;
193
ArrayPointer(const T * arr_,int size_)194 ArrayPointer(const T *arr_, int size_) : arr(arr_), size(size_)
195 {
196 }
197 };
198
199 template <typename Iterator>
operator <<(std::ostream & str,const Array<Iterator> & fmt)200 std::ostream &operator<<(std::ostream &str, const Array<Iterator> &fmt)
201 {
202 str << "{ ";
203 for (Iterator cur = fmt.begin; cur != fmt.end; ++cur)
204 {
205 if (cur != fmt.begin)
206 str << ", ";
207 str << *cur;
208 }
209 str << " }";
210 return str;
211 }
212
213 template <typename T>
operator <<(std::ostream & str,const ArrayPointer<T> & fmt)214 std::ostream &operator<<(std::ostream &str, const ArrayPointer<T> &fmt)
215 {
216 if (fmt.arr != DE_NULL)
217 return str << Array<const T *>(fmt.arr, fmt.arr + fmt.size);
218 else
219 return str << "(null)";
220 }
221
222 // Hex format iterator (useful for combining with ArrayFormatter).
223 // \todo [2012-10-30 pyry] Implement more generic format iterator.
224
225 template <typename T, typename Iterator = const T *>
226 class HexIterator
227 {
228 public:
HexIterator(Iterator iter)229 HexIterator(Iterator iter) : m_iter(iter)
230 {
231 }
232
operator ++(void)233 HexIterator<T, Iterator> &operator++(void)
234 {
235 ++m_iter;
236 return *this;
237 }
operator ++(int)238 HexIterator<T, Iterator> operator++(int)
239 {
240 return HexIterator(m_iter++);
241 }
242
operator ==(const HexIterator<T,Iterator> & other) const243 bool operator==(const HexIterator<T, Iterator> &other) const
244 {
245 return m_iter == other.m_iter;
246 }
operator !=(const HexIterator<T,Iterator> & other) const247 bool operator!=(const HexIterator<T, Iterator> &other) const
248 {
249 return m_iter != other.m_iter;
250 }
251
252 #if !defined(__INTELLISENSE__)
253 // Intellisense in VS2013 crashes when parsing this.
operator *(void) const254 Hex<sizeof(T) * 2> operator*(void) const
255 {
256 return Hex<sizeof(T) * 2>(*m_iter);
257 }
258 #endif
259
260 private:
261 Iterator m_iter;
262 };
263
264 } // namespace Format
265
266 template <int Bits>
makeMask64(void)267 inline uint64_t makeMask64(void)
268 {
269 return (1ull << Bits) - 1;
270 }
271 template <>
makeMask64(void)272 inline uint64_t makeMask64<64>(void)
273 {
274 return ~0ull;
275 }
276 template <typename T>
toUint64(T value)277 inline uint64_t toUint64(T value)
278 {
279 return (uint64_t)value & makeMask64<sizeof(T) * 8>();
280 }
281
282 /** Format value as hexadecimal number. */
283 template <size_t NumDigits, typename T>
toHex(T value)284 inline Format::Hex<NumDigits> toHex(T value)
285 {
286 return Format::Hex<NumDigits>(toUint64(value));
287 }
288
289 /** Format value as hexadecimal number. */
290 template <typename T>
toHex(T value)291 inline Format::Hex<sizeof(T) * 2> toHex(T value)
292 {
293 return Format::Hex<sizeof(T) * 2>(toUint64(value));
294 }
295
296 /** Decode and format bitfield. */
297 template <typename T, size_t Size>
formatBitfield(T value,const Format::BitDesc (& desc)[Size])298 inline Format::Bitfield<sizeof(T) * 8> formatBitfield(T value, const Format::BitDesc (&desc)[Size])
299 {
300 return Format::Bitfield<sizeof(T) * 8>((uint64_t)value, &desc[0], &desc[Size]);
301 }
302
303 /** Format array contents. */
304 template <typename Iterator>
formatArray(const Iterator & begin,const Iterator & end)305 inline Format::Array<Iterator> formatArray(const Iterator &begin, const Iterator &end)
306 {
307 return Format::Array<Iterator>(begin, end);
308 }
309
310 /** Format array contents. */
311 template <typename T>
formatArray(const T * arr,int size)312 inline Format::ArrayPointer<T> formatArray(const T *arr, int size)
313 {
314 return Format::ArrayPointer<T>(arr, size);
315 }
316
317 /** Format array contents. */
318 template <typename T, int Size>
formatArray(const T (& arr)[Size])319 inline Format::ArrayPointer<T> formatArray(const T (&arr)[Size])
320 {
321 return Format::ArrayPointer<T>(arr, Size);
322 }
323
324 } // namespace tcu
325
326 #endif // _TCUFORMATUTIL_HPP
327