LCOV - code coverage report
Current view: top level - mfbt - ArrayUtils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 9 23 39.1 %
Date: 2017-07-14 16:53:18 Functions: 142 421 33.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * Implements various helper functions related to arrays.
       9             :  */
      10             : 
      11             : #ifndef mozilla_ArrayUtils_h
      12             : #define mozilla_ArrayUtils_h
      13             : 
      14             : #include "mozilla/Assertions.h"
      15             : #include "mozilla/Attributes.h"
      16             : 
      17             : #include <stddef.h>
      18             : 
      19             : #ifdef __cplusplus
      20             : 
      21             : #include "mozilla/Alignment.h"
      22             : #include "mozilla/Array.h"
      23             : #include "mozilla/EnumeratedArray.h"
      24             : #include "mozilla/TypeTraits.h"
      25             : 
      26             : namespace mozilla {
      27             : 
      28             : /*
      29             :  * Safely subtract two pointers when it is known that aEnd >= aBegin, yielding a
      30             :  * size_t result.
      31             :  *
      32             :  * Ordinary pointer subtraction yields a ptrdiff_t result, which, being signed,
      33             :  * has insufficient range to express the distance between pointers at opposite
      34             :  * ends of the address space. Furthermore, most compilers use ptrdiff_t to
      35             :  * represent the intermediate byte address distance, before dividing by
      36             :  * sizeof(T); if that intermediate result overflows, they'll produce results
      37             :  * with the wrong sign even when the correct scaled distance would fit in a
      38             :  * ptrdiff_t.
      39             :  */
      40             : template<class T>
      41             : MOZ_ALWAYS_INLINE size_t
      42     2568761 : PointerRangeSize(T* aBegin, T* aEnd)
      43             : {
      44     2568761 :   MOZ_ASSERT(aEnd >= aBegin);
      45     2568761 :   return (size_t(aEnd) - size_t(aBegin)) / sizeof(T);
      46             : }
      47             : 
      48             : /*
      49             :  * Compute the length of an array with constant length.  (Use of this method
      50             :  * with a non-array pointer will not compile.)
      51             :  *
      52             :  * Beware of the implicit trailing '\0' when using this with string constants.
      53             :  */
      54             : template<typename T, size_t N>
      55             : constexpr size_t
      56     3245915 : ArrayLength(T (&aArr)[N])
      57             : {
      58     3245915 :   return N;
      59             : }
      60             : 
      61             : template<typename T, size_t N>
      62             : constexpr size_t
      63         200 : ArrayLength(const Array<T, N>& aArr)
      64             : {
      65         200 :   return N;
      66             : }
      67             : 
      68             : template<typename E, E N, typename T>
      69             : constexpr size_t
      70           0 : ArrayLength(const EnumeratedArray<E, N, T>& aArr)
      71             : {
      72           0 :   return size_t(N);
      73             : }
      74             : 
      75             : /*
      76             :  * Compute the address one past the last element of a constant-length array.
      77             :  *
      78             :  * Beware of the implicit trailing '\0' when using this with string constants.
      79             :  */
      80             : template<typename T, size_t N>
      81             : constexpr T*
      82       13960 : ArrayEnd(T (&aArr)[N])
      83             : {
      84       13960 :   return aArr + ArrayLength(aArr);
      85             : }
      86             : 
      87             : template<typename T, size_t N>
      88             : constexpr T*
      89             : ArrayEnd(Array<T, N>& aArr)
      90             : {
      91             :   return &aArr[0] + ArrayLength(aArr);
      92             : }
      93             : 
      94             : template<typename T, size_t N>
      95             : constexpr const T*
      96             : ArrayEnd(const Array<T, N>& aArr)
      97             : {
      98             :   return &aArr[0] + ArrayLength(aArr);
      99             : }
     100             : 
     101             : namespace detail {
     102             : 
     103             : template<typename AlignType, typename Pointee,
     104             :          typename = EnableIf<!IsVoid<AlignType>::value>>
     105             : struct AlignedChecker
     106             : {
     107             :   static void
     108             :   test(const Pointee* aPtr)
     109             :   {
     110             :     MOZ_ASSERT((uintptr_t(aPtr) % MOZ_ALIGNOF(AlignType)) == 0,
     111             :                "performing a range-check with a misaligned pointer");
     112             :   }
     113             : };
     114             : 
     115             : template<typename AlignType, typename Pointee>
     116             : struct AlignedChecker<AlignType, Pointee>
     117             : {
     118             :   static void
     119           0 :   test(const Pointee* aPtr)
     120             :   {
     121           0 :   }
     122             : };
     123             : 
     124             : } // namespace detail
     125             : 
     126             : /**
     127             :  * Determines whether |aPtr| points at an object in the range [aBegin, aEnd).
     128             :  *
     129             :  * |aPtr| must have the same alignment as |aBegin| and |aEnd|.  This usually
     130             :  * should be achieved by ensuring |aPtr| points at a |U|, not just that it
     131             :  * points at a |T|.
     132             :  *
     133             :  * It is a usage error for any argument to be misaligned.
     134             :  *
     135             :  * It's okay for T* to be void*, and if so U* may also be void*.  In the latter
     136             :  * case no argument is required to be aligned (obviously, as void* implies no
     137             :  * particular alignment).
     138             :  */
     139             : template<typename T, typename U>
     140             : inline typename EnableIf<IsSame<T, U>::value ||
     141             :                          IsBaseOf<T, U>::value ||
     142             :                          IsVoid<T>::value,
     143             :                          bool>::Type
     144           0 : IsInRange(const T* aPtr, const U* aBegin, const U* aEnd)
     145             : {
     146           0 :   MOZ_ASSERT(aBegin <= aEnd);
     147           0 :   detail::AlignedChecker<U, T>::test(aPtr);
     148           0 :   detail::AlignedChecker<U, U>::test(aBegin);
     149           0 :   detail::AlignedChecker<U, U>::test(aEnd);
     150           0 :   return aBegin <= reinterpret_cast<const U*>(aPtr) &&
     151           0 :          reinterpret_cast<const U*>(aPtr) < aEnd;
     152             : }
     153             : 
     154             : /**
     155             :  * Convenience version of the above method when the valid range is specified as
     156             :  * uintptr_t values.  As above, |aPtr| must be aligned, and |aBegin| and |aEnd|
     157             :  * must be aligned with respect to |T|.
     158             :  */
     159             : template<typename T>
     160             : inline bool
     161           0 : IsInRange(const T* aPtr, uintptr_t aBegin, uintptr_t aEnd)
     162             : {
     163           0 :   return IsInRange(aPtr,
     164             :                    reinterpret_cast<const T*>(aBegin),
     165           0 :                    reinterpret_cast<const T*>(aEnd));
     166             : }
     167             : 
     168             : namespace detail {
     169             : 
     170             : /*
     171             :  * Helper for the MOZ_ARRAY_LENGTH() macro to make the length a typesafe
     172             :  * compile-time constant even on compilers lacking constexpr support.
     173             :  */
     174             : template <typename T, size_t N>
     175             : char (&ArrayLengthHelper(T (&array)[N]))[N];
     176             : 
     177             : } /* namespace detail */
     178             : 
     179             : } /* namespace mozilla */
     180             : 
     181             : #endif /* __cplusplus */
     182             : 
     183             : /*
     184             :  * MOZ_ARRAY_LENGTH() is an alternative to mozilla::ArrayLength() for C files
     185             :  * that can't use C++ template functions and for static_assert() calls that
     186             :  * can't call ArrayLength() when it is not a C++11 constexpr function.
     187             :  */
     188             : #ifdef __cplusplus
     189             : #  define MOZ_ARRAY_LENGTH(array)   sizeof(mozilla::detail::ArrayLengthHelper(array))
     190             : #else
     191             : #  define MOZ_ARRAY_LENGTH(array)   (sizeof(array)/sizeof((array)[0]))
     192             : #endif
     193             : 
     194             : #endif /* mozilla_ArrayUtils_h */

Generated by: LCOV version 1.13