[libc-commits] [libc] 06cfb7a - [libc] add a vector internal class

Michael Jones via libc-commits libc-commits at lists.llvm.org
Thu Feb 10 11:04:22 PST 2022


Author: Michael Jones
Date: 2022-02-10T11:04:18-08:00
New Revision: 06cfb7a3456b6e657047c31b4b4c57006d5fc9d1

URL: https://github.com/llvm/llvm-project/commit/06cfb7a3456b6e657047c31b4b4c57006d5fc9d1
DIFF: https://github.com/llvm/llvm-project/commit/06cfb7a3456b6e657047c31b4b4c57006d5fc9d1.diff

LOG: [libc] add a vector internal class

Add a basic implementation of the vector class for use internally to
LLVM-libc.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D118954

Added: 
    libc/src/__support/CPP/vector.h
    libc/test/utils/CPP/vector_test.cpp

Modified: 
    libc/src/__support/CPP/CMakeLists.txt
    libc/test/utils/CPP/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 78f6cf2cd2c3f..b591734a6b6f6 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -1,3 +1,4 @@
+# TODO(michaelrj): separate the standalone_cpp library into individual targets.
 add_header_library(
   standalone_cpp
   HDRS
@@ -10,3 +11,11 @@ add_header_library(
     StringView.h
     TypeTraits.h
 )
+
+add_header_library(
+  vector
+  HDRS
+    vector.h
+  DEPENDS
+    libc.include.stdlib
+)

diff  --git a/libc/src/__support/CPP/vector.h b/libc/src/__support/CPP/vector.h
new file mode 100644
index 0000000000000..e8873d1c14ad2
--- /dev/null
+++ b/libc/src/__support/CPP/vector.h
@@ -0,0 +1,92 @@
+//===-- A self contained equivalent of std::vector --------------*- 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_SRC_SUPPORT_CPP_VECTOR_H
+#define LLVM_LIBC_SRC_SUPPORT_CPP_VECTOR_H
+
+#include <stddef.h> // For size_t.
+
+#include <stdlib.h> // For malloc/realloc/free
+
+namespace __llvm_libc {
+namespace cpp {
+
+// This implementation does not have a templated allocator since that feature
+// isn't relevant for a libc setting.
+
+// Vector is a templated dynamically resizable array. This implementation is
+// only meant for primitives or structs, and will not call destructors on held
+// objects.
+template <class T> class vector {
+  T *data_array;
+  size_t array_size;
+  size_t num_elements = 0;
+  static constexpr size_t DEFAULT_SIZE = 16;
+  static constexpr size_t GROWTH_FACTOR = 2;
+  static constexpr size_t MAX_SIZE = ~size_t(0);
+
+public:
+  constexpr vector<T>() : array_size{DEFAULT_SIZE} {
+    data_array = static_cast<T *>(malloc(DEFAULT_SIZE * sizeof(T)));
+  }
+
+  constexpr vector<T>(const vector<T> &other) = delete;
+  constexpr vector<T>(const vector<T> &&other) = delete;
+
+  ~vector() { free(data_array); }
+
+  constexpr vector &operator=(vector &other) = delete;
+  constexpr vector &operator=(vector &&other) = delete;
+
+  constexpr void reserve(size_t new_size) {
+    if (new_size >= array_size)
+      increase_size(new_size + 1);
+  }
+
+  constexpr void push_back(const T &value) {
+    if (num_elements >= array_size)
+      increase_size(num_elements + 1);
+    data_array[num_elements] = value;
+    ++num_elements;
+  }
+
+  constexpr T &operator[](size_t pos) { return data_array[pos]; }
+  constexpr T *data() { return data_array; }
+  constexpr const T *data() const { return data_array; }
+
+  constexpr bool empty() const { return num_elements == 0; }
+
+  constexpr size_t size() const { return num_elements; }
+  constexpr size_t max_size() const { return MAX_SIZE; }
+
+  constexpr size_t capacity() const { return array_size; }
+
+private:
+  static constexpr size_t MAX_DIV_BY_GROWTH = MAX_SIZE / GROWTH_FACTOR;
+
+  // new_size is treated as the minimum size for the new array. This function
+  // will increase array_size by GROWTH_FACTOR until there is space for new_size
+  // items.
+  constexpr void increase_size(size_t new_size) {
+    size_t temp_size = array_size;
+    if (new_size >= MAX_DIV_BY_GROWTH) {
+      temp_size = new_size;
+    } else {
+      if (temp_size == 0)
+        temp_size = 1;
+      while (temp_size <= new_size)
+        temp_size = temp_size * GROWTH_FACTOR;
+    }
+    array_size = temp_size;
+    data_array = static_cast<T *>(realloc(data_array, array_size * sizeof(T)));
+  }
+};
+} // namespace cpp
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CPP_VECTOR_H

diff  --git a/libc/test/utils/CPP/CMakeLists.txt b/libc/test/utils/CPP/CMakeLists.txt
index a4a0eed0c9c74..7d4f15b7af5c5 100644
--- a/libc/test/utils/CPP/CMakeLists.txt
+++ b/libc/test/utils/CPP/CMakeLists.txt
@@ -39,3 +39,13 @@ add_libc_unittest(
   DEPENDS
     libc.src.__support.CPP.standalone_cpp
 )
+
+add_libc_unittest(
+  vector_test
+  SUITE
+    libc_cpp_utils_unittests
+  SRCS
+    vector_test.cpp
+  DEPENDS
+    libc.src.__support.CPP.vector
+)

diff  --git a/libc/test/utils/CPP/vector_test.cpp b/libc/test/utils/CPP/vector_test.cpp
new file mode 100644
index 0000000000000..a27eafa151bc6
--- /dev/null
+++ b/libc/test/utils/CPP/vector_test.cpp
@@ -0,0 +1,37 @@
+//===-- Unittests for vector ----------------------------------------------===//
+//
+// 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/CPP/vector.h"
+#include "utils/UnitTest/Test.h"
+
+TEST(LlvmLibcVectorTest, SimpleConstructor) {
+  __llvm_libc::cpp::vector<int> vec;
+}
+
+TEST(LlvmLibcVectorTest, OrderedWriteOrderedReadTest) {
+  __llvm_libc::cpp::vector<size_t> vec;
+
+  for (size_t i = 0; i < 100; i = i + 2) {
+    vec.push_back(i);
+  }
+  ASSERT_EQ(vec.size(), size_t(50));
+  ASSERT_GE(vec.capacity(), vec.size());
+  for (size_t j = 0; j < vec.size(); ++j) {
+    ASSERT_EQ(vec[j], j * 2);
+  }
+}
+
+TEST(LlvmLibcVectorTest, ReserveTest) {
+  __llvm_libc::cpp::vector<bool> vec;
+
+  size_t prev_capacity = vec.capacity();
+
+  vec.reserve(prev_capacity * 2);
+
+  ASSERT_GT(vec.capacity(), prev_capacity * 2);
+}


        


More information about the libc-commits mailing list