diff options
author | 2020-11-24 13:41:10 -0800 | |
---|---|---|
committer | 2020-12-07 17:09:06 -0800 | |
commit | 5444fc8c17d65453e3623d2307a813e611c72c6f (patch) | |
tree | bf999aaa8c1b302d3b5de4a377aac8fe80e9fb7d | |
parent | f22c4c072cec6bec83ac08cecfb55e953ff21ea5 (diff) |
FTL: Standardize style
Adopt STL-flavored Google style for internal and libbase consistency.
Add README.
Bug: 160012986
Test: ftl_test
Change-Id: I1056f6fa890d68717386d634c398bb2faa46775c
-rw-r--r-- | include/ftl/array_traits.h (renamed from include/ftl/ArrayTraits.h) | 18 | ||||
-rw-r--r-- | include/ftl/initializer_list.h (renamed from include/ftl/InitializerList.h) | 6 | ||||
-rw-r--r-- | include/ftl/small_map.h (renamed from include/ftl/SmallMap.h) | 36 | ||||
-rw-r--r-- | include/ftl/small_vector.h (renamed from include/ftl/SmallVector.h) | 90 | ||||
-rw-r--r-- | include/ftl/static_vector.h (renamed from include/ftl/StaticVector.h) | 95 | ||||
-rw-r--r-- | libs/ftl/Android.bp | 6 | ||||
-rw-r--r-- | libs/ftl/README.md | 41 | ||||
-rw-r--r-- | libs/ftl/small_map_test.cpp (renamed from libs/ftl/SmallMap_test.cpp) | 2 | ||||
-rw-r--r-- | libs/ftl/small_vector_test.cpp (renamed from libs/ftl/SmallVector_test.cpp) | 16 | ||||
-rw-r--r-- | libs/ftl/static_vector_test.cpp (renamed from libs/ftl/StaticVector_test.cpp) | 20 |
10 files changed, 187 insertions, 143 deletions
diff --git a/include/ftl/ArrayTraits.h b/include/ftl/array_traits.h index ff685c5b48..011034f98f 100644 --- a/include/ftl/ArrayTraits.h +++ b/include/ftl/array_traits.h @@ -28,8 +28,8 @@ namespace android::ftl { template <typename T> struct ArrayTraits { using value_type = T; - using size_type = size_t; - using difference_type = ptrdiff_t; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; using pointer = value_type*; using reference = value_type&; @@ -99,34 +99,34 @@ public: // Mixin to define comparison operators for an array-like template. // TODO: Replace with operator<=> in C++20. -template <template <typename, size_t> class Array> +template <template <typename, std::size_t> class Array> struct ArrayComparators { - template <typename T, size_t N, size_t M> + template <typename T, std::size_t N, std::size_t M> friend bool operator==(const Array<T, N>& lhs, const Array<T, M>& rhs) { return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } - template <typename T, size_t N, size_t M> + template <typename T, std::size_t N, std::size_t M> friend bool operator<(const Array<T, N>& lhs, const Array<T, M>& rhs) { return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } - template <typename T, size_t N, size_t M> + template <typename T, std::size_t N, std::size_t M> friend bool operator>(const Array<T, N>& lhs, const Array<T, M>& rhs) { return rhs < lhs; } - template <typename T, size_t N, size_t M> + template <typename T, std::size_t N, std::size_t M> friend bool operator!=(const Array<T, N>& lhs, const Array<T, M>& rhs) { return !(lhs == rhs); } - template <typename T, size_t N, size_t M> + template <typename T, std::size_t N, std::size_t M> friend bool operator>=(const Array<T, N>& lhs, const Array<T, M>& rhs) { return !(lhs < rhs); } - template <typename T, size_t N, size_t M> + template <typename T, std::size_t N, std::size_t M> friend bool operator<=(const Array<T, N>& lhs, const Array<T, M>& rhs) { return !(lhs > rhs); } diff --git a/include/ftl/InitializerList.h b/include/ftl/initializer_list.h index bb99280745..62f63b7c16 100644 --- a/include/ftl/InitializerList.h +++ b/include/ftl/initializer_list.h @@ -27,7 +27,7 @@ namespace android::ftl { // first S0 arguments, the second element is initialized with the next S1 arguments, and so // on. The list of Types (T0, ..., TM) is flattened, so M is equal to the sum of the Sizes. // -// The InitializerList is created using ftl::init::list, and is consumed by constructors of +// An InitializerList is created using ftl::init::list, and is consumed by constructors of // containers. The function call operator is overloaded such that arguments are accumulated // in a tuple with each successive call. For instance, the following calls initialize three // strings using different constructors, i.e. string literal, default, and count/character: @@ -49,7 +49,7 @@ namespace android::ftl { template <typename T, typename Sizes = std::index_sequence<>, typename... Types> struct InitializerList; -template <typename T, size_t... Sizes, typename... Types> +template <typename T, std::size_t... Sizes, typename... Types> struct InitializerList<T, std::index_sequence<Sizes...>, Types...> { // Creates a superset InitializerList by appending the number of arguments to Sizes, and // expanding Types with forwarding references for each argument. @@ -72,7 +72,7 @@ struct KeyValue {}; // Shorthand for key-value pairs that assigns the first argument to the key, and the rest to the // value. The specialization is on KeyValue rather than std::pair, so that ftl::init::list works // with the latter. -template <typename K, typename V, size_t... Sizes, typename... Types> +template <typename K, typename V, std::size_t... Sizes, typename... Types> struct InitializerList<KeyValue<K, V>, std::index_sequence<Sizes...>, Types...> { // Accumulate the three arguments to std::pair's piecewise constructor. template <typename... Args> diff --git a/include/ftl/SmallMap.h b/include/ftl/small_map.h index 87ae99cace..d05836950a 100644 --- a/include/ftl/SmallMap.h +++ b/include/ftl/small_map.h @@ -16,8 +16,8 @@ #pragma once -#include <ftl/InitializerList.h> -#include <ftl/SmallVector.h> +#include <ftl/initializer_list.h> +#include <ftl/small_vector.h> #include <functional> #include <optional> @@ -54,7 +54,7 @@ namespace android::ftl { // // assert(map == SmallMap(ftl::init::map(-1, "xyz")(42, "???")(123, "abc"))); // -template <typename K, typename V, size_t N> +template <typename K, typename V, std::size_t N> class SmallMap final { using Map = SmallVector<std::pair<const K, V>, N>; @@ -92,26 +92,26 @@ public: // ftl::SmallMap map = ftl::init::map(0, 'a')(1, 'b')(2, 'c'); // static_assert(std::is_same_v<decltype(map), ftl::SmallMap<int, char, 3>>); // - template <typename U, size_t... Sizes, typename... Types> - SmallMap(InitializerList<U, std::index_sequence<Sizes...>, Types...>&& init) - : mMap(std::move(init)) { + template <typename U, std::size_t... Sizes, typename... Types> + SmallMap(InitializerList<U, std::index_sequence<Sizes...>, Types...>&& list) + : map_(std::move(list)) { // TODO: Enforce unique keys. } - size_type max_size() const { return mMap.max_size(); } - size_type size() const { return mMap.size(); } - bool empty() const { return mMap.empty(); } + size_type max_size() const { return map_.max_size(); } + size_type size() const { return map_.size(); } + bool empty() const { return map_.empty(); } // Returns whether the map is backed by static or dynamic storage. - bool dynamic() const { return mMap.dynamic(); } + bool dynamic() const { return map_.dynamic(); } - iterator begin() { return mMap.begin(); } + iterator begin() { return map_.begin(); } const_iterator begin() const { return cbegin(); } - const_iterator cbegin() const { return mMap.cbegin(); } + const_iterator cbegin() const { return map_.cbegin(); } - iterator end() { return mMap.end(); } + iterator end() { return map_.end(); } const_iterator end() const { return cend(); } - const_iterator cend() const { return mMap.cend(); } + const_iterator cend() const { return map_.cend(); } // Returns whether a mapping exists for the given key. bool contains(const key_type& key) const { @@ -173,16 +173,16 @@ public: } private: - Map mMap; + Map map_; }; // Deduction guide for in-place constructor. -template <typename K, typename V, size_t... Sizes, typename... Types> +template <typename K, typename V, std::size_t... Sizes, typename... Types> SmallMap(InitializerList<KeyValue<K, V>, std::index_sequence<Sizes...>, Types...>&&) -> SmallMap<K, V, sizeof...(Sizes)>; // Returns whether the key-value pairs of two maps are equal. -template <typename K, typename V, size_t N, typename Q, typename W, size_t M> +template <typename K, typename V, std::size_t N, typename Q, typename W, std::size_t M> bool operator==(const SmallMap<K, V, N>& lhs, const SmallMap<Q, W, M>& rhs) { if (lhs.size() != rhs.size()) return false; @@ -197,7 +197,7 @@ bool operator==(const SmallMap<K, V, N>& lhs, const SmallMap<Q, W, M>& rhs) { } // TODO: Remove in C++20. -template <typename K, typename V, size_t N, typename Q, typename W, size_t M> +template <typename K, typename V, std::size_t N, typename Q, typename W, std::size_t M> inline bool operator!=(const SmallMap<K, V, N>& lhs, const SmallMap<Q, W, M>& rhs) { return !(lhs == rhs); } diff --git a/include/ftl/SmallVector.h b/include/ftl/small_vector.h index 2f05a9bf02..a8686baa8b 100644 --- a/include/ftl/SmallVector.h +++ b/include/ftl/small_vector.h @@ -16,8 +16,8 @@ #pragma once -#include <ftl/ArrayTraits.h> -#include <ftl/StaticVector.h> +#include <ftl/array_traits.h> +#include <ftl/static_vector.h> #include <algorithm> #include <iterator> @@ -29,7 +29,7 @@ namespace android::ftl { template <typename> -struct IsSmallVector; +struct is_small_vector; // ftl::StaticVector that promotes to std::vector when full. SmallVector is a drop-in replacement // for std::vector with statically allocated storage for N elements, whose goal is to improve run @@ -74,7 +74,7 @@ struct IsSmallVector; // assert(strings[1] == "123"); // assert(strings[2] == "???"); // -template <typename T, size_t N> +template <typename T, std::size_t N> class SmallVector final : ArrayTraits<T>, ArrayComparators<SmallVector> { using Static = StaticVector<T, N>; using Dynamic = SmallVector<T, 0>; @@ -103,25 +103,25 @@ public: // Constructs at most N elements. See StaticVector for underlying constructors. template <typename Arg, typename... Args, - typename = std::enable_if_t<!IsSmallVector<remove_cvref_t<Arg>>{}>> + typename = std::enable_if_t<!is_small_vector<remove_cvref_t<Arg>>{}>> SmallVector(Arg&& arg, Args&&... args) - : mVector(std::in_place_type<Static>, std::forward<Arg>(arg), + : vector_(std::in_place_type<Static>, std::forward<Arg>(arg), std::forward<Args>(args)...) {} // Copies at most N elements from a smaller convertible vector. - template <typename U, size_t M, typename = std::enable_if_t<M <= N>> + template <typename U, std::size_t M, typename = std::enable_if_t<M <= N>> SmallVector(const SmallVector<U, M>& other) - : SmallVector(IteratorRange, other.begin(), other.end()) {} + : SmallVector(kIteratorRange, other.begin(), other.end()) {} - void swap(SmallVector& other) { mVector.swap(other.mVector); } + void swap(SmallVector& other) { vector_.swap(other.vector_); } // Returns whether the vector is backed by static or dynamic storage. - bool dynamic() const { return std::holds_alternative<Dynamic>(mVector); } + bool dynamic() const { return std::holds_alternative<Dynamic>(vector_); } // Avoid std::visit as it generates a dispatch table. #define DISPATCH(T, F, ...) \ T F() __VA_ARGS__ { \ - return dynamic() ? std::get<Dynamic>(mVector).F() : std::get<Static>(mVector).F(); \ + return dynamic() ? std::get<Dynamic>(vector_).F() : std::get<Static>(vector_).F(); \ } DISPATCH(size_type, max_size, const) @@ -157,7 +157,7 @@ public: #undef DISPATCH reference operator[](size_type i) { - return dynamic() ? std::get<Dynamic>(mVector)[i] : std::get<Static>(mVector)[i]; + return dynamic() ? std::get<Dynamic>(vector_)[i] : std::get<Static>(vector_)[i]; } const_reference operator[](size_type i) const { return const_cast<SmallVector&>(*this)[i]; } @@ -175,9 +175,9 @@ public: template <typename... Args> reference replace(const_iterator it, Args&&... args) { if (dynamic()) { - return std::get<Dynamic>(mVector).replace(it, std::forward<Args>(args)...); + return std::get<Dynamic>(vector_).replace(it, std::forward<Args>(args)...); } else { - return std::get<Static>(mVector).replace(it, std::forward<Args>(args)...); + return std::get<Static>(vector_).replace(it, std::forward<Args>(args)...); } } @@ -188,9 +188,9 @@ public: // template <typename... Args> reference emplace_back(Args&&... args) { - constexpr auto insertStatic = &Static::template emplace_back<Args...>; - constexpr auto insertDynamic = &Dynamic::template emplace_back<Args...>; - return *insert<insertStatic, insertDynamic>(std::forward<Args>(args)...); + constexpr auto kInsertStatic = &Static::template emplace_back<Args...>; + constexpr auto kInsertDynamic = &Dynamic::template emplace_back<Args...>; + return *insert<kInsertStatic, kInsertDynamic>(std::forward<Args>(args)...); } // Appends an element. @@ -199,19 +199,19 @@ public: // Otherwise, only the end() iterator is invalidated. // void push_back(const value_type& v) { - constexpr auto insertStatic = + constexpr auto kInsertStatic = static_cast<bool (Static::*)(const value_type&)>(&Static::push_back); - constexpr auto insertDynamic = + constexpr auto kInsertDynamic = static_cast<bool (Dynamic::*)(const value_type&)>(&Dynamic::push_back); - insert<insertStatic, insertDynamic>(v); + insert<kInsertStatic, kInsertDynamic>(v); } void push_back(value_type&& v) { - constexpr auto insertStatic = + constexpr auto kInsertStatic = static_cast<bool (Static::*)(value_type&&)>(&Static::push_back); - constexpr auto insertDynamic = + constexpr auto kInsertDynamic = static_cast<bool (Dynamic::*)(value_type&&)>(&Dynamic::push_back); - insert<insertStatic, insertDynamic>(std::move(v)); + insert<kInsertStatic, kInsertDynamic>(std::move(v)); } // Removes the last element. The vector must not be empty, or the call is erroneous. @@ -220,9 +220,9 @@ public: // void pop_back() { if (dynamic()) { - std::get<Dynamic>(mVector).pop_back(); + std::get<Dynamic>(vector_).pop_back(); } else { - std::get<Static>(mVector).pop_back(); + std::get<Static>(vector_).pop_back(); } } @@ -233,39 +233,39 @@ public: // void unstable_erase(iterator it) { if (dynamic()) { - std::get<Dynamic>(mVector).unstable_erase(it); + std::get<Dynamic>(vector_).unstable_erase(it); } else { - std::get<Static>(mVector).unstable_erase(it); + std::get<Static>(vector_).unstable_erase(it); } } private: - template <auto insertStatic, auto insertDynamic, typename... Args> + template <auto InsertStatic, auto InsertDynamic, typename... Args> auto insert(Args&&... args) { - if (Dynamic* const vector = std::get_if<Dynamic>(&mVector)) { - return (vector->*insertDynamic)(std::forward<Args>(args)...); + if (Dynamic* const vector = std::get_if<Dynamic>(&vector_)) { + return (vector->*InsertDynamic)(std::forward<Args>(args)...); } - auto& vector = std::get<Static>(mVector); + auto& vector = std::get<Static>(vector_); if (vector.full()) { - return (promote(vector).*insertDynamic)(std::forward<Args>(args)...); + return (promote(vector).*InsertDynamic)(std::forward<Args>(args)...); } else { - return (vector.*insertStatic)(std::forward<Args>(args)...); + return (vector.*InsertStatic)(std::forward<Args>(args)...); } } - Dynamic& promote(Static& staticVector) { - assert(staticVector.full()); + Dynamic& promote(Static& static_vector) { + assert(static_vector.full()); // Allocate double capacity to reduce probability of reallocation. Dynamic vector; vector.reserve(Static::max_size() * 2); - std::move(staticVector.begin(), staticVector.end(), std::back_inserter(vector)); + std::move(static_vector.begin(), static_vector.end(), std::back_inserter(vector)); - return mVector.template emplace<Dynamic>(std::move(vector)); + return vector_.template emplace<Dynamic>(std::move(vector)); } - std::variant<Static, Dynamic> mVector; + std::variant<Static, Dynamic> vector_; }; // Partial specialization without static storage. @@ -360,13 +360,13 @@ public: }; template <typename> -struct IsSmallVector : std::false_type {}; +struct is_small_vector : std::false_type {}; -template <typename T, size_t N> -struct IsSmallVector<SmallVector<T, N>> : std::true_type {}; +template <typename T, std::size_t N> +struct is_small_vector<SmallVector<T, N>> : std::true_type {}; // Deduction guide for array constructor. -template <typename T, size_t N> +template <typename T, std::size_t N> SmallVector(T (&)[N]) -> SmallVector<std::remove_cv_t<T>, N>; // Deduction guide for variadic constructor. @@ -375,15 +375,15 @@ template <typename T, typename... Us, typename V = std::decay_t<T>, SmallVector(T&&, Us&&...) -> SmallVector<V, 1 + sizeof...(Us)>; // Deduction guide for in-place constructor. -template <typename T, size_t... Sizes, typename... Types> +template <typename T, std::size_t... Sizes, typename... Types> SmallVector(InitializerList<T, std::index_sequence<Sizes...>, Types...>&&) -> SmallVector<T, sizeof...(Sizes)>; // Deduction guide for StaticVector conversion. -template <typename T, size_t N> +template <typename T, std::size_t N> SmallVector(StaticVector<T, N>&&) -> SmallVector<T, N>; -template <typename T, size_t N> +template <typename T, std::size_t N> inline void swap(SmallVector<T, N>& lhs, SmallVector<T, N>& rhs) { lhs.swap(rhs); } diff --git a/include/ftl/StaticVector.h b/include/ftl/static_vector.h index c1325568a0..501217558c 100644 --- a/include/ftl/StaticVector.h +++ b/include/ftl/static_vector.h @@ -16,8 +16,8 @@ #pragma once -#include <ftl/ArrayTraits.h> -#include <ftl/InitializerList.h> +#include <ftl/array_traits.h> +#include <ftl/initializer_list.h> #include <algorithm> #include <cassert> @@ -28,9 +28,9 @@ namespace android::ftl { -constexpr struct IteratorRangeTag {} IteratorRange; +constexpr struct IteratorRangeTag {} kIteratorRange; -// Fixed-capacity, statically allocated counterpart of std::vector. Akin to std::array, StaticVector +// Fixed-capacity, statically allocated counterpart of std::vector. Like std::array, StaticVector // allocates contiguous storage for N elements of type T at compile time, but stores at most (rather // than exactly) N elements. Unlike std::array, its default constructor does not require T to have a // default constructor, since elements are constructed in place as the vector grows. Operations that @@ -38,7 +38,8 @@ constexpr struct IteratorRangeTag {} IteratorRange; // adheres to standard containers, except the unstable_erase operation that does not preserve order, // and the replace operation that destructively emplaces. // -// StaticVector<T, 1> is analogous to an iterable std::optional, but StaticVector<T, 0> is an error. +// StaticVector<T, 1> is analogous to an iterable std::optional. +// StaticVector<T, 0> is an error. // // Example usage: // @@ -72,7 +73,7 @@ constexpr struct IteratorRangeTag {} IteratorRange; // assert(strings[1] == "123"); // assert(strings[2] == "???"); // -template <typename T, size_t N> +template <typename T, std::size_t N> class StaticVector final : ArrayTraits<T>, ArrayIterators<StaticVector<T, N>, T>, ArrayComparators<StaticVector> { @@ -88,7 +89,7 @@ class StaticVector final : ArrayTraits<T>, // latter unless they are input iterators and cannot be used to construct elements. If // the former is intended, the caller can pass an IteratorRangeTag to disambiguate. template <typename I, typename Traits = std::iterator_traits<I>> - using IsInputIterator = std::conjunction< + using is_input_iterator = std::conjunction< std::is_base_of<std::input_iterator_tag, typename Traits::iterator_category>, std::negation<std::is_constructible<T, I>>>; @@ -112,33 +113,34 @@ public: // Copies and moves a vector, respectively. StaticVector(const StaticVector& other) - : StaticVector(IteratorRange, other.begin(), other.end()) {} - StaticVector(StaticVector&& other) { swap<Empty>(other); } + : StaticVector(kIteratorRange, other.begin(), other.end()) {} + + StaticVector(StaticVector&& other) { swap<true>(other); } // Copies at most N elements from a smaller convertible vector. - template <typename U, size_t M, typename = std::enable_if_t<M <= N>> + template <typename U, std::size_t M, typename = std::enable_if_t<M <= N>> StaticVector(const StaticVector<U, M>& other) - : StaticVector(IteratorRange, other.begin(), other.end()) {} + : StaticVector(kIteratorRange, other.begin(), other.end()) {} // Copies at most N elements from an array. - template <typename U, size_t M> + template <typename U, std::size_t M> explicit StaticVector(U (&array)[M]) - : StaticVector(IteratorRange, std::begin(array), std::end(array)) {} + : StaticVector(kIteratorRange, std::begin(array), std::end(array)) {} // Copies at most N elements from the range [first, last). // // IteratorRangeTag disambiguates with initialization from two iterator-like elements. // - template <typename Iterator, typename = std::enable_if_t<IsInputIterator<Iterator>{}>> - StaticVector(Iterator first, Iterator last) : StaticVector(IteratorRange, first, last) { + template <typename Iterator, typename = std::enable_if_t<is_input_iterator<Iterator>{}>> + StaticVector(Iterator first, Iterator last) : StaticVector(kIteratorRange, first, last) { using V = typename std::iterator_traits<Iterator>::value_type; static_assert(std::is_constructible_v<value_type, V>, "Incompatible iterator range"); } template <typename Iterator> StaticVector(IteratorRangeTag, Iterator first, Iterator last) - : mSize(std::min(max_size(), static_cast<size_type>(std::distance(first, last)))) { - std::uninitialized_copy(first, first + mSize, begin()); + : size_(std::min(max_size(), static_cast<size_type>(std::distance(first, last)))) { + std::uninitialized_copy(first, first + size_, begin()); } // Constructs at most N elements. The template arguments T and N are inferred using the @@ -174,10 +176,10 @@ public: // assert(vector[1].empty()); // assert(vector[2] == "???"); // - template <typename U, size_t Size, size_t... Sizes, typename... Types> - StaticVector(InitializerList<U, std::index_sequence<Size, Sizes...>, Types...>&& init) + template <typename U, std::size_t Size, std::size_t... Sizes, typename... Types> + StaticVector(InitializerList<U, std::index_sequence<Size, Sizes...>, Types...>&& list) : StaticVector(std::index_sequence<0, 0, Size>{}, std::make_index_sequence<Size>{}, - std::index_sequence<Sizes...>{}, init.tuple) {} + std::index_sequence<Sizes...>{}, list.tuple) {} ~StaticVector() { std::destroy(begin(), end()); } @@ -189,21 +191,22 @@ public: StaticVector& operator=(StaticVector&& other) { std::destroy(begin(), end()); - mSize = 0; - swap<Empty>(other); + size_ = 0; + swap<true>(other); return *this; } - template <typename = void> + // IsEmpty enables a fast path when the vector is known to be empty at compile time. + template <bool IsEmpty = false> void swap(StaticVector&); static constexpr size_type max_size() { return N; } - size_type size() const { return mSize; } + size_type size() const { return size_; } bool empty() const { return size() == 0; } bool full() const { return size() == max_size(); } - iterator begin() { return std::launder(reinterpret_cast<pointer>(mData)); } + iterator begin() { return std::launder(reinterpret_cast<pointer>(data_)); } iterator end() { return begin() + size(); } using Iter::begin; @@ -252,7 +255,7 @@ public: iterator emplace_back(Args&&... args) { if (full()) return end(); const iterator it = construct_at(end(), std::forward<Args>(args)...); - ++mSize; + ++size_; return it; } @@ -291,22 +294,20 @@ public: construct_at(it, std::move(back())); std::destroy_at(last()); } - --mSize; + --size_; } private: - struct Empty {}; - // Recursion for variadic constructor. - template <size_t I, typename E, typename... Es> + template <std::size_t I, typename E, typename... Es> StaticVector(std::index_sequence<I>, E&& element, Es&&... elements) : StaticVector(std::index_sequence<I + 1>{}, std::forward<Es>(elements)...) { construct_at(begin() + I, std::forward<E>(element)); } // Base case for variadic constructor. - template <size_t I> - explicit StaticVector(std::index_sequence<I>) : mSize(I) {} + template <std::size_t I> + explicit StaticVector(std::index_sequence<I>) : size_(I) {} // Recursion for in-place constructor. // @@ -317,29 +318,31 @@ private: // The Sizes sequence lists the argument counts for elements after I, so Size is the ArgCount // for the next element. The recursion stops when Sizes is empty for the last element. // - template <size_t I, size_t ArgIndex, size_t ArgCount, size_t... Indices, size_t Size, - size_t... Sizes, typename... Args> + template <std::size_t I, std::size_t ArgIndex, std::size_t ArgCount, std::size_t... Indices, + std::size_t Size, std::size_t... Sizes, typename... Args> StaticVector(std::index_sequence<I, ArgIndex, ArgCount>, std::index_sequence<Indices...>, std::index_sequence<Size, Sizes...>, std::tuple<Args...>& tuple) : StaticVector(std::index_sequence<I + 1, ArgIndex + ArgCount, Size>{}, - std::make_index_sequence<Size>{}, std::index_sequence<Sizes...>{}, tuple) { + std::make_index_sequence<Size>{}, std::index_sequence<Sizes...>{}, + tuple) { construct_at(begin() + I, std::move(std::get<ArgIndex + Indices>(tuple))...); } // Base case for in-place constructor. - template <size_t I, size_t ArgIndex, size_t ArgCount, size_t... Indices, typename... Args> + template <std::size_t I, std::size_t ArgIndex, std::size_t ArgCount, std::size_t... Indices, + typename... Args> StaticVector(std::index_sequence<I, ArgIndex, ArgCount>, std::index_sequence<Indices...>, std::index_sequence<>, std::tuple<Args...>& tuple) - : mSize(I + 1) { + : size_(I + 1) { construct_at(begin() + I, std::move(std::get<ArgIndex + Indices>(tuple))...); } - size_type mSize = 0; - std::aligned_storage_t<sizeof(value_type), alignof(value_type)> mData[N]; + size_type size_ = 0; + std::aligned_storage_t<sizeof(value_type), alignof(value_type)> data_[N]; }; // Deduction guide for array constructor. -template <typename T, size_t N> +template <typename T, std::size_t N> StaticVector(T (&)[N]) -> StaticVector<std::remove_cv_t<T>, N>; // Deduction guide for variadic constructor. @@ -348,12 +351,12 @@ template <typename T, typename... Us, typename V = std::decay_t<T>, StaticVector(T&&, Us&&...) -> StaticVector<V, 1 + sizeof...(Us)>; // Deduction guide for in-place constructor. -template <typename T, size_t... Sizes, typename... Types> +template <typename T, std::size_t... Sizes, typename... Types> StaticVector(InitializerList<T, std::index_sequence<Sizes...>, Types...>&&) -> StaticVector<T, sizeof...(Sizes)>; -template <typename T, size_t N> -template <typename E> +template <typename T, std::size_t N> +template <bool IsEmpty> void StaticVector<T, N>::swap(StaticVector& other) { auto [to, from] = std::make_pair(this, &other); if (from == this) return; @@ -362,7 +365,7 @@ void StaticVector<T, N>::swap(StaticVector& other) { auto [min, max] = std::make_pair(size(), other.size()); // No elements to swap if moving into an empty vector. - if constexpr (std::is_same_v<E, Empty>) { + if constexpr (IsEmpty) { assert(min == 0); } else { if (min > max) { @@ -382,10 +385,10 @@ void StaticVector<T, N>::swap(StaticVector& other) { std::uninitialized_move(first, last, to->begin() + min); std::destroy(first, last); - std::swap(mSize, other.mSize); + std::swap(size_, other.size_); } -template <typename T, size_t N> +template <typename T, std::size_t N> inline void swap(StaticVector<T, N>& lhs, StaticVector<T, N>& rhs) { lhs.swap(rhs); } diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp index eb8e57a911..883d1388d1 100644 --- a/libs/ftl/Android.bp +++ b/libs/ftl/Android.bp @@ -5,9 +5,9 @@ cc_test { address: true, }, srcs: [ - "SmallMap_test.cpp", - "SmallVector_test.cpp", - "StaticVector_test.cpp", + "small_map_test.cpp", + "small_vector_test.cpp", + "static_vector_test.cpp", ], cflags: [ "-Wall", diff --git a/libs/ftl/README.md b/libs/ftl/README.md new file mode 100644 index 0000000000..bdd750f40a --- /dev/null +++ b/libs/ftl/README.md @@ -0,0 +1,41 @@ +# FTL + +FTL is a template library shared by SurfaceFlinger and InputFlinger, inspired by +and supplementing the C++ Standard Library. The intent is to fill gaps for areas +not (yet) covered—like cache-efficient data structures and lock-free concurrency +primitives—and implement proposals that are missing or experimental in Android's +libc++ branch. The design takes some liberties with standard compliance, notably +assuming that exceptions are disabled. + +## Tests + + atest ftl_test + +## Style + +- Based on [Google C++ Style](https://google.github.io/styleguide/cppguide.html). +- Informed by [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines). + +Naming conventions are as follows: + +- `PascalCase` + - Types and aliases, except standard interfaces. + - Template parameters, including non-type ones. +- `snake_case` + - Variables, and data members with trailing underscore. + - Functions, free and member alike. + - Type traits, with standard `_t` and `_v` suffixes. +- `kCamelCase` + - Enumerators and `constexpr` constants with static storage duration. +- `MACRO_CASE` + - Macros, with `FTL_` prefix unless `#undef`ed. + +Template parameter packs are named with the following convention: + + typename T, typename... Ts + typename Arg, typename... Args + + std::size_t I, std::size_t... Is + std::size_t Size, std::size_t... Sizes + +The `details` namespace contains implementation details. diff --git a/libs/ftl/SmallMap_test.cpp b/libs/ftl/small_map_test.cpp index fa00c06a70..4e7662b112 100644 --- a/libs/ftl/SmallMap_test.cpp +++ b/libs/ftl/small_map_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <ftl/SmallMap.h> +#include <ftl/small_map.h> #include <gtest/gtest.h> #include <cctype> diff --git a/libs/ftl/SmallVector_test.cpp b/libs/ftl/small_vector_test.cpp index d0c28582d8..dbb2d4f9b9 100644 --- a/libs/ftl/SmallVector_test.cpp +++ b/libs/ftl/small_vector_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <ftl/SmallVector.h> +#include <ftl/small_vector.h> #include <gtest/gtest.h> #include <algorithm> @@ -72,8 +72,8 @@ TEST(SmallVector, Construct) { } { // Array constructor. - const float kFloats[] = {.1f, .2f, .3f}; - SmallVector vector(kFloats); + const float floats[] = {.1f, .2f, .3f}; + SmallVector vector(floats); EXPECT_EQ(vector, (SmallVector{.1f, .2f, .3f})); EXPECT_FALSE(vector.dynamic()); @@ -149,8 +149,8 @@ TEST(SmallVector, String) { EXPECT_STREQ(chars.begin(), "abcdefghij"); // Constructor takes iterator range. - const char kString[] = "123456"; - SmallVector<char, 10> string(std::begin(kString), std::end(kString)); + const char numbers[] = "123456"; + SmallVector<char, 10> string(std::begin(numbers), std::end(numbers)); EXPECT_FALSE(string.dynamic()); EXPECT_STREQ(string.begin(), "123456"); @@ -171,7 +171,7 @@ TEST(SmallVector, String) { TEST(SmallVector, CopyableElement) { struct Pair { - // Needed because std::vector emplace does not use uniform initialization. + // Needed because std::vector does not use list initialization to emplace. Pair(int a, int b) : a(a), b(b) {} const int a, b; @@ -325,8 +325,8 @@ TEST(SmallVector, Sort) { // Constructor takes array reference. { - const char* kStrings[] = {"cake", "lie"}; - strings = SmallVector(kStrings); + const char* array[] = {"cake", "lie"}; + strings = SmallVector(array); EXPECT_FALSE(strings.dynamic()); } diff --git a/libs/ftl/StaticVector_test.cpp b/libs/ftl/static_vector_test.cpp index db42d23dfa..3e662820d7 100644 --- a/libs/ftl/StaticVector_test.cpp +++ b/libs/ftl/static_vector_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include <ftl/StaticVector.h> +#include <ftl/static_vector.h> #include <gtest/gtest.h> #include <algorithm> @@ -68,8 +68,8 @@ TEST(StaticVector, Construct) { } { // Array constructor. - const float kFloats[] = {.1f, .2f, .3f}; - StaticVector vector(kFloats); + const float floats[] = {.1f, .2f, .3f}; + StaticVector vector(floats); EXPECT_EQ(vector, (StaticVector{.1f, .2f, .3f})); } { @@ -122,11 +122,11 @@ TEST(StaticVector, Construct) { const char* str; }; - const char* kStrings[] = {"a", "b", "c", "d"}; + const char* strings[] = {"a", "b", "c", "d"}; { // Two iterator-like elements. - StaticVector<String, 3> vector(kStrings, kStrings + 3); + StaticVector<String, 3> vector(strings, strings + 3); ASSERT_EQ(vector.size(), 2u); EXPECT_STREQ(vector[0].str, "a"); @@ -134,7 +134,7 @@ TEST(StaticVector, Construct) { } { // Disambiguating iterator constructor. - StaticVector<String, 3> vector(ftl::IteratorRange, kStrings, kStrings + 3); + StaticVector<String, 3> vector(ftl::kIteratorRange, strings, strings + 3); ASSERT_EQ(vector.size(), 3u); EXPECT_STREQ(vector[0].str, "a"); @@ -153,8 +153,8 @@ TEST(StaticVector, String) { EXPECT_STREQ(chars.begin(), "abcdefghi"); // Constructor takes iterator range. - const char kString[] = "123456"; - StaticVector<char, 10> string(std::begin(kString), std::end(kString)); + const char numbers[] = "123456"; + StaticVector<char, 10> string(std::begin(numbers), std::end(numbers)); EXPECT_STREQ(string.begin(), "123456"); EXPECT_EQ(string.size(), 7u); @@ -290,8 +290,8 @@ TEST(StaticVector, Sort) { // Constructor takes array reference. { - const char* kStrings[] = {"cake", "lie"}; - strings = StaticVector(kStrings); + const char* array[] = {"cake", "lie"}; + strings = StaticVector(array); } EXPECT_GT(sorted, strings); |