[libc-commits] [libc] 176c853 - [libc] add internal string class

Michael Jones via libc-commits libc-commits at lists.llvm.org
Thu Jan 19 09:26:31 PST 2023


Author: Michael Jones
Date: 2023-01-19T09:26:22-08:00
New Revision: 176c853d1da5c344194952659eeb74f063e13010

URL: https://github.com/llvm/llvm-project/commit/176c853d1da5c344194952659eeb74f063e13010
DIFF: https://github.com/llvm/llvm-project/commit/176c853d1da5c344194952659eeb74f063e13010.diff

LOG: [libc] add internal string class

The scanf implementation needs a dynamically resizing string class. This
patch adds a minimal version of that class along with tests to check the
current functionality.

Reviewed By: sivachandra

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

Added: 
    libc/src/__support/char_vector.h
    libc/test/src/__support/char_vector_test.cpp

Modified: 
    libc/src/__support/CMakeLists.txt
    libc/test/src/__support/CMakeLists.txt
    libc/test/src/__support/CPP/stringview_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index fc80c5389ddfc..8b702af082fc2 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -145,6 +145,12 @@ add_header_library(
     libc.src.__support.CPP.array
 )
 
+add_header_library(
+  char_vector
+  HDRS
+    char_vector.h
+)
+
 add_header_library(
   number_pair
   HDRS

diff  --git a/libc/src/__support/char_vector.h b/libc/src/__support/char_vector.h
new file mode 100644
index 0000000000000..0a9a2d7e4cf14
--- /dev/null
+++ b/libc/src/__support/char_vector.h
@@ -0,0 +1,76 @@
+//===-- Standalone implementation of a char 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_CHARVECTOR_H
+#define LLVM_LIBC_SRC_SUPPORT_CHARVECTOR_H
+
+#include <stddef.h>
+#include <stdlib.h> // For allocation.
+
+namespace __llvm_libc {
+
+// This is very simple alternate of the std::string class. There is no
+// bounds check performed in any of the methods. The callers are expected to
+// do the checks before invoking the methods.
+//
+// This class will be extended as needed in future.
+
+class CharVector {
+  static constexpr size_t INIT_BUFF_SIZE = 64;
+  char local_buffer[INIT_BUFF_SIZE];
+  char *cur_str = local_buffer;
+  size_t cur_buff_size = INIT_BUFF_SIZE;
+  size_t index = 0;
+
+public:
+  CharVector() = default;
+  ~CharVector() {
+    if (cur_str != local_buffer)
+      free(cur_str);
+  }
+
+  // append returns true on success and false on allocation failure.
+  bool append(char new_char) {
+    // Subtract 1 for index starting at 0 and another for the null terminator.
+    if (index >= cur_buff_size - 2) {
+      // If the new character would cause the string to be longer than the
+      // buffer's size, attempt to allocate a new buffer.
+      cur_buff_size = cur_buff_size * 2;
+      if (cur_str == local_buffer) {
+        char *new_str;
+        new_str = reinterpret_cast<char *>(malloc(cur_buff_size));
+        if (new_str == NULL) {
+          return false;
+        }
+        // TODO: replace with inline memcpy
+        for (size_t i = 0; i < index; ++i)
+          new_str[i] = cur_str[i];
+        cur_str = new_str;
+      } else {
+        cur_str = reinterpret_cast<char *>(realloc(cur_str, cur_buff_size));
+        if (cur_str == NULL) {
+          return false;
+        }
+      }
+    }
+    cur_str[index] = new_char;
+    ++index;
+    return true;
+  }
+
+  char *c_str() {
+    cur_str[index] = '\0';
+    return cur_str;
+  }
+
+  size_t length() { return index; }
+};
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CHARVECTOR_H

diff  --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt
index b835812f6e1b8..fa35aa45712ff 100644
--- a/libc/test/src/__support/CMakeLists.txt
+++ b/libc/test/src/__support/CMakeLists.txt
@@ -84,6 +84,16 @@ add_libc_unittest(
     libc.src.__support.fixedvector
 )
 
+add_libc_unittest(
+  char_vector_test
+  SUITE
+    libc_support_unittests
+  SRCS
+    char_vector_test.cpp
+  DEPENDS
+    libc.src.__support.char_vector
+)
+
 add_executable(
   libc_str_to_float_comparison_test
   str_to_float_comparison_test.cpp

diff  --git a/libc/test/src/__support/CPP/stringview_test.cpp b/libc/test/src/__support/CPP/stringview_test.cpp
index bd6b614218bb4..240b590e69976 100644
--- a/libc/test/src/__support/CPP/stringview_test.cpp
+++ b/libc/test/src/__support/CPP/stringview_test.cpp
@@ -1,5 +1,4 @@
-//===-- Unittests for string_view
-//------------------------------------------===//
+//===-- Unittests for string_view -----------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.

diff  --git a/libc/test/src/__support/char_vector_test.cpp b/libc/test/src/__support/char_vector_test.cpp
new file mode 100644
index 0000000000000..15e269bed1857
--- /dev/null
+++ b/libc/test/src/__support/char_vector_test.cpp
@@ -0,0 +1,78 @@
+//===-- Unittests for char_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/char_vector.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::CharVector;
+
+TEST(LlvmLibcCharVectorTest, InitializeCheck) {
+  CharVector v;
+  ASSERT_EQ(v.length(), size_t(0));
+}
+
+TEST(LlvmLibcCharVectorTest, AppendShort) {
+  CharVector v;
+  ASSERT_EQ(v.length(), size_t(0));
+
+  constexpr char test_str[] = "1234567890";
+  for (size_t i = 0; test_str[i] != '\0'; ++i) {
+    v.append(test_str[i]);
+  }
+  ASSERT_STREQ(v.c_str(), test_str);
+}
+
+TEST(LlvmLibcCharVectorTest, AppendMedium) {
+  CharVector v;
+  ASSERT_EQ(v.length(), size_t(0));
+
+  // 100 characters (each row is 50)
+  constexpr char test_str[] =
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy";
+  for (size_t i = 0; test_str[i] != '\0'; ++i) {
+    ASSERT_EQ(v.length(), i);
+    v.append(test_str[i]);
+  }
+  ASSERT_STREQ(v.c_str(), test_str);
+  ASSERT_EQ(v.length(), size_t(100));
+}
+
+TEST(LlvmLibcCharVectorTest, AppendLong) {
+  CharVector v;
+  ASSERT_EQ(v.length(), size_t(0));
+
+  // 1000 characters
+  constexpr char test_str[] =
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy"
+      "12345678901234567890123456789012345678901234567890"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy";
+  for (size_t i = 0; test_str[i] != '\0'; ++i) {
+    ASSERT_EQ(v.length(), i);
+    v.append(test_str[i]);
+  }
+  ASSERT_STREQ(v.c_str(), test_str);
+  ASSERT_EQ(v.length(), size_t(1000));
+}


        


More information about the libc-commits mailing list