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
135 class Enum
136 {
137 public:
138 typedef const char* (*GetNameFunc) (int value);
139
Enum(GetNameFunc getName,int value)140 Enum (GetNameFunc getName, int 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<sizeof(int)*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<sizeof(int)*2>(m_value).toString();
162 }
163
164 private:
165 GetNameFunc m_getName;
166 int m_value;
167 };
168
operator <<(std::ostream & stream,Enum fmt)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
Array(const Iterator & begin_,const Iterator & end_)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
ArrayPointer(const T * arr_,int size_)190 ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {}
191 };
192
193 template <typename Iterator>
operator <<(std::ostream & str,const Array<Iterator> & fmt)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>
operator <<(std::ostream & str,const ArrayPointer<T> & fmt)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:
HexIterator(Iterator iter)223 HexIterator (Iterator iter) : m_iter(iter) {}
224
operator ++(void)225 HexIterator<T, Iterator>& operator++ (void) { ++m_iter; return *this; }
operator ++(int)226 HexIterator<T, Iterator> operator++ (int) { return HexIterator(m_iter++); }
227
operator ==(const HexIterator<T,Iterator> & other) const228 bool operator== (const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; }
operator !=(const HexIterator<T,Iterator> & other) const229 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.
operator *(void) const233 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
makeMask64(void)242 template <int Bits> inline deUint64 makeMask64 (void) { return (1ull<<Bits)-1; }
makeMask64(void)243 template <> inline deUint64 makeMask64<64> (void) { return ~0ull; }
toUint64(T value)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>
toHex(T value)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>
toHex(T value)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>
formatBitfield(T value,const Format::BitDesc (& desc)[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>
formatArray(const Iterator & begin,const Iterator & end)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>
formatArray(const T * arr,int size)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