pw_minimal_cpp_stdlib: More iterator support

Update pw_minimal_cpp_stdlib to include the following:
 - climits header
 - std::begin() and std::end()
 - std::find()
 - std::copy()

Change-Id: Iac5818e897daf79ff0a4c882a5a730da8e84a3f8
diff --git a/pw_minimal_cpp_stdlib/BUILD b/pw_minimal_cpp_stdlib/BUILD
index 592cab7..96aca6d 100644
--- a/pw_minimal_cpp_stdlib/BUILD
+++ b/pw_minimal_cpp_stdlib/BUILD
@@ -28,6 +28,7 @@
         "public/internal/algorithm.h",
         "public/internal/array.h",
         "public/internal/cinttypes.h",
+        "public/internal/climits.h",
         "public/internal/cmath.h",
         "public/internal/cstdarg.h",
         "public/internal/cstddef.h",
@@ -46,6 +47,7 @@
         "public/algorithm",
         "public/array",
         "public/cinttypes",
+        "public/climits",
         "public/cmath",
         "public/cstdarg",
         "public/cstddef",
diff --git a/pw_minimal_cpp_stdlib/BUILD.gn b/pw_minimal_cpp_stdlib/BUILD.gn
index 97060a5..3cbe163 100644
--- a/pw_minimal_cpp_stdlib/BUILD.gn
+++ b/pw_minimal_cpp_stdlib/BUILD.gn
@@ -30,6 +30,7 @@
     "public/algorithm",
     "public/array",
     "public/cinttypes",
+    "public/climits",
     "public/cmath",
     "public/cstdarg",
     "public/cstddef",
@@ -48,6 +49,7 @@
     "public/internal/algorithm.h",
     "public/internal/array.h",
     "public/internal/cinttypes.h",
+    "public/internal/climits.h",
     "public/internal/cmath.h",
     "public/internal/cstdarg.h",
     "public/internal/cstddef.h",
diff --git a/pw_minimal_cpp_stdlib/public/climits b/pw_minimal_cpp_stdlib/public/climits
new file mode 120000
index 0000000..e098495
--- /dev/null
+++ b/pw_minimal_cpp_stdlib/public/climits
@@ -0,0 +1 @@
+internal/climits.h
\ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/internal/algorithm.h b/pw_minimal_cpp_stdlib/public/internal/algorithm.h
index f905e11..6ad7179 100644
--- a/pw_minimal_cpp_stdlib/public/internal/algorithm.h
+++ b/pw_minimal_cpp_stdlib/public/internal/algorithm.h
@@ -17,6 +17,16 @@
 
 namespace std {
 
+template <class InputIterator, class OutputIterator>
+constexpr OutputIterator copy(InputIterator first,
+                              InputIterator last,
+                              OutputIterator dest) {
+  while (first != last) {
+    *dest++ = *first++;
+  }
+  return dest;
+}
+
 template <typename T>
 constexpr const T& min(const T& lhs, const T& rhs) {
   return (rhs < lhs) ? rhs : lhs;
@@ -27,6 +37,18 @@
   return (lhs < rhs) ? rhs : lhs;
 }
 
+template <class InputIterator, typename T>
+constexpr InputIterator find(InputIterator first,
+                             InputIterator last,
+                             const T& value) {
+  for (; first != last; ++first) {
+    if (*first == value) {
+      return first;
+    }
+  }
+  return last;
+}
+
 template <typename T>
 constexpr T&& forward(remove_reference_t<T>& value) {
   return static_cast<T&&>(value);
diff --git a/pw_minimal_cpp_stdlib/public/internal/climits.h b/pw_minimal_cpp_stdlib/public/internal/climits.h
new file mode 100644
index 0000000..6acdaea
--- /dev/null
+++ b/pw_minimal_cpp_stdlib/public/internal/climits.h
@@ -0,0 +1,16 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include <limits.h>
diff --git a/pw_minimal_cpp_stdlib/public/internal/iterator.h b/pw_minimal_cpp_stdlib/public/internal/iterator.h
index 4470731..e3010be 100644
--- a/pw_minimal_cpp_stdlib/public/internal/iterator.h
+++ b/pw_minimal_cpp_stdlib/public/internal/iterator.h
@@ -20,6 +20,16 @@
 #define __cpp_lib_nonmember_container_access 201411L
 
 template <typename C>
+auto begin(C& container) -> decltype(container.begin()) {
+  return container.begin();
+}
+
+template <typename C>
+auto begin(const C& container) -> decltype(container.begin()) {
+  return container.begin();
+}
+
+template <typename C>
 constexpr auto data(C& container) -> decltype(container.data()) {
   return container.data();
 }
@@ -35,6 +45,16 @@
 }
 
 template <typename C>
+auto end(C& container) -> decltype(container.end()) {
+  return container.end();
+}
+
+template <typename C>
+auto end(const C& container) -> decltype(container.end()) {
+  return container.end();
+}
+
+template <typename C>
 constexpr auto size(const C& container) -> decltype(container.size()) {
   return container.size();
 }
diff --git a/pw_minimal_cpp_stdlib/test.cc b/pw_minimal_cpp_stdlib/test.cc
index a29f649..63129e3 100644
--- a/pw_minimal_cpp_stdlib/test.cc
+++ b/pw_minimal_cpp_stdlib/test.cc
@@ -41,6 +41,64 @@
   EXPECT_EQ(std::forward<int>(2), 2);
 }
 
