#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 #include #include #include namespace tcu { namespace Format { // Hexadecimal value formatter. template class Hex { public: Hex(uint64_t 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: uint64_t value; }; template std::ostream &operator<<(std::ostream &stream, tcu::Format::Hex hex) { return hex.toStream(stream); } // Bitfield formatter. class BitDesc { public: uint64_t bit; const char *name; BitDesc(uint64_t bit_, const char *name_) : bit(bit_), name(name_) { } }; #define TCU_BIT_DESC(BIT) tcu::Format::BitDesc(BIT, #BIT) template class Bitfield { public: Bitfield(uint64_t value, const BitDesc *begin, const BitDesc *end) : m_value(value), m_begin(begin), m_end(end) { } std::ostream &toStream(std::ostream &stream) { uint64_t 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(bitsLeft); } return stream; } private: uint64_t m_value; const BitDesc *m_begin; const BitDesc *m_end; }; template inline std::ostream &operator<<(std::ostream &stream, Bitfield decoder) { return decoder.toStream(stream); } // Enum formatter. // \todo [2012-10-30 pyry] Use template for GetName. template 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((uint64_t)m_value); } std::string toString(void) const { const char *name = m_getName(m_value); if (name) return std::string(name); else return Hex((uint64_t)m_value).toString(); } private: const GetNameFunc m_getName; const T m_value; }; template inline std::ostream &operator<<(std::ostream &stream, const Enum &fmt) { return fmt.toStream(stream); } // Array formatters. template class Array { public: Iterator begin; Iterator end; Array(const Iterator &begin_, const Iterator &end_) : begin(begin_), end(end_) { } }; template class ArrayPointer { public: const T *arr; int size; ArrayPointer(const T *arr_, int size_) : arr(arr_), size(size_) { } }; template std::ostream &operator<<(std::ostream &str, const Array &fmt) { str << "{ "; for (Iterator cur = fmt.begin; cur != fmt.end; ++cur) { if (cur != fmt.begin) str << ", "; str << *cur; } str << " }"; return str; } template std::ostream &operator<<(std::ostream &str, const ArrayPointer &fmt) { if (fmt.arr != DE_NULL) return str << Array(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 class HexIterator { public: HexIterator(Iterator iter) : m_iter(iter) { } HexIterator &operator++(void) { ++m_iter; return *this; } HexIterator operator++(int) { return HexIterator(m_iter++); } bool operator==(const HexIterator &other) const { return m_iter == other.m_iter; } bool operator!=(const HexIterator &other) const { return m_iter != other.m_iter; } #if !defined(__INTELLISENSE__) // Intellisense in VS2013 crashes when parsing this. Hex operator*(void) const { return Hex(*m_iter); } #endif private: Iterator m_iter; }; } // namespace Format template inline uint64_t makeMask64(void) { return (1ull << Bits) - 1; } template <> inline uint64_t makeMask64<64>(void) { return ~0ull; } template inline uint64_t toUint64(T value) { return (uint64_t)value & makeMask64(); } /** Format value as hexadecimal number. */ template inline Format::Hex toHex(T value) { return Format::Hex(toUint64(value)); } /** Format value as hexadecimal number. */ template inline Format::Hex toHex(T value) { return Format::Hex(toUint64(value)); } /** Decode and format bitfield. */ template inline Format::Bitfield formatBitfield(T value, const Format::BitDesc (&desc)[Size]) { return Format::Bitfield((uint64_t)value, &desc[0], &desc[Size]); } /** Format array contents. */ template inline Format::Array formatArray(const Iterator &begin, const Iterator &end) { return Format::Array(begin, end); } /** Format array contents. */ template inline Format::ArrayPointer formatArray(const T *arr, int size) { return Format::ArrayPointer(arr, size); } /** Format array contents. */ template inline Format::ArrayPointer formatArray(const T (&arr)[Size]) { return Format::ArrayPointer(arr, Size); } } // namespace tcu #endif // _TCUFORMATUTIL_HPP