[libc] Add a utility data structure named FixedVector.

This data structure uses a backing cpp::array object and supports a
vector like push_back API. In comparison with a traditional vector
data structure, it is of a fixed capacity and cannot be resized.

Differential Revision: https://reviews.llvm.org/D131377
This commit is contained in:
Siva Chandra Reddy 2022-08-06 00:19:51 +00:00
parent cab6cd6834
commit daa44a2309
4 changed files with 125 additions and 0 deletions

View File

@ -70,6 +70,14 @@ add_header_library(
arg_list.h
)
add_header_library(
fixedvector
HDRS
fixedvector.h
DEPENDS
libc.src.__support.CPP.array
)
add_subdirectory(FPUtil)
add_subdirectory(OSUtil)

View File

@ -0,0 +1,62 @@
//===-- A data structure for a fixed capacity data store --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SUPPORT_FIXEDVECTOR_H
#define LLVM_LIBC_SUPPORT_FIXEDVECTOR_H
#include "src/__support/CPP/array.h"
namespace __llvm_libc {
// A fixed size data store backed by an underlying cpp::array data structure. It
// supports vector like API but is not resizable like a vector.
template <typename T, size_t CAPACITY> class FixedVector {
cpp::array<T, CAPACITY> store;
size_t item_count = 0;
public:
constexpr FixedVector() = default;
bool push_back(const T &obj) {
if (item_count == CAPACITY)
return false;
store[item_count] = obj;
++item_count;
return true;
}
const T &back() const { return store[item_count - 1]; }
T &back() { return store[item_count - 1]; }
bool pop_back() {
if (item_count == 0)
return false;
--item_count;
return true;
}
bool empty() const { return item_count == 0; }
// Empties the store for all practical purposes.
void reset() { item_count = 0; }
// This static method does not free up the resources held by |store|,
// say by calling `free` or something similar. It just does the equivalent
// of the `reset` method. Considering that FixedVector is of fixed storage,
// a `destroy` method like this should not be required. However, FixedVector
// is used in a few places as an alternate for data structures which use
// dynamically allocated storate. So, the `destroy` method like this
// matches the `destroy` API of those other data structures so that users
// can easily swap one data structure for the other.
static void destroy(FixedVector<T, CAPACITY> *store) { store->reset(); }
};
} // namespace __llvm_libc
#endif // LLVM_LIBC_SUPPORT_FIXEDVECTOR_H

View File

@ -63,6 +63,16 @@ add_libc_unittest(
libc.src.__support.CPP.uint
)
add_libc_unittest(
fixedvector_test
SUITE
libc_support_unittests
SRCS
fixedvector_test.cpp
DEPENDS
libc.src.__support.fixedvector
)
add_executable(
libc_str_to_float_comparison_test
str_to_float_comparison_test.cpp

View File

@ -0,0 +1,45 @@
//===-- Unittests for FixedVector -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "src/__support/fixedvector.h"
#include "utils/UnitTest/Test.h"
TEST(LlvmLibcFixedVectorTest, PushAndPop) {
__llvm_libc::FixedVector<int, 20> fixed_vector;
ASSERT_TRUE(fixed_vector.empty());
for (int i = 0; i < 20; i++)
ASSERT_TRUE(fixed_vector.push_back(i));
ASSERT_FALSE(fixed_vector.empty());
ASSERT_FALSE(fixed_vector.push_back(123));
for (int i = 20; i > 0; --i) {
ASSERT_EQ(fixed_vector.back(), i - 1);
ASSERT_TRUE(fixed_vector.pop_back());
}
ASSERT_FALSE(fixed_vector.pop_back());
ASSERT_TRUE(fixed_vector.empty());
}
TEST(LlvmLibcFixedVectorTest, Reset) {
__llvm_libc::FixedVector<int, 20> fixed_vector;
ASSERT_TRUE(fixed_vector.empty());
for (int i = 0; i < 20; i++)
ASSERT_TRUE(fixed_vector.push_back(i));
ASSERT_FALSE(fixed_vector.empty());
fixed_vector.reset();
ASSERT_TRUE(fixed_vector.empty());
}
TEST(LlvmLibcFixedVectorTest, Destroy) {
__llvm_libc::FixedVector<int, 20> fixed_vector;
ASSERT_TRUE(fixed_vector.empty());
for (int i = 0; i < 20; i++)
ASSERT_TRUE(fixed_vector.push_back(i));
ASSERT_FALSE(fixed_vector.empty());
__llvm_libc::FixedVector<int, 20>::destroy(&fixed_vector);
ASSERT_TRUE(fixed_vector.empty());
}