+TEST(Algorithm, Copy) {
+  constexpr size_t kCopyOffset = 1;
+  std::array<int, 3> foo{3, 2, 1};
+  std::array<int, 5> bar{0};
+
+  // Ensure zero-element iterator doesn't modify the destination object when
+  // copied.
+  int temp = foo[0];
+  std::copy(foo.end(), foo.end(), bar.begin());
+  EXPECT_EQ(foo[0], temp);
+
+  // Copy a single element.
+  std::array<int, 1> one{-101};
+  std::copy(one.begin(), one.end(), foo.begin());
+  EXPECT_EQ(foo[0], -101);
+
+  auto copy_end = std::copy(foo.begin(), foo.end(), bar.begin() + kCopyOffset);
+  // Verify the iterator points to the end of the copied region.
+  EXPECT_EQ(copy_end, bar.begin() + foo.size() + kCopyOffset);
+
+  // Verify all the values were properly copied from foo to bar.
+  {
+    size_t i = 0;
+    for (auto it = bar.begin() + kCopyOffset; it != copy_end; ++it) {
+      EXPECT_EQ(*it, foo[i++]);
+    }
+  }
+}
+
+TEST(Algorithm, Find) {
+  std::array<int, 5> foo{3, 2, 1, 42, 17};
+  // Ensure a value in the middle of the array is properly found.
+  EXPECT_EQ(*std::find(std::begin(foo), std::end(foo), 42), 42);
+
+  // Ensure the iterator returned by find() matches the expected location of the
+  // element.
+  EXPECT_EQ(std::find(std::begin(foo), std::end(foo), 42), std::begin(foo) + 3);
+
+  // Ensure an element at the beginning of an array is found.
+  EXPECT_EQ(*std::find(std::begin(foo), std::end(foo), 3), foo[0]);
+
+  // Ensure an element at the end of an array is found.
+  EXPECT_EQ(*std::find(std::begin(foo), std::end(foo), 17),
+            foo[foo.size() - 1]);
+}
+
+TEST(Algorithm, NotFound) {
+  std::array<int, 3> foo{3, 2, 1};
+
+  // Ensure that if an element is not found, an iterator matching foo.end() is
+  // returned.
+  EXPECT_EQ(std::find(std::begin(foo), std::end(foo), -99), std::end(foo));
+
+  // Ensure that a zero-element iterator range returns the end iterator passed
+  // to std::find().
+  EXPECT_EQ(std::find(std::end(foo), std::end(foo), 3), std::end(foo));
+}
+
 TEST(Array, Basic) {
   constexpr std::array<int, 4> array{0, 1, 2, 3};
 
@@ -77,6 +135,9 @@
   EXPECT_EQ(std::data(foo), foo.data());
   EXPECT_EQ(std::size(foo), foo.size());
 
+  EXPECT_EQ(*std::begin(foo), foo[0]);
+  EXPECT_EQ(std::end(foo), std::begin(foo) + foo.size());
+
   foo.fill(99);
   EXPECT_EQ(foo[0], 99);
   EXPECT_EQ(foo[1], 99);