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