tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Algorithm.h (4319B)


      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 /* A polyfill for `<algorithm>`. */
      8 
      9 #ifndef mozilla_Algorithm_h
     10 #define mozilla_Algorithm_h
     11 
     12 #include "mozilla/Result.h"
     13 
     14 #include <iterator>
     15 #include <type_traits>
     16 
     17 namespace mozilla {
     18 
     19 // Returns true if all elements in the range [aFirst, aLast)
     20 // satisfy the predicate aPred.
     21 template <class Iter, class Pred>
     22 constexpr bool AllOf(Iter aFirst, Iter aLast, Pred aPred) {
     23  for (; aFirst != aLast; ++aFirst) {
     24    if (!aPred(*aFirst)) {
     25      return false;
     26    }
     27  }
     28  return true;
     29 }
     30 
     31 // Like C++20's `std::any_of`.
     32 template <typename Iter, typename Pred>
     33 constexpr bool AnyOf(Iter aFirst, Iter aLast, Pred aPred) {
     34  for (; aFirst != aLast; ++aFirst) {
     35    if (aPred(*aFirst)) {
     36      return true;
     37    }
     38  }
     39 
     40  return false;
     41 }
     42 
     43 namespace detail {
     44 template <typename Transform, typename SrcIter>
     45 using ArrayElementTransformType = typename std::invoke_result_t<
     46    Transform, typename std::iterator_traits<SrcIter>::reference>;
     47 
     48 template <typename Transform, typename SrcIter>
     49 struct TransformTraits {
     50  using result_type = ArrayElementTransformType<Transform, SrcIter>;
     51 
     52  using result_ok_type = typename result_type::ok_type;
     53  using result_err_type = typename result_type::err_type;
     54 };
     55 }  // namespace detail
     56 
     57 // An algorithm similar to TransformAbortOnErr combined with a condition that
     58 // allows to skip elements. At most std::distance(aIter, aEnd) elements will be
     59 // inserted into aDst.
     60 //
     61 // Type requirements, in addition to those specified in TransformAbortOnErr:
     62 // - Cond must be compatible with signature
     63 //   bool (const SrcIter::value_type&)
     64 template <typename SrcIter, typename DstIter, typename Cond, typename Transform>
     65 Result<Ok,
     66       typename detail::TransformTraits<Transform, SrcIter>::result_err_type>
     67 TransformIfAbortOnErr(SrcIter aIter, SrcIter aEnd, DstIter aDst, Cond aCond,
     68                      Transform aTransform) {
     69  for (; aIter != aEnd; ++aIter) {
     70    if (!aCond(static_cast<std::add_const_t<
     71                   typename std::iterator_traits<SrcIter>::value_type>&>(
     72            *aIter))) {
     73      continue;
     74    }
     75 
     76    auto res = aTransform(*aIter);
     77    if (res.isErr()) {
     78      return Err(res.unwrapErr());
     79    }
     80 
     81    *aDst++ = res.unwrap();
     82  }
     83  return Ok{};
     84 }
     85 
     86 template <typename SrcRange, typename DstIter, typename Cond,
     87          typename Transform>
     88 auto TransformIfAbortOnErr(SrcRange& aRange, DstIter aDst, Cond aCond,
     89                           Transform aTransform) {
     90  using std::begin;
     91  using std::end;
     92  return TransformIfAbortOnErr(begin(aRange), end(aRange), aDst, aCond,
     93                               aTransform);
     94 }
     95 
     96 // An algorithm similar to std::transform, adapted to error handling based on
     97 // mozilla::Result<V, E>. It iterates through the input range [aIter, aEnd) and
     98 // inserts the result of applying aTransform to each element into aDst, if
     99 // aTransform returns a success result. On the first error result, iterating is
    100 // aborted, and the error result is returned as an overall result. If all
    101 // transformations return a success result, Ok is returned as an overall result.
    102 //
    103 // Type requirements:
    104 // - SrcIter must be an InputIterator.
    105 // - DstIter must be an OutputIterator.
    106 // - Transform must be compatible with signature
    107 //   Result<DstIter::value_type, E> (SrcIter::reference)
    108 template <typename SrcIter, typename DstIter, typename Transform>
    109 Result<Ok,
    110       typename detail::TransformTraits<Transform, SrcIter>::result_err_type>
    111 TransformAbortOnErr(SrcIter aIter, SrcIter aEnd, DstIter aDst,
    112                    Transform aTransform) {
    113  return TransformIfAbortOnErr(
    114      aIter, aEnd, aDst, [](const auto&) { return true; }, aTransform);
    115 }
    116 
    117 template <typename SrcRange, typename DstIter, typename Transform>
    118 auto TransformAbortOnErr(SrcRange& aRange, DstIter aDst, Transform aTransform) {
    119  using std::begin;
    120  using std::end;
    121  return TransformIfAbortOnErr(
    122      begin(aRange), end(aRange), aDst, [](const auto&) { return true; },
    123      aTransform);
    124 }
    125 
    126 }  // namespace mozilla
    127 
    128 #endif  // mozilla_Algorithm_h