mfbt/IntegerTypeTraits.h
author Bryce Van Dyk <bvandyk@mozilla.com>
Mon, 27 Aug 2018 16:25:54 +0000
changeset 488616 259675bd67f96acf1ae0f2ed6115de4331a94d32
parent 247072 25507fee09eba0c2ecc38551ca1877d027b36fbe
child 505383 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1486502 - Add widevine CDM headers to third party paths, clang-format ignore. r=sylvestre We wish to keep the widevine headers in the same formatting as upstream to ease comparison and as we do not modify these files. This patch adds the existing headers, as well as another we anticipate pulling down for our next bump (content_decryption_module_proxy.h) to the ignored paths. These files are ignored individually rather than the whole directory they're in, as we also have Mozilla code in that dir. Differential Revision: https://phabricator.services.mozilla.com/D4347

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* Helpers to manipulate integer types that don't fit in TypeTraits.h */

#ifndef mozilla_IntegerTypeTraits_h
#define mozilla_IntegerTypeTraits_h

#include "mozilla/TypeTraits.h"
#include <stdint.h>

namespace mozilla {

namespace detail {

/**
 * StdintTypeForSizeAndSignedness returns the stdint integer type
 * of given size (can be 1, 2, 4 or 8) and given signedness
 * (false means unsigned, true means signed).
 */
template<size_t Size, bool Signedness>
struct StdintTypeForSizeAndSignedness;

template<>
struct StdintTypeForSizeAndSignedness<1, true>
{
  typedef int8_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<1, false>
{
  typedef uint8_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<2, true>
{
  typedef int16_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<2, false>
{
  typedef uint16_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<4, true>
{
  typedef int32_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<4, false>
{
  typedef uint32_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<8, true>
{
  typedef int64_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<8, false>
{
  typedef uint64_t Type;
};

} // namespace detail

template<size_t Size>
struct UnsignedStdintTypeForSize
  : detail::StdintTypeForSizeAndSignedness<Size, false>
{};

template<size_t Size>
struct SignedStdintTypeForSize
  : detail::StdintTypeForSizeAndSignedness<Size, true>
{};

template<typename IntegerType>
struct PositionOfSignBit
{
  static_assert(IsIntegral<IntegerType>::value,
                "PositionOfSignBit is only for integral types");
  // 8 here should be CHAR_BIT from limits.h, but the world has moved on.
  static const size_t value = 8 * sizeof(IntegerType) - 1;
};

/**
 * MinValue returns the minimum value of the given integer type as a
 * compile-time constant, which std::numeric_limits<IntegerType>::min()
 * cannot do in c++98.
 */
template<typename IntegerType>
struct MinValue
{
private:
  static_assert(IsIntegral<IntegerType>::value,
                "MinValue is only for integral types");

  typedef typename MakeUnsigned<IntegerType>::Type UnsignedIntegerType;
  static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;

public:
  // Bitwise ops may return a larger type, that's why we cast explicitly.
  // In C++, left bit shifts on signed values is undefined by the standard
  // unless the shifted value is representable.
  // Notice that signed-to-unsigned conversions are always well-defined in
  // the standard as the value congruent to 2**n, as expected. By contrast,
  // unsigned-to-signed is only well-defined if the value is representable.
  static const IntegerType value =
      IsSigned<IntegerType>::value
      ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
      : IntegerType(0);
};

/**
 * MaxValue returns the maximum value of the given integer type as a
 * compile-time constant, which std::numeric_limits<IntegerType>::max()
 * cannot do in c++98.
 */
template<typename IntegerType>
struct MaxValue
{
  static_assert(IsIntegral<IntegerType>::value,
                "MaxValue is only for integral types");

  // Tricksy, but covered by the CheckedInt unit test.
  // Relies on the type of MinValue<IntegerType>::value
  // being IntegerType.
  static const IntegerType value = ~MinValue<IntegerType>::value;
};

} // namespace mozilla

#endif // mozilla_IntegerTypeTraits_h