| #ifndef _TCUFORMATUTIL_HPP |
| #define _TCUFORMATUTIL_HPP |
| /*------------------------------------------------------------------------- |
| * drawElements Quality Program Tester Core |
| * ---------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief String format utilities. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuDefs.hpp" |
| #include "deString.h" |
| |
| #include <ostream> |
| #include <string> |
| #include <sstream> |
| #include <iomanip> |
| |
| namespace tcu |
| { |
| namespace Format |
| { |
| |
| // Hexadecimal value formatter. |
| template <size_t NumDigits> |
| class Hex |
| { |
| public: |
| Hex (deUint64 value_) : value(value_) {} |
| |
| std::ostream& toStream (std::ostream& stream) const |
| { |
| DE_STATIC_ASSERT(0 < NumDigits && NumDigits <= 16); |
| |
| return stream << "0x" |
| << std::right |
| << std::setfill('0') |
| << std::setw(NumDigits) |
| << std::hex |
| << value; |
| } |
| |
| std::string toString (void) const |
| { |
| std::stringstream stream; |
| |
| toStream(stream); |
| return stream.str(); |
| } |
| |
| private: |
| deUint64 value; |
| }; |
| |
| template <size_t NumDigits> |
| std::ostream& operator<< (std::ostream& stream, tcu::Format::Hex<NumDigits> hex) |
| { |
| return hex.toStream(stream); |
| } |
| |
| // Bitfield formatter. |
| |
| class BitDesc |
| { |
| public: |
| deUint64 bit; |
| const char* name; |
| |
| BitDesc (deUint64 bit_, const char* name_) : bit(bit_), name(name_) {} |
| }; |
| |
| #define TCU_BIT_DESC(BIT) tcu::Format::BitDesc(BIT, #BIT) |
| |
| template <size_t BitfieldSize> |
| class Bitfield |
| { |
| public: |
| Bitfield (deUint64 value, const BitDesc* begin, const BitDesc* end) |
| : m_value (value) |
| , m_begin (begin) |
| , m_end (end) |
| { |
| } |
| |
| std::ostream& toStream (std::ostream& stream) |
| { |
| deUint64 bitsLeft = m_value; |
| for (const BitDesc* curDesc = m_begin; curDesc != m_end; curDesc++) |
| { |
| if (curDesc->bit & bitsLeft) |
| { |
| if (bitsLeft != m_value) |
| stream << "|"; |
| stream << curDesc->name; |
| bitsLeft ^= curDesc->bit; |
| } |
| } |
| |
| if (bitsLeft != 0) |
| { |
| if (bitsLeft != m_value) |
| stream << "|"; |
| stream << Hex<BitfieldSize/4>(bitsLeft); |
| } |
| |
| return stream; |
| } |
| |
| private: |
| deUint64 m_value; |
| const BitDesc* m_begin; |
| const BitDesc* m_end; |
| }; |
| |
| template <size_t BitfieldSize> |
| inline std::ostream& operator<< (std::ostream& stream, Bitfield<BitfieldSize> decoder) |
| { |
| return decoder.toStream(stream); |
| } |
| |
| // Enum formatter. |
| // \todo [2012-10-30 pyry] Use template for GetName. |
| template <typename T, size_t NumBytes = sizeof(T)> |
| class Enum |
| { |
| public: |
| typedef const char* (*GetNameFunc) (T value); |
| |
| Enum (GetNameFunc getName, T value) |
| : m_getName (getName) |
| , m_value (value) |
| { |
| } |
| |
| std::ostream& toStream (std::ostream& stream) const |
| { |
| const char* name = m_getName(m_value); |
| if (name) |
| return stream << name; |
| else |
| return stream << Hex<NumBytes*2>((deUint64)m_value); |
| } |
| |
| std::string toString (void) const |
| { |
| const char* name = m_getName(m_value); |
| if (name) |
| return std::string(name); |
| else |
| return Hex<NumBytes*2>((deUint64)m_value).toString(); |
| } |
| |
| private: |
| const GetNameFunc m_getName; |
| const T m_value; |
| }; |
| |
| template <typename T, size_t NumBytes> |
| inline std::ostream& operator<< (std::ostream& stream, const Enum<T, NumBytes>& fmt) { return fmt.toStream(stream); } |
| |
| // Array formatters. |
| |
| template <typename Iterator> |
| class Array |
| { |
| public: |
| Iterator begin; |
| Iterator end; |
| |
| Array (const Iterator& begin_, const Iterator& end_) : begin(begin_), end(end_) {} |
| }; |
| |
| template <typename T> |
| class ArrayPointer |
| { |
| public: |
| const T* arr; |
| int size; |
| |
| ArrayPointer (const T* arr_, int size_) : arr(arr_), size(size_) {} |
| }; |
| |
| template <typename Iterator> |
| std::ostream& operator<< (std::ostream& str, const Array<Iterator>& fmt) |
| { |
| str << "{ "; |
| for (Iterator cur = fmt.begin; cur != fmt.end; ++cur) |
| { |
| if (cur != fmt.begin) |
| str << ", "; |
| str << *cur; |
| } |
| str << " }"; |
| return str; |
| } |
| |
| template <typename T> |
| std::ostream& operator<< (std::ostream& str, const ArrayPointer<T>& fmt) |
| { |
| if (fmt.arr != DE_NULL) |
| return str << Array<const T*>(fmt.arr, fmt.arr+fmt.size); |
| else |
| return str << "(null)"; |
| } |
| |
| // Hex format iterator (useful for combining with ArrayFormatter). |
| // \todo [2012-10-30 pyry] Implement more generic format iterator. |
| |
| template <typename T, typename Iterator = const T*> |
| class HexIterator |
| { |
| public: |
| HexIterator (Iterator iter) : m_iter(iter) {} |
| |
| HexIterator<T, Iterator>& operator++ (void) { ++m_iter; return *this; } |
| HexIterator<T, Iterator> operator++ (int) { return HexIterator(m_iter++); } |
| |
| bool operator== (const HexIterator<T, Iterator>& other) const { return m_iter == other.m_iter; } |
| bool operator!= (const HexIterator<T, Iterator>& other) const { return m_iter != other.m_iter; } |
| |
| #if !defined(__INTELLISENSE__) |
| // Intellisense in VS2013 crashes when parsing this. |
| Hex<sizeof(T)*2> operator* (void) const { return Hex<sizeof(T)*2>(*m_iter); } |
| #endif |
| |
| private: |
| Iterator m_iter; |
| }; |
| |
| } // Format |
| |
| template <int Bits> inline deUint64 makeMask64 (void) { return (1ull<<Bits)-1; } |
| template <> inline deUint64 makeMask64<64> (void) { return ~0ull; } |
| template <typename T> inline deUint64 toUint64 (T value) { return (deUint64)value & makeMask64<sizeof(T)*8>(); } |
| |
| /** Format value as hexadecimal number. */ |
| template <size_t NumDigits, typename T> |
| inline Format::Hex<NumDigits> toHex (T value) |
| { |
| return Format::Hex<NumDigits>(toUint64(value)); |
| } |
| |
| /** Format value as hexadecimal number. */ |
| template <typename T> |
| inline Format::Hex<sizeof(T)*2> toHex (T value) |
| { |
| return Format::Hex<sizeof(T)*2>(toUint64(value)); |
| } |
| |
| /** Decode and format bitfield. */ |
| template <typename T, size_t Size> |
| inline Format::Bitfield<sizeof(T)*8> formatBitfield (T value, const Format::BitDesc (&desc)[Size]) |
| { |
| return Format::Bitfield<sizeof(T)*8>((deUint64)value, &desc[0], &desc[Size]); |
| } |
| |
| /** Format array contents. */ |
| template <typename Iterator> |
| inline Format::Array<Iterator> formatArray (const Iterator& begin, const Iterator& end) |
| { |
| return Format::Array<Iterator>(begin, end); |
| } |
| |
| /** Format array contents. */ |
| template <typename T> |
| inline Format::ArrayPointer<T> formatArray (const T* arr, int size) |
| { |
| return Format::ArrayPointer<T>(arr, size); |
| } |
| |
| /** Format array contents. */ |
| template <typename T, int Size> |
| inline Format::ArrayPointer<T> formatArray (const T (&arr)[Size]) |
| { |
| return Format::ArrayPointer<T>(arr, Size); |
| } |
| |
| } // tcu |
| |
| #endif // _TCUFORMATUTIL_HPP |