pw_minimal_cpp_stdlib: Extremely limited C++ lib pw_minimal_cpp_stdlib is an extremely limited, non-standard implementation of the C++ Standard Library. It requires C++17 and a C standard library. Change-Id: I2d0b8d6cf49730e2c746eddf2c4a23308af1eb6a
diff --git a/BUILD.gn b/BUILD.gn index 6379134..355b961 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1,4 +1,4 @@ -# Copyright 2019 The Pigweed Authors +# 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 @@ -54,6 +54,7 @@ "$dir_pw_base64", "$dir_pw_checksum", "$dir_pw_kvs", + "$dir_pw_minimal_cpp_stdlib", "$dir_pw_polyfill", "$dir_pw_preprocessor", "$dir_pw_protobuf", @@ -73,6 +74,7 @@ "$dir_pw_checksum:tests", "$dir_pw_kvs:tests", "$dir_pw_log:tests", + "$dir_pw_minimal_cpp_stdlib:tests", "$dir_pw_polyfill:tests", "$dir_pw_preprocessor:tests", "$dir_pw_protobuf:tests",
diff --git a/CMakeLists.txt b/CMakeLists.txt index d8ed777..3e6b40d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -27,6 +27,7 @@ add_subdirectory(pw_kvs) add_subdirectory(pw_log) add_subdirectory(pw_log_basic) +add_subdirectory(pw_minimal_cpp_stdlib) add_subdirectory(pw_polyfill) add_subdirectory(pw_preprocessor) add_subdirectory(pw_span)
diff --git a/docs/BUILD.gn b/docs/BUILD.gn index 031834e..076900d 100644 --- a/docs/BUILD.gn +++ b/docs/BUILD.gn
@@ -51,6 +51,7 @@ "$dir_pw_dumb_io_baremetal_stm32f429:docs", "$dir_pw_dumb_io_stdio:docs", "$dir_pw_log:docs", + "$dir_pw_minimal_cpp_stdlib:docs", "$dir_pw_module:docs", "$dir_pw_polyfill:docs", "$dir_pw_preprocessor:docs",
diff --git a/modules.gni b/modules.gni index 41fe5cf..d543d55 100644 --- a/modules.gni +++ b/modules.gni
@@ -32,6 +32,7 @@ dir_pw_kvs = "$dir_pigweed/pw_kvs" dir_pw_log = "$dir_pigweed/pw_log" dir_pw_log_basic = "$dir_pigweed/pw_log_basic" +dir_pw_minimal_cpp_stdlib = "$dir_pigweed/pw_minimal_cpp_stdlib" dir_pw_module = "$dir_pigweed/pw_module" dir_pw_polyfill = "$dir_pigweed/pw_polyfill" dir_pw_preprocessor = "$dir_pigweed/pw_preprocessor"
diff --git a/pw_minimal_cpp_stdlib/BUILD b/pw_minimal_cpp_stdlib/BUILD new file mode 100644 index 0000000..3e39d7b --- /dev/null +++ b/pw_minimal_cpp_stdlib/BUILD
@@ -0,0 +1,70 @@ +# 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. + +load( + "//pw_build:pigweed.bzl", + "pw_cc_library", + "pw_cc_test", +) + +pw_cc_library( + name = "pw_minimal_cpp_stdlib", + srcs = [ + "public/internal/algorithm.h", + "public/internal/array.h", + "public/internal/cinttypes.h", + "public/internal/cmath.h", + "public/internal/cstdarg.h", + "public/internal/cstddef.h", + "public/internal/cstdint.h", + "public/internal/cstdio.h", + "public/internal/cstring.h", + "public/internal/iterator.h", + "public/internal/limits.h", + "public/internal/new.h", + "public/internal/string_view.h", + "public/internal/type_traits.h", + "public/internal/utility.h", + ], + hdrs = [ + "public/algorithm", + "public/array", + "public/cinttypes", + "public/cmath", + "public/cstdarg", + "public/cstddef", + "public/cstdint", + "public/cstdio", + "public/cstring", + "public/iterator", + "public/limits", + "public/new", + "public/string_view", + "public/type_traits", + "public/utility", + ], + copts = ["-nostdinc++"], + includes = ["public"], +) + +pw_cc_test( + name = "test", + srcs = [ + "test.cc", + ], + copts = ["-nostdinc++"], + deps = [ + ":pw_minimal_cpp_stdlib", + ], +)
diff --git a/pw_minimal_cpp_stdlib/BUILD.gn b/pw_minimal_cpp_stdlib/BUILD.gn new file mode 100644 index 0000000..d9ac40f --- /dev/null +++ b/pw_minimal_cpp_stdlib/BUILD.gn
@@ -0,0 +1,92 @@ +# 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. + +import("$dir_pw_docgen/docs.gni") +import("$dir_pw_unit_test/test.gni") + +config("include_dirs") { + include_dirs = [ "public" ] +} + +config("no_cpp_includes") { + cflags = [ "-nostdinc++" ] +} + +source_set("pw_minimal_cpp_stdlib") { + public_configs = [ ":include_dirs" ] + configs = [ ":no_cpp_includes" ] + public = [ + "public/algorithm", + "public/array", + "public/cinttypes", + "public/cmath", + "public/cstdarg", + "public/cstddef", + "public/cstdint", + "public/cstdio", + "public/cstring", + "public/iterator", + "public/limits", + "public/new", + "public/string_view", + "public/type_traits", + "public/utility", + ] + sources = [ + "public/internal/algorithm.h", + "public/internal/array.h", + "public/internal/cinttypes.h", + "public/internal/cmath.h", + "public/internal/cstdarg.h", + "public/internal/cstddef.h", + "public/internal/cstdint.h", + "public/internal/cstdio.h", + "public/internal/cstring.h", + "public/internal/iterator.h", + "public/internal/limits.h", + "public/internal/new.h", + "public/internal/string_view.h", + "public/internal/type_traits.h", + "public/internal/utility.h", + ] +} + +pw_test_group("tests") { + tests = [ + ":minimal_cpp_stdlib_test", + ":standard_library_test", + ] +} + +pw_test("minimal_cpp_stdlib_test") { + configs = [ ":no_cpp_includes" ] + deps = [ + ":pw_minimal_cpp_stdlib", + ] + sources = [ + "test.cc", + ] +} + +pw_test("standard_library_test") { + sources = [ + "test.cc", + ] +} + +pw_doc_group("docs") { + sources = [ + "docs.rst", + ] +}
diff --git a/pw_minimal_cpp_stdlib/CMakeLists.txt b/pw_minimal_cpp_stdlib/CMakeLists.txt new file mode 100644 index 0000000..90f96cd --- /dev/null +++ b/pw_minimal_cpp_stdlib/CMakeLists.txt
@@ -0,0 +1,15 @@ +# 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. + +pw_auto_add_simple_module(pw_minimal_cpp_stdlib)
diff --git a/pw_minimal_cpp_stdlib/docs.rst b/pw_minimal_cpp_stdlib/docs.rst new file mode 100644 index 0000000..904f369 --- /dev/null +++ b/pw_minimal_cpp_stdlib/docs.rst
@@ -0,0 +1,31 @@ +.. _chapter-pw-minimal-cpp-stdlib: + +.. default-domain:: cpp + +--------------------- +pw_minimal_cpp_stdlib +--------------------- +The pw_minimal_cpp_stdlib module provides an extremely limited implementation of +the C++ Standard Library. This module falls far, far short of providing a +complete C++ Standard Library and should only be used in dire situations where +you happen to be compiling with C++17 but don't have a C++ Standard Library +available to you. + +The C++ Standard Library headers (e.g. ``<cstdint>`` and ``<type_traits>``) are +defined in ``public/``. These files are symlinks to their implementations in +``public/internal/``. + +.. tip:: + + You can automatically recreate the symlinks in ``public/`` by executing the + following Bash code from ``pw_minimal_cpp_stdlib/public/``. + + .. code-block:: bash + + for f in $(ls internal/); do ln -s internal/$f ${f%.h}; done + +Requirments +=========== +- C++17 +- gcc or clang +- The C Standard Library
diff --git a/pw_minimal_cpp_stdlib/public/algorithm b/pw_minimal_cpp_stdlib/public/algorithm new file mode 120000 index 0000000..81f8692 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/algorithm
@@ -0,0 +1 @@ +internal/algorithm.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/array b/pw_minimal_cpp_stdlib/public/array new file mode 120000 index 0000000..e9f7bca --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/array
@@ -0,0 +1 @@ +internal/array.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/cinttypes b/pw_minimal_cpp_stdlib/public/cinttypes new file mode 120000 index 0000000..8b251e5 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/cinttypes
@@ -0,0 +1 @@ +internal/cinttypes.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/cmath b/pw_minimal_cpp_stdlib/public/cmath new file mode 120000 index 0000000..caf5054 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/cmath
@@ -0,0 +1 @@ +internal/cmath.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/cstdarg b/pw_minimal_cpp_stdlib/public/cstdarg new file mode 120000 index 0000000..5d649b5 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/cstdarg
@@ -0,0 +1 @@ +internal/cstdarg.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/cstddef b/pw_minimal_cpp_stdlib/public/cstddef new file mode 120000 index 0000000..c351114 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/cstddef
@@ -0,0 +1 @@ +internal/cstddef.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/cstdint b/pw_minimal_cpp_stdlib/public/cstdint new file mode 120000 index 0000000..749150f --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/cstdint
@@ -0,0 +1 @@ +internal/cstdint.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/cstdio b/pw_minimal_cpp_stdlib/public/cstdio new file mode 120000 index 0000000..12ae705 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/cstdio
@@ -0,0 +1 @@ +internal/cstdio.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/cstring b/pw_minimal_cpp_stdlib/public/cstring new file mode 120000 index 0000000..429e026 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/cstring
@@ -0,0 +1 @@ +internal/cstring.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 new file mode 100644 index 0000000..2556702 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/algorithm.h
@@ -0,0 +1,40 @@ +// 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 <type_traits> + +namespace std { + +template <typename T> +constexpr const T& min(const T& lhs, const T& rhs) { + return (rhs < lhs) ? rhs : lhs; +} + +template <typename T> +constexpr const T& max(const T& lhs, const T& rhs) { + return (lhs < rhs) ? rhs : lhs; +} + +template <typename T> +constexpr T&& forward(remove_reference_t<T>& value) { + return static_cast<T&&>(value); +} + +template <typename T> +constexpr T&& forward(remove_reference_t<T>&& value) { + return static_cast<T&&>(value); +} + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/array.h b/pw_minimal_cpp_stdlib/public/internal/array.h new file mode 100644 index 0000000..80aeeca --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/array.h
@@ -0,0 +1,103 @@ +// 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 <iterator> + +namespace std { + +template <typename T, decltype(sizeof(0)) kSize> +struct array { + using value_type = T; + using size_type = decltype(kSize); + using difference_type = + decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr)); + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + using iterator = T*; + using const_iterator = const T*; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + // NOT IMPLEMENTED: at() does not bounds checking. + constexpr reference at(size_type index) { return data()[index]; } + constexpr const_reference at(size_type index) const { return data()[index]; } + + constexpr reference operator[](size_type index) { return data()[index]; } + constexpr const_reference operator[](size_type index) const { + return data()[index]; + } + + constexpr reference front() { return data()[0]; } + constexpr const_reference front() const { return data()[0]; } + + constexpr reference back() { + static_assert(kSize > 0); + return data()[size() - 1]; + } + constexpr const_reference back() const { + static_assert(kSize > 0); + return data()[size() - 1]; + } + + constexpr pointer data() noexcept { + static_assert(kSize > 0); + return __data; + } + constexpr const_pointer data() const noexcept { + static_assert(kSize > 0); + return __data; + } + + constexpr iterator begin() noexcept { return data(); } + constexpr const_iterator begin() const noexcept { return data(); } + constexpr const_iterator cbegin() const noexcept { return begin(); } + + constexpr iterator end() noexcept { return data() + kSize; } + constexpr const_iterator end() const noexcept { return data() + kSize; } + constexpr const_iterator cend() const noexcept { return end(); } + + // NOT IMPLEMENTED + constexpr reverse_iterator rbegin() noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + + // NOT IMPLEMENTED + constexpr reverse_iterator rend() noexcept; + constexpr const_reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + [[nodiscard]] constexpr bool empty() const noexcept { return kSize == 0u; } + + constexpr size_type size() const noexcept { return kSize; } + + constexpr size_type max_size() const noexcept { return size(); } + + constexpr void fill(const T& value) { + for (T& array_value : __data) { + array_value = value; + } + } + + // NOT IMPLEMENTED + constexpr void swap(array& other) noexcept; + + T __data[kSize]; +}; + +// NOT IMPLEMENTED: comparison operators, get, swap, tuple specializations + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/cinttypes.h b/pw_minimal_cpp_stdlib/public/internal/cinttypes.h new file mode 100644 index 0000000..5141862 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/cinttypes.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 "inttypes.h"
diff --git a/pw_minimal_cpp_stdlib/public/internal/cmath.h b/pw_minimal_cpp_stdlib/public/internal/cmath.h new file mode 100644 index 0000000..cec4a7e --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/cmath.h
@@ -0,0 +1,55 @@ +// 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 <math.h> + +namespace std { + +// The integer overloads of these functions are not provided. + +// This is not technically correct, but avoids ambiguous calls to an overloaded +// abs function. +template <typename T> +inline T abs(T value) { + return value < 0 ? -value : value; +} + +#ifdef isfinite +#undef isfinite +#endif // isfinite + +inline bool isfinite(float value) { return __builtin_isfinite(value); } +inline bool isfinite(double value) { return __builtin_isfinite(value); } +inline bool isfinite(long double value) { return __builtin_isfinite(value); } + +#ifdef isnan +#undef isnan +#endif // isnan + +inline bool isnan(float value) { return __builtin_isnan(value); } +inline bool isnan(double value) { return __builtin_isnan(value); } +inline bool isnan(long double value) { return __builtin_isnan(value); } + +#ifdef signbit +#undef signbit +#endif // signbit + +inline bool signbit(float value) { return __builtin_signbit(value); } +inline bool signbit(double value) { return __builtin_signbit(value); } +inline bool signbit(long double value) { return __builtin_signbit(value); } + +using ::round; + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/cstdarg.h b/pw_minimal_cpp_stdlib/public/internal/cstdarg.h new file mode 100644 index 0000000..8d31c67 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/cstdarg.h
@@ -0,0 +1,22 @@ +// 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 <stdarg.h> + +namespace std { + +using ::va_list; + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/cstddef.h b/pw_minimal_cpp_stdlib/public/internal/cstddef.h new file mode 100644 index 0000000..bcb7bb2 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/cstddef.h
@@ -0,0 +1,74 @@ +// 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 <stddef.h> + +namespace std { + +using ::ptrdiff_t; +using ::size_t; +using nullptr_t = decltype(nullptr); +using ::max_align_t; + +#define __cpp_lib_byte 201603L + +enum class byte : unsigned char {}; + +template <typename I> +constexpr I to_integer(byte b) noexcept { + return I(b); +} + +constexpr byte operator|(byte l, byte r) noexcept { + return byte(static_cast<unsigned int>(l) | static_cast<unsigned int>(r)); +} + +constexpr byte operator&(byte l, byte r) noexcept { + return byte(static_cast<unsigned int>(l) & static_cast<unsigned int>(r)); +} + +constexpr byte operator^(byte l, byte r) noexcept { + return byte(static_cast<unsigned int>(l) ^ static_cast<unsigned int>(r)); +} + +constexpr byte operator~(byte b) noexcept { + return byte(~static_cast<unsigned int>(b)); +} + +template <typename I> +constexpr byte operator<<(byte b, I shift) noexcept { + return byte(static_cast<unsigned int>(b) << shift); +} + +template <typename I> +constexpr byte operator>>(byte b, I shift) noexcept { + return byte(static_cast<unsigned int>(b) >> shift); +} + +constexpr byte& operator|=(byte& l, byte r) noexcept { return l = l | r; } +constexpr byte& operator&=(byte& l, byte r) noexcept { return l = l & r; } +constexpr byte& operator^=(byte& l, byte r) noexcept { return l = l ^ r; } + +template <typename I> +inline byte& operator<<=(byte& b, I shift) noexcept { + return b = b << shift; +} + +template <typename I> +inline byte& operator>>=(byte& b, I shift) noexcept { + return b = b >> shift; +} + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/cstdint.h b/pw_minimal_cpp_stdlib/public/internal/cstdint.h new file mode 100644 index 0000000..abe9e04 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/cstdint.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 "stdint.h"
diff --git a/pw_minimal_cpp_stdlib/public/internal/cstdio.h b/pw_minimal_cpp_stdlib/public/internal/cstdio.h new file mode 100644 index 0000000..0a4bae6 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/cstdio.h
@@ -0,0 +1,32 @@ +// 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 <stdio.h> + +namespace std { + +using ::size_t; + +// Only a small subset of functions are exposed here. + +using ::putchar; +using ::puts; +using ::snprintf; +using ::vsnprintf; + +using ::getchar; +using ::sscanf; + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/cstring.h b/pw_minimal_cpp_stdlib/public/internal/cstring.h new file mode 100644 index 0000000..b2f08ad --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/cstring.h
@@ -0,0 +1,39 @@ +// 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 <string.h> + +namespace std { + +using ::size_t; + +// Only a small subset of functions are exposed here. + +using ::memchr; +using ::memcmp; +using ::memcpy; +using ::memmove; +using ::memset; + +using ::strcat; +using ::strcpy; +using ::strncat; +using ::strncpy; + +using ::strcmp; +using ::strlen; +using ::strncmp; + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/iterator.h b/pw_minimal_cpp_stdlib/public/internal/iterator.h new file mode 100644 index 0000000..9c5e9ad --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/iterator.h
@@ -0,0 +1,51 @@ +// 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 <cstddef> + +namespace std { + +#define __cpp_lib_nonmember_container_access 201411L + +template <typename C> +constexpr auto data(C& container) -> decltype(container.data()) { + return container.data(); +} + +template <typename C> +constexpr auto data(const C& container) -> decltype(container.data()) { + return container.data(); +} + +template <typename T, decltype(sizeof(int)) kSize> +constexpr T* data(T (&array)[kSize]) noexcept { + return array; +} + +template <typename C> +constexpr auto size(const C& container) -> decltype(container.size()) { + return container.size(); +} + +template <typename T, decltype(sizeof(int)) kSize> +constexpr decltype(sizeof(int)) size(const T (&)[kSize]) noexcept { + return kSize; +} + +// NOT IMPLEMENTED: Reverse iterators are not implemented. +template <typename> +struct reverse_iterator; + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/limits.h b/pw_minimal_cpp_stdlib/public/internal/limits.h new file mode 100644 index 0000000..6c14180 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/limits.h
@@ -0,0 +1,65 @@ +// 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> + +namespace std { + +template <typename T> +struct numeric_limits { + static constexpr bool is_specialized = false; +}; + +// Only a few of the numeric_limits methods are implemented. +#define _PW_LIMITS_SPECIALIZATION( \ + type, val_signed, val_int, min_value, max_value) \ + template <> \ + struct numeric_limits<type> { \ + static constexpr bool is_specialized = true; \ + \ + static constexpr bool is_signed = (val_signed); \ + static constexpr bool is_integer = (val_int); \ + \ + static constexpr type min() noexcept { return (min_value); } \ + static constexpr type max() noexcept { return (max_value); } \ + } + +#define _PW_INTEGRAL_LIMIT(type, sname, uname) \ + _PW_LIMITS_SPECIALIZATION( \ + signed type, true, true, sname##_MIN, sname##_MAX); \ + _PW_LIMITS_SPECIALIZATION(unsigned type, false, true, 0u, uname##_MAX) + +_PW_LIMITS_SPECIALIZATION(bool, false, true, false, true); +_PW_LIMITS_SPECIALIZATION(char, char(-1) < char(0), true, CHAR_MIN, CHAR_MAX); + +_PW_INTEGRAL_LIMIT(char, SCHAR, UCHAR); +_PW_INTEGRAL_LIMIT(short, SHRT, USHRT); +_PW_INTEGRAL_LIMIT(int, INT, UINT); +_PW_INTEGRAL_LIMIT(long, LONG, ULONG); + +#ifndef LLONG_MIN +#define LLONG_MIN ((long long)(~0ull ^ (~0ull >> 1))) +#define LLONG_MAX ((long long)(~0ull >> 1)) + +#define ULLONG_MIN (0ull) +#define ULLONG_MAX (~0ull) +#endif // LLONG_MIN + +_PW_INTEGRAL_LIMIT(long long, LLONG, ULLONG); + +#undef _PW_LIMITS_SPECIALIZATION +#undef _PW_INTEGRAL_LIMIT + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/new.h b/pw_minimal_cpp_stdlib/public/internal/new.h new file mode 100644 index 0000000..d21d991 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/new.h
@@ -0,0 +1,17 @@ +// 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 + +// Placement new +inline void* operator new(decltype(sizeof(0)), void* ptr) { return ptr; }
diff --git a/pw_minimal_cpp_stdlib/public/internal/string_view.h b/pw_minimal_cpp_stdlib/public/internal/string_view.h new file mode 100644 index 0000000..65ee858 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/string_view.h
@@ -0,0 +1,174 @@ +// 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 <algorithm> +#include <cstddef> +#include <iterator> + +#define __cpp_lib_string_view 201606L + +namespace std { + +template <typename T> +class basic_string_view { + public: + using traits_type = void; // No traits object is used. + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using const_iterator = const T*; + using iterator = const_iterator; + using const_reverse_iterator = ::std::reverse_iterator<const_iterator>; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + + static constexpr size_type npos = size_type(-1); + + constexpr basic_string_view() noexcept : string_(nullptr), size_(0) {} + constexpr basic_string_view(const basic_string_view&) noexcept = default; + constexpr basic_string_view(const T* string, size_type count) + : string_(string), size_(count) {} + constexpr basic_string_view(const T* string) + : string_(string), size_(CStringLength(string)) {} + + constexpr basic_string_view& operator=(const basic_string_view&) noexcept = + default; + + constexpr const_iterator begin() const noexcept { return string_; } + constexpr const_iterator cbegin() const noexcept { return begin(); } + + constexpr const_iterator end() const noexcept { return string_ + size_; } + constexpr const_iterator cend() const noexcept { return end(); } + + // NOT IMPLEMENTED: Reverse iterators not supported. + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + + constexpr const_reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + constexpr const_reference operator[](size_type pos) const { + return data()[pos]; + } + + // NOT IMPLEMENTED: at() has no bounds checking. + constexpr const_reference at(size_type pos) const { return data()[pos]; } + + constexpr const_reference front() const { return data()[0]; } + + constexpr const_reference back() const { return data()[size() - 1]; } + + constexpr const_pointer data() const noexcept { return string_; } + + constexpr size_type size() const noexcept { return size_; } + constexpr size_type length() const noexcept { return size(); } + + constexpr size_type max_size() const noexcept { return ~size_t{0}; } + + [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0u; } + + constexpr void remove_prefix(size_type characters) { + string_ += characters; + size_ -= characters; + } + + constexpr void remove_suffix(size_type characters) { size_ -= characters; } + + constexpr void swap(basic_string_view& other) noexcept { + pointer temp_string = string_; + string_ = other.string_; + other.string_ = temp_string; + + size_type temp_size = size_; + size_ = other.size_; + other.size_ = temp_size; + } + + // NOT IMPLEMENTED: copy does no bounds checking. + constexpr size_type copy(T* dest, size_type count, size_type pos = 0) const { + const size_type to_copy = min(count, size() - pos); + for (size_type i = pos; i < pos + to_copy; ++i) { + *dest++ = string_[i]; + } + return to_copy; + } + + constexpr basic_string_view substr(size_type pos = 0, + size_type count = npos) const { + return basic_string_view(string_ + pos, min(count, size() - pos)); + } + + // NOT IMPLEMENTED: These functions and their overloads are not defined. + constexpr int compare(basic_string_view view) const noexcept; + constexpr bool starts_with(basic_string_view view) const noexcept; + constexpr bool ends_with(basic_string_view view) const noexcept; + constexpr size_type find(basic_string_view view, + size_type pos = 0) const noexcept; + constexpr size_type rfind(basic_string_view view, + size_type pos = npos) const noexcept; + constexpr size_type find_first_of(basic_string_view view, + size_type pos = 0) const noexcept; + constexpr size_type find_last_of(basic_string_view view, + size_type pos = npos) const noexcept; + constexpr size_type find_first_not_of(basic_string_view view, + size_type pos = 0) const noexcept; + constexpr size_type find_last_not_of(basic_string_view view, + size_type pos = npos) const noexcept; + + private: + static constexpr size_type CStringLength(const T* string) { + size_type length = 0; + while (string[length] != T()) { + length += 1; + } + return length; + } + + const_pointer string_; + size_type size_; +}; + +template <typename T> +constexpr bool operator==(basic_string_view<T> lhs, basic_string_view<T> rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + for (typename basic_string_view<T>::size_type i = 0; i < lhs.size(); ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + return true; +} + +template <typename T> +constexpr bool operator!=(basic_string_view<T> lhs, basic_string_view<T> rhs) { + return !(lhs == rhs); +} + +// NOT IMPLEMENTED: Other comparison operators are not defined. + +using string_view = basic_string_view<char>; +using wstring_view = basic_string_view<wchar_t>; +using u16string_view = basic_string_view<char16_t>; +using u32string_view = basic_string_view<char32_t>; + +// NOT IMPLEMENTED: string_view literals cannot be implemented since they do not +// start with _. + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/type_traits.h b/pw_minimal_cpp_stdlib/public/internal/type_traits.h new file mode 100644 index 0000000..422b2df --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/type_traits.h
@@ -0,0 +1,425 @@ +// 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 + +namespace std { + +#define __cpp_lib_transformation_trait_aliases 201304L +#define __cpp_lib_type_trait_variable_templates 201510L + +template <decltype(sizeof(0)) kLength, + decltype(sizeof(0)) kAlignment> // no default +struct aligned_storage { + struct type { + alignas(kAlignment) unsigned char __data[kLength]; + }; +}; + +template <decltype(sizeof(0)) kLength, + decltype(sizeof(0)) kAlignment> // no default +using aligned_storage_t = typename aligned_storage<kLength, kAlignment>::type; + +#define __cpp_lib_integral_constant_callable 201304L + +template <typename T, T kValue> +struct integral_constant { + using value_type = T; + using type = integral_constant; + + static constexpr T value = kValue; + + constexpr operator value_type() const noexcept { return value; } + + constexpr value_type operator()() const noexcept { return value; } +}; + +#define __cpp_lib_bool_constant 201505L + +template <bool kValue> +using bool_constant = integral_constant<bool, kValue>; + +using true_type = bool_constant<true>; +using false_type = bool_constant<false>; + +template <typename T> +struct is_array : false_type {}; + +template <typename T> +struct is_array<T[]> : true_type {}; + +template <typename T, decltype(sizeof(int)) kSize> +struct is_array<T[kSize]> : true_type {}; + +template <typename T> +inline constexpr bool is_array_v = is_array<T>::value; + +template <typename T> +struct is_const : false_type {}; + +template <typename T> +struct is_const<const T> : true_type {}; + +// NOT IMPLEMENTED: is_enum requires compiler builtins. +template <typename T> +struct is_enum : false_type {}; + +template <typename T> +inline constexpr bool is_enum_v = is_enum<T>::value; + +template <typename T> +struct remove_cv; // Forward declaration + +namespace impl { + +template <typename T> +struct is_floating_point : false_type {}; + +template <> +struct is_floating_point<float> : true_type {}; +template <> +struct is_floating_point<double> : true_type {}; +template <> +struct is_floating_point<long double> : true_type {}; + +} // namespace impl + +template <typename T> +struct is_floating_point + : impl::is_floating_point<typename remove_cv<T>::type> {}; + +template <typename T> +inline constexpr bool is_floating_point_v = is_floating_point<T>::value; + +namespace impl { + +template <typename T> +struct is_integral : false_type {}; + +template <> +struct is_integral<bool> : true_type {}; +template <> +struct is_integral<char> : true_type {}; +template <> +struct is_integral<char16_t> : true_type {}; +template <> +struct is_integral<char32_t> : true_type {}; +template <> +struct is_integral<wchar_t> : true_type {}; + +template <> +struct is_integral<short> : true_type {}; +template <> +struct is_integral<unsigned short> : true_type {}; +template <> +struct is_integral<int> : true_type {}; +template <> +struct is_integral<unsigned int> : true_type {}; +template <> +struct is_integral<long> : true_type {}; +template <> +struct is_integral<unsigned long> : true_type {}; +template <> +struct is_integral<long long> : true_type {}; +template <> +struct is_integral<unsigned long long> : true_type {}; + +} // namespace impl + +template <typename T> +struct is_integral : impl::is_integral<typename remove_cv<T>::type> {}; + +template <typename T> +inline constexpr bool is_integral_v = is_integral<T>::value; + +template <typename T> +struct is_arithmetic + : bool_constant<is_integral_v<T> || is_floating_point_v<T>> {}; + +template <typename T> +inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; + +#define __cpp_lib_is_null_pointer 201309L + +template <typename T> +struct is_null_pointer : false_type {}; + +template <> +struct is_null_pointer<decltype(nullptr)> : true_type {}; + +template <typename T> +inline constexpr bool is_null_pointer_v = is_null_pointer<T>::value; + +template <typename T> +struct is_pointer : false_type {}; + +template <typename T> +struct is_pointer<T*> : true_type {}; + +template <typename T> +inline constexpr bool is_pointer_v = is_pointer<T>::value; + +template <typename T, typename U> +struct is_same : false_type {}; + +template <typename T> +struct is_same<T, T> : true_type {}; + +template <typename T, typename U> +inline constexpr bool is_same_v = is_same<T, U>::value; + +namespace impl { + +template <typename T, bool = is_arithmetic<T>::value> +struct is_signed : integral_constant<bool, T(-1) < T(0)> {}; + +template <typename T> +struct is_signed<T, false> : false_type {}; + +} // namespace impl + +template <typename T> +struct is_signed : impl::is_signed<T>::type {}; + +template <typename T> +inline constexpr bool is_signed_v = is_signed<T>::value; + +template <typename T> +struct is_unsigned : bool_constant<!is_signed_v<T>> {}; + +template <typename T> +inline constexpr bool is_unsigned_v = is_unsigned<T>::value; + +template <typename T> +struct is_void : is_same<void, typename remove_cv<T>::type> {}; + +template <typename T> +inline constexpr bool is_void_v = is_void<T>::value; + +template <bool kBool, typename TrueType, typename FalseType> +struct conditional { + using type = TrueType; +}; + +template <typename TrueType, typename FalseType> +struct conditional<false, TrueType, FalseType> { + using type = FalseType; +}; + +template <bool kBool, typename TrueType, typename FalseType> +using conditional_t = typename conditional<kBool, TrueType, FalseType>::type; + +template <bool kEnable, typename T = void> +struct enable_if { + using type = T; +}; + +template <typename T> +struct enable_if<false, T> {}; + +template <bool kEnable, typename T = void> +using enable_if_t = typename enable_if<kEnable, T>::type; + +template <typename T> +struct remove_const { + using type = T; +}; + +template <typename T> +struct remove_const<const T> { + using type = T; +}; + +template <typename T> +using remove_const_t = typename remove_const<T>::type; + +template <typename T> +struct remove_volatile { + using type = T; +}; + +template <typename T> +struct remove_volatile<volatile T> { + using type = T; +}; + +template <typename T> +using remove_volatile_t = typename remove_volatile<T>::type; + +template <typename T> +struct remove_cv { + using type = remove_volatile_t<remove_const_t<T>>; +}; + +template <typename T> +using remove_cv_t = typename remove_cv<T>::type; + +template <typename T> +struct remove_extent { + using type = T; +}; + +template <typename T> +struct remove_extent<T[]> { + using type = T; +}; + +template <typename T, decltype(sizeof(0)) kSize> +struct remove_extent<T[kSize]> { + using type = T; +}; + +template <typename T> +using remove_extent_t = typename remove_extent<T>::type; + +template <typename T> +struct remove_pointer { + using type = T; +}; + +template <typename T> +struct remove_pointer<T*> { + using type = T; +}; + +template <typename T> +struct remove_pointer<T* const> { + using type = T; +}; + +template <typename T> +struct remove_pointer<T* volatile> { + using type = T; +}; + +template <typename T> +struct remove_pointer<T* const volatile> { + using type = T; +}; + +template <typename T> +using remove_pointer_t = typename remove_pointer<T>::type; + +template <typename T> +struct remove_reference { + using type = T; +}; + +template <typename T> +struct remove_reference<T&> { + using type = T; +}; + +template <typename T> +struct remove_reference<T&&> { + using type = T; +}; + +template <typename T> +using remove_reference_t = typename remove_reference<T>::type; + +// NOT IMPLEMENTED: This implementation is INCOMPLETE, as it does not cover +// function types. +template <typename T> +struct decay { + private: + using U = remove_reference_t<T>; + + public: + using type = + conditional_t<is_array<U>::value, remove_extent_t<U>*, remove_cv_t<U>>; +}; + +template <typename T> +using decay_t = typename decay<T>::type; + +#define __cpp_lib_type_identity 201806 + +template <class T> +struct type_identity { + using type = T; +}; + +template <typename T> +using type_identity_t = typename type_identity<T>::type; + +#define __cpp_lib_void_t void_t 201411L + +template <typename...> +using void_t = void; + +// NOT IMPLEMENTED: add_rvalue_refernce does work with reference types. +template <typename T> +struct add_rvalue_reference { + using type = T&&; +}; + +template <typename T> +using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; + +template <typename T> +add_rvalue_reference_t<T> declval() noexcept; + +namespace impl { + +template <typename> +using templated_true = true_type; + +template <typename T> +auto returnable(int) -> templated_true<T()>; + +template <typename> +auto returnable(...) -> false_type; + +template <typename From, typename To> +auto convertible(int) + -> templated_true<decltype(declval<void (&)(To)>()(declval<From>()))>; + +template <typename, typename> +auto convertible(...) -> false_type; + +} // namespace impl + +template <typename From, typename To> +struct is_convertible + : bool_constant<(decltype(impl::returnable<To>(0))() && + decltype(impl::convertible<From, To>(0))()) || + (is_void_v<From> && is_void_v<To>)> {}; + +template <typename T, typename U> +inline constexpr bool is_convertible_v = is_convertible<T, U>::value; + +// NOT IMPLEMENTED: Stubs are provided for these traits classes, but they do not +// return useful values. Many of these would require compiler builtins. +template <typename T> +struct is_function : false_type {}; +template <typename T> +struct is_trivially_copyable : true_type {}; +template <typename T> +struct is_polymorphic : false_type {}; +template <typename T, typename U> +struct is_base_of : false_type {}; +template <typename T> +struct extent : integral_constant<decltype(sizeof(int)), 1> {}; +template <typename T> +inline constexpr bool extent_v = extent<T>::value; +template <typename T> +struct underlying_type { + using type = T; +}; +template <typename T> +using underlying_type_t = typename underlying_type<T>::type; +template <typename T> +inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value; + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/utility.h b/pw_minimal_cpp_stdlib/public/internal/utility.h new file mode 100644 index 0000000..6d238f7 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/internal/utility.h
@@ -0,0 +1,25 @@ +// 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 + +namespace std { + +// Forward declare these classes, which are specialized in other headers. +template <decltype(sizeof(0)), typename> +struct tuple_element; + +template <typename> +struct tuple_size; + +} // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/iterator b/pw_minimal_cpp_stdlib/public/iterator new file mode 120000 index 0000000..4703aa8 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/iterator
@@ -0,0 +1 @@ +internal/iterator.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/limits b/pw_minimal_cpp_stdlib/public/limits new file mode 120000 index 0000000..8309de0 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/limits
@@ -0,0 +1 @@ +internal/limits.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/new b/pw_minimal_cpp_stdlib/public/new new file mode 120000 index 0000000..ed0129c --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/new
@@ -0,0 +1 @@ +internal/new.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/string_view b/pw_minimal_cpp_stdlib/public/string_view new file mode 120000 index 0000000..8e1be67 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/string_view
@@ -0,0 +1 @@ +internal/string_view.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/type_traits b/pw_minimal_cpp_stdlib/public/type_traits new file mode 120000 index 0000000..71b1217 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/type_traits
@@ -0,0 +1 @@ +internal/type_traits.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/public/utility b/pw_minimal_cpp_stdlib/public/utility new file mode 120000 index 0000000..58c32f2 --- /dev/null +++ b/pw_minimal_cpp_stdlib/public/utility
@@ -0,0 +1 @@ +internal/utility.h \ No newline at end of file
diff --git a/pw_minimal_cpp_stdlib/test.cc b/pw_minimal_cpp_stdlib/test.cc new file mode 100644 index 0000000..1d9c6c3 --- /dev/null +++ b/pw_minimal_cpp_stdlib/test.cc
@@ -0,0 +1,151 @@ +// Copyright 2019 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. + +// Include all of the provided headers, even if they aren't tested. +#include <algorithm> +#include <array> +#include <cinttypes> +#include <cmath> +#include <cstdarg> +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstring> +#include <iterator> +#include <limits> +#include <new> +#include <string_view> +#include <type_traits> +#include <utility> + +#include "gtest/gtest.h" + +namespace { + +TEST(Algorithm, Basic) { + static_assert(std::min(1, 2) == 1); + static_assert(std::max(1, 2) == 2); + + EXPECT_EQ(std::forward<int>(2), 2); +} + +TEST(Array, Basic) { + constexpr std::array<int, 4> array{0, 1, 2, 3}; + + static_assert(array[2] == 2); + + for (int i = 0; i < static_cast<int>(array.size()); ++i) { + EXPECT_EQ(i, array[i]); + } +} + +TEST(Cmath, Basic) { + EXPECT_EQ(std::abs(-1), 1); + EXPECT_EQ(std::abs(1), 1); + + EXPECT_TRUE(std::isfinite(1.0)); + EXPECT_FALSE(std::isfinite(1.0 / 0.0)); + + EXPECT_FALSE(std::isnan(1.0)); + EXPECT_TRUE(std::isnan(0.0 / 0.0)); + + EXPECT_FALSE(std::signbit(1.0)); + EXPECT_TRUE(std::signbit(-1.0)); +} + +TEST(Cstddef, Basic) { + using std::byte; + byte foo = byte{12}; + EXPECT_EQ(foo, byte{12}); +} + +TEST(Iterator, Basic) { + std::array<int, 3> foo{3, 2, 1}; + + EXPECT_EQ(std::data(foo), foo.data()); + EXPECT_EQ(std::size(foo), foo.size()); + + foo.fill(99); + EXPECT_EQ(foo[0], 99); + EXPECT_EQ(foo[1], 99); + EXPECT_EQ(foo[2], 99); +} + +TEST(Limits, Basic) { + static_assert(std::numeric_limits<unsigned char>::is_specialized); + static_assert(std::numeric_limits<unsigned char>::is_integer); + static_assert(std::numeric_limits<unsigned char>::min() == 0u); + static_assert(std::numeric_limits<unsigned char>::max() == 255u); + + static_assert(std::numeric_limits<signed char>::is_specialized); + static_assert(std::numeric_limits<signed char>::is_integer); + static_assert(std::numeric_limits<signed char>::min() == -128); + static_assert(std::numeric_limits<signed char>::max() == 127); + + // Assume 64-bit long long + static_assert(std::numeric_limits<long long>::is_specialized); + static_assert(std::numeric_limits<long long>::is_integer); + static_assert(std::numeric_limits<long long>::min() == + (-9223372036854775807ll - 1)); + static_assert(std::numeric_limits<long long>::max() == 9223372036854775807ll); + + static_assert(std::numeric_limits<unsigned long long>::is_specialized); + static_assert(std::numeric_limits<unsigned long long>::is_integer); + static_assert(std::numeric_limits<unsigned long long>::min() == 0u); + static_assert(std::numeric_limits<unsigned long long>::max() == + 18446744073709551615ull); +} + +TEST(New, Basic) { + unsigned char value[4]; + new (value) int(1234); + + int int_value; + std::memcpy(&int_value, value, sizeof(int_value)); + EXPECT_EQ(1234, int_value); +} + +TEST(StringView, Basic) { + constexpr std::string_view value("1234567890"); + static_assert(value.size() == 10); + static_assert(value[1] == '2'); + + char buffer[] = "!!!!!"; + constexpr size_t buffer_size = sizeof(buffer) - 1; // always keep the \0 + + value.copy(buffer, buffer_size, 10); + EXPECT_STREQ(buffer, "!!!!!"); + + value.copy(buffer, buffer_size, 9); + EXPECT_STREQ(buffer, "0!!!!"); + + value.copy(buffer, buffer_size, 2); + EXPECT_STREQ(buffer, "34567"); + + value.copy(buffer, buffer_size); + EXPECT_STREQ(buffer, "12345"); +} + +TEST(TypeTraits, Basic) { + static_assert(std::is_integral_v<bool>); + static_assert(!std::is_integral_v<float>); + + static_assert(std::is_floating_point_v<float>); + static_assert(!std::is_floating_point_v<bool>); + + static_assert(std::is_same_v<float, float>); + static_assert(!std::is_same_v<char, unsigned char>); +} + +} // namespace