summaryrefslogtreecommitdiffstats
path: root/xpcom/ds/ArrayAlgorithm.h
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/ds/ArrayAlgorithm.h')
-rw-r--r--xpcom/ds/ArrayAlgorithm.h109
1 files changed, 109 insertions, 0 deletions
diff --git a/xpcom/ds/ArrayAlgorithm.h b/xpcom/ds/ArrayAlgorithm.h
new file mode 100644
index 0000000000..2556eef465
--- /dev/null
+++ b/xpcom/ds/ArrayAlgorithm.h
@@ -0,0 +1,109 @@
+/* -*- 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/. */
+
+#ifndef ArrayAlgorithm_h___
+#define ArrayAlgorithm_h___
+
+#include "nsTArray.h"
+
+#include "mozilla/Algorithm.h"
+#include "mozilla/ResultExtensions.h"
+
+namespace mozilla {
+
+// An algorithm similar to TransformAbortOnErr, which creates a new nsTArray
+// rather than inserting into an output iterator. The capacity of the result
+// array is set to the number of elements that will be inserted if all
+// transformations are successful. This variant is fallible, i.e. if setting the
+// capacity fails, NS_ERROR_OUT_OF_MEMORY is returned as an error value. This
+// variant only works with nsresult errors.
+template <
+ typename SrcIter, typename Transform,
+ typename = std::enable_if_t<std::is_same_v<
+ typename detail::TransformTraits<Transform, SrcIter>::result_err_type,
+ nsresult>>>
+Result<nsTArray<typename detail::TransformTraits<Transform,
+ SrcIter>::result_ok_type>,
+ nsresult>
+TransformIntoNewArrayAbortOnErr(SrcIter aIter, SrcIter aEnd,
+ Transform aTransform, fallible_t) {
+ nsTArray<typename detail::TransformTraits<Transform, SrcIter>::result_ok_type>
+ res;
+ if (!res.SetCapacity(std::distance(aIter, aEnd), fallible)) {
+ return Err(NS_ERROR_OUT_OF_MEMORY);
+ }
+
+ auto transformRes = TransformAbortOnErr(aIter, aEnd, MakeBackInserter(res),
+ std::move(aTransform));
+ if (NS_WARN_IF(transformRes.isErr())) {
+ return Err(transformRes.unwrapErr());
+ }
+
+ return res;
+}
+
+template <typename SrcRange, typename Transform>
+auto TransformIntoNewArrayAbortOnErr(SrcRange& aRange, Transform aTransform,
+ fallible_t) {
+ using std::begin;
+ using std::end;
+ return TransformIntoNewArrayAbortOnErr(begin(aRange), end(aRange), aTransform,
+ fallible);
+}
+
+// An algorithm similar to std::transform, which creates a new nsTArray
+// rather than inserting into an output iterator. The capacity of the result
+// array is set to the number of elements that will be inserted. This variant is
+// fallible, i.e. if setting the capacity fails, NS_ERROR_OUT_OF_MEMORY is
+// returned as an error value. This variant only works with nsresult errors.
+template <typename SrcIter, typename Transform>
+Result<nsTArray<detail::ArrayElementTransformType<Transform, SrcIter>>,
+ nsresult>
+TransformIntoNewArray(SrcIter aIter, SrcIter aEnd, Transform aTransform,
+ fallible_t) {
+ nsTArray<detail::ArrayElementTransformType<Transform, SrcIter>> res;
+ if (!res.SetCapacity(std::distance(aIter, aEnd), fallible)) {
+ return Err(NS_ERROR_OUT_OF_MEMORY);
+ }
+
+ std::transform(aIter, aEnd, MakeBackInserter(res), std::move(aTransform));
+
+ return res;
+}
+
+template <typename SrcRange, typename Transform>
+auto TransformIntoNewArray(SrcRange& aRange, Transform aTransform, fallible_t) {
+ using std::begin;
+ using std::end;
+ return TransformIntoNewArray(begin(aRange), end(aRange), aTransform,
+ fallible);
+}
+
+// An algorithm similar to std::transform, which creates a new nsTArray
+// rather than inserting into an output iterator. The capacity of the result
+// array is set to the number of elements that will be inserted. This variant is
+// infallible, i.e. if setting the capacity fails, the process is aborted.
+template <typename SrcIter, typename Transform>
+nsTArray<detail::ArrayElementTransformType<Transform, SrcIter>>
+TransformIntoNewArray(SrcIter aIter, SrcIter aEnd, Transform aTransform) {
+ nsTArray<detail::ArrayElementTransformType<Transform, SrcIter>> res;
+ res.SetCapacity(std::distance(aIter, aEnd));
+
+ std::transform(aIter, aEnd, MakeBackInserter(res), std::move(aTransform));
+
+ return res;
+}
+
+template <typename SrcRange, typename Transform>
+auto TransformIntoNewArray(SrcRange& aRange, Transform aTransform) {
+ using std::begin;
+ using std::end;
+ return TransformIntoNewArray(begin(aRange), end(aRange), aTransform);
+}
+
+} // namespace mozilla
+
+#endif // !defined(ArrayAlgorithm_h___)