LCOV - code coverage report
Current view: top level - mfbt - BinarySearch.h (source / functions) Hit Total Coverage
Test: output.info Lines: 27 27 100.0 %
Date: 2017-07-14 16:53:18 Functions: 27 113 23.9 %
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             : #ifndef mozilla_BinarySearch_h
       8             : #define mozilla_BinarySearch_h
       9             : 
      10             : #include "mozilla/Assertions.h"
      11             : 
      12             : #include <stddef.h>
      13             : 
      14             : namespace mozilla {
      15             : 
      16             : /*
      17             :  * The BinarySearch() algorithm searches the given container |aContainer| over
      18             :  * the sorted index range [aBegin, aEnd) for an index |i| where
      19             :  * |aContainer[i] == aTarget|.
      20             :  * If such an index |i| is found, BinarySearch returns |true| and the index is
      21             :  * returned via the outparam |aMatchOrInsertionPoint|. If no index is found,
      22             :  * BinarySearch returns |false| and the outparam returns the first index in
      23             :  * [aBegin, aEnd] where |aTarget| can be inserted to maintain sorted order.
      24             :  *
      25             :  * Example:
      26             :  *
      27             :  *   Vector<int> sortedInts = ...
      28             :  *
      29             :  *   size_t match;
      30             :  *   if (BinarySearch(sortedInts, 0, sortedInts.length(), 13, &match)) {
      31             :  *     printf("found 13 at %lu\n", match);
      32             :  *   }
      33             :  *
      34             :  * The BinarySearchIf() version behaves similarly, but takes |aComparator|, a
      35             :  * functor to compare the values with, instead of a value to find.
      36             :  * That functor should take one argument - the value to compare - and return an
      37             :  * |int| with the comparison result:
      38             :  *
      39             :  *   * 0, if the argument is equal to,
      40             :  *   * less than 0, if the argument is greater than,
      41             :  *   * greater than 0, if the argument is less than
      42             :  *
      43             :  * the value.
      44             :  *
      45             :  * Example:
      46             :  *
      47             :  *   struct Comparator {
      48             :  *     int operator()(int aVal) const {
      49             :  *       if (mTarget < aVal) { return -1; }
      50             :  *       if (mTarget > aVal) { return 1; }
      51             :  *       return 0;
      52             :  *     }
      53             :  *     explicit Comparator(int aTarget) : mTarget(aTarget) {}
      54             :  *     const int mTarget;
      55             :  *   };
      56             :  *
      57             :  *   Vector<int> sortedInts = ...
      58             :  *
      59             :  *   size_t match;
      60             :  *   if (BinarySearchIf(sortedInts, 0, sortedInts.length(), Comparator(13), &match)) {
      61             :  *     printf("found 13 at %lu\n", match);
      62             :  *   }
      63             :  *
      64             :  */
      65             : 
      66             : template<typename Container, typename Comparator>
      67             : bool
      68      163565 : BinarySearchIf(const Container& aContainer, size_t aBegin, size_t aEnd,
      69             :                const Comparator& aCompare, size_t* aMatchOrInsertionPoint)
      70             : {
      71      163565 :   MOZ_ASSERT(aBegin <= aEnd);
      72             : 
      73      163565 :   size_t low = aBegin;
      74      163565 :   size_t high = aEnd;
      75     1210421 :   while (high != low) {
      76      666498 :     size_t middle = low + (high - low) / 2;
      77             : 
      78             :     // Allow any intermediate type so long as it provides a suitable ordering
      79             :     // relation.
      80      666498 :     const int result = aCompare(aContainer[middle]);
      81             : 
      82      666498 :     if (result == 0) {
      83      143070 :       *aMatchOrInsertionPoint = middle;
      84      143070 :       return true;
      85             :     }
      86             : 
      87      523428 :     if (result < 0) {
      88      251268 :       high = middle;
      89             :     } else {
      90      272160 :       low = middle + 1;
      91             :     }
      92             :   }
      93             : 
      94       20495 :   *aMatchOrInsertionPoint = low;
      95       20495 :   return false;
      96             : }
      97             : 
      98             : namespace detail {
      99             : 
     100             : template<class T>
     101             : class BinarySearchDefaultComparator
     102             : {
     103             : public:
     104        5430 :   explicit BinarySearchDefaultComparator(const T& aTarget)
     105        5430 :     : mTarget(aTarget)
     106        5430 :   {}
     107             : 
     108             :   template <class U>
     109       19835 :   int operator()(const U& aVal) const {
     110       19835 :     if (mTarget == aVal) {
     111        5114 :       return 0;
     112             :     }
     113             : 
     114       14721 :     if (mTarget < aVal) {
     115        7861 :       return -1;
     116             :     }
     117             : 
     118        6860 :     return 1;
     119             :   }
     120             : 
     121             : private:
     122             :   const T& mTarget;
     123             : };
     124             : 
     125             : } // namespace detail
     126             : 
     127             : template <typename Container, typename T>
     128             : bool
     129        5415 : BinarySearch(const Container& aContainer, size_t aBegin, size_t aEnd,
     130             :              T aTarget, size_t* aMatchOrInsertionPoint)
     131             : {
     132       10830 :   return BinarySearchIf(aContainer, aBegin, aEnd,
     133             :                         detail::BinarySearchDefaultComparator<T>(aTarget),
     134       10830 :                         aMatchOrInsertionPoint);
     135             : }
     136             : 
     137             : } // namespace mozilla
     138             : 
     139             : #endif // mozilla_BinarySearch_h

Generated by: LCOV version 1.13