1 | //===-- Standalone implementation of a char vector --------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_LIBC_SRC___SUPPORT_CHARVECTOR_H |
10 | #define LLVM_LIBC_SRC___SUPPORT_CHARVECTOR_H |
11 | |
12 | #include "src/__support/common.h" // LIBC_INLINE |
13 | |
14 | #include <stddef.h> // size_t |
15 | #include <stdlib.h> // malloc, realloc, free |
16 | |
17 | namespace LIBC_NAMESPACE { |
18 | |
19 | // This is very simple alternate of the std::string class. There is no |
20 | // bounds check performed in any of the methods. The callers are expected to |
21 | // do the checks before invoking the methods. |
22 | // |
23 | // This class will be extended as needed in future. |
24 | |
25 | class CharVector { |
26 | static constexpr size_t INIT_BUFF_SIZE = 64; |
27 | char local_buffer[INIT_BUFF_SIZE]; |
28 | char *cur_str = local_buffer; |
29 | size_t cur_buff_size = INIT_BUFF_SIZE; |
30 | size_t index = 0; |
31 | |
32 | public: |
33 | CharVector() = default; |
34 | LIBC_INLINE ~CharVector() { |
35 | if (cur_str != local_buffer) |
36 | free(ptr: cur_str); |
37 | } |
38 | |
39 | // append returns true on success and false on allocation failure. |
40 | LIBC_INLINE bool append(char new_char) { |
41 | // Subtract 1 for index starting at 0 and another for the null terminator. |
42 | if (index >= cur_buff_size - 2) { |
43 | // If the new character would cause the string to be longer than the |
44 | // buffer's size, attempt to allocate a new buffer. |
45 | cur_buff_size = cur_buff_size * 2; |
46 | if (cur_str == local_buffer) { |
47 | char *new_str; |
48 | new_str = reinterpret_cast<char *>(malloc(size: cur_buff_size)); |
49 | if (new_str == nullptr) { |
50 | return false; |
51 | } |
52 | // TODO: replace with inline memcpy |
53 | for (size_t i = 0; i < index; ++i) |
54 | new_str[i] = cur_str[i]; |
55 | cur_str = new_str; |
56 | } else { |
57 | cur_str = reinterpret_cast<char *>(realloc(ptr: cur_str, size: cur_buff_size)); |
58 | if (cur_str == nullptr) { |
59 | return false; |
60 | } |
61 | } |
62 | } |
63 | cur_str[index] = new_char; |
64 | ++index; |
65 | return true; |
66 | } |
67 | |
68 | LIBC_INLINE char *c_str() { |
69 | cur_str[index] = '\0'; |
70 | return cur_str; |
71 | } |
72 | |
73 | LIBC_INLINE size_t length() { return index; } |
74 | }; |
75 | |
76 | } // namespace LIBC_NAMESPACE |
77 | |
78 | #endif // LLVM_LIBC_SRC___SUPPORT_CHARVECTOR_H |
79 | |