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: 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 <int 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 <int 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 <int 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 135 class Enum 136 { 137 public: 138 typedef const char* (*GetNameFunc) (int value); 139 140 Enum (GetNameFunc getName, int 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<sizeof(int)*2>(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<sizeof(int)*2>(m_value).toString(); 162 } 163 164 private: 165 GetNameFunc m_getName; 166 int m_value; 167 }; 168 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 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 190 ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {} 191 }; 192 193 template <typename Iterator> 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> 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: 223 HexIterator (Iterator iter) : m_iter(iter) {} 224 225 HexIterator<T, Iterator>& operator++ (void) { ++m_iter; return *this; } 226 HexIterator<T, Iterator> operator++ (int) { return HexIterator(m_iter++); } 227 228 bool operator== (const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; } 229 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. 233 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 242 template <int Bits> inline deUint64 makeMask64 (void) { return (1ull<<Bits)-1; } 243 template <> inline deUint64 makeMask64<64> (void) { return ~0ull; } 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> 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> 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> 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> 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> 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