michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* Helpers to manipulate integer types that don't fit in TypeTraits.h */ michael@0: michael@0: #ifndef mozilla_IntegerTypeTraits_h michael@0: #define mozilla_IntegerTypeTraits_h michael@0: michael@0: #include "mozilla/TypeTraits.h" michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace detail { michael@0: michael@0: /** michael@0: * StdintTypeForSizeAndSignedness returns the stdint integer type michael@0: * of given size (can be 1, 2, 4 or 8) and given signedness michael@0: * (false means unsigned, true means signed). michael@0: */ michael@0: template michael@0: struct StdintTypeForSizeAndSignedness; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<1, true> michael@0: { typedef int8_t Type; }; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<1, false> michael@0: { typedef uint8_t Type; }; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<2, true> michael@0: { typedef int16_t Type; }; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<2, false> michael@0: { typedef uint16_t Type; }; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<4, true> michael@0: { typedef int32_t Type; }; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<4, false> michael@0: { typedef uint32_t Type; }; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<8, true> michael@0: { typedef int64_t Type; }; michael@0: michael@0: template<> michael@0: struct StdintTypeForSizeAndSignedness<8, false> michael@0: { typedef uint64_t Type; }; michael@0: michael@0: } // namespace detail michael@0: michael@0: template michael@0: struct UnsignedStdintTypeForSize michael@0: : detail::StdintTypeForSizeAndSignedness michael@0: {}; michael@0: michael@0: template michael@0: struct PositionOfSignBit michael@0: { michael@0: static_assert(IsIntegral::value, "PositionOfSignBit is only for integral types"); michael@0: // 8 here should be CHAR_BIT from limits.h, but the world has moved on. michael@0: static const size_t value = 8 * sizeof(IntegerType) - 1; michael@0: }; michael@0: michael@0: /** michael@0: * MinValue returns the minimum value of the given integer type as a michael@0: * compile-time constant, which std::numeric_limits::min() michael@0: * cannot do in c++98. michael@0: */ michael@0: template michael@0: struct MinValue michael@0: { michael@0: private: michael@0: static_assert(IsIntegral::value, "MinValue is only for integral types"); michael@0: michael@0: typedef typename MakeUnsigned::Type UnsignedIntegerType; michael@0: static const size_t PosOfSignBit = PositionOfSignBit::value; michael@0: michael@0: public: michael@0: // Bitwise ops may return a larger type, that's why we cast explicitly. michael@0: // In C++, left bit shifts on signed values is undefined by the standard michael@0: // unless the shifted value is representable. michael@0: // Notice that signed-to-unsigned conversions are always well-defined in michael@0: // the standard as the value congruent to 2**n, as expected. By contrast, michael@0: // unsigned-to-signed is only well-defined if the value is representable. michael@0: static const IntegerType value = michael@0: IsSigned::value michael@0: ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit) michael@0: : IntegerType(0); michael@0: }; michael@0: michael@0: /** michael@0: * MaxValue returns the maximum value of the given integer type as a michael@0: * compile-time constant, which std::numeric_limits::max() michael@0: * cannot do in c++98. michael@0: */ michael@0: template michael@0: struct MaxValue michael@0: { michael@0: static_assert(IsIntegral::value, "MaxValue is only for integral types"); michael@0: michael@0: // Tricksy, but covered by the CheckedInt unit test. michael@0: // Relies on the type of MinValue::value michael@0: // being IntegerType. michael@0: static const IntegerType value = ~MinValue::value; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_IntegerTypeTraits_h