Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
string_storage.h
Go to the documentation of this file.
1#ifndef HALIDE_RUNTIME_STRING_STORAGE_H
2#define HALIDE_RUNTIME_STRING_STORAGE_H
3
4#include "../HalideRuntime.h"
5#include "block_storage.h"
6
7namespace Halide {
8namespace Runtime {
9namespace Internal {
10
11// Static utility functions for dealing with string data
13 static bool is_empty(const char *str) {
14 if (str == nullptr) {
15 return true;
16 }
17 if (str[0] == '\0') {
18 return true;
19 }
20 return false;
21 }
22
23 // count the number of delimited string tokens
24 static size_t count_tokens(const char *str, const char *delim) {
25 if (StringUtils::is_empty(str)) {
26 return 0;
27 }
28 if (StringUtils::is_empty(delim)) {
29 return 1;
30 } // no delim ... string is one token
31
32 size_t count = 0;
33 const char *ptr = str;
34 size_t delim_length = strlen(delim);
35 while (!StringUtils::is_empty(ptr)) {
36 const char *next_delim = strstr(ptr, delim);
37 ptr = (next_delim != nullptr) ? (next_delim + delim_length) : nullptr;
38 ++count;
39 }
40 return count;
41 }
42
43 // retuns true if s1 contains s2 (within n characters)
44 static bool contains(const char *s1, const char *s2, size_t n) {
45 if (is_empty(s2)) {
46 return true;
47 } // s2 is empty ... return true to match strstr
48 char starts_with = *s2;
49 for (size_t length = strlen(s2); length <= n; n--, s1++) {
50 if (*s1 == starts_with) {
51 for (size_t i = 1; i <= length; i++) {
52 if (i == length) {
53 return true;
54 }
55 if (s1[i] != s2[i]) {
56 break;
57 }
58 }
59 }
60 }
61 return false;
62 }
63
64 static size_t count_length(const char *str, size_t max_chars) {
65 const char *ptr = str;
66 while (!StringUtils::is_empty(ptr) && ((size_t(ptr - str)) < max_chars)) {
67 ++ptr;
68 }
69 return size_t(ptr - str);
70 }
71
72 static size_t copy_up_to(char *dst, const char *src, size_t max_chars) {
73 size_t length = count_length(src, max_chars);
74 memcpy(dst, src, length);
75 dst[length] = '\0';
76 return length;
77 }
78};
79
80// --
81// Storage class for handling c-string data (based on block storage)
82// -- Intended for building and maintaining string data w/8-bit chars
83//
85public:
86 explicit StringStorage(void *user_context = nullptr, uint32_t capacity = 0, const SystemMemoryAllocatorFns &sma = default_allocator());
87 StringStorage(const StringStorage &other) = default;
89
90 // Factory methods for creation / destruction
92 static void destroy(void *user_context, StringStorage *string_storage);
93
94 void initialize(void *user_context, uint32_t capacity = 0, const SystemMemoryAllocatorFns &sma = default_allocator());
95 void destroy(void *user_context);
96
98 bool operator==(const StringStorage &other) const;
99 bool operator!=(const StringStorage &other) const;
100
101 bool contains(const char *str) const;
102 bool contains(const StringStorage &other) const;
103
104 void reserve(void *user_context, size_t length);
105 void assign(void *user_context, char ch);
106 void assign(void *user_context, const char *str, size_t length = 0); // if length is zero, strlen is used
107 void append(void *user_context, char ch);
108 void append(void *user_context, const char *str, size_t length = 0); // if length is zero, strlen is used
109 void prepend(void *user_context, char ch);
110 void prepend(void *user_context, const char *str, size_t length = 0); // if length is zero, strlen is used
111 void clear(void *user_context);
112 void terminate(void *user_context, size_t length);
113
114 size_t length() const;
115 const char *data() const;
116
119
120private:
121 BlockStorage contents;
122};
123
125 : contents(user_context, {sizeof(char), 32, 32}, sma) {
126 if (capacity) {
127 contents.reserve(user_context, capacity);
128 }
129}
130
134
136 halide_abort_if_false(user_context, system_allocator.allocate != nullptr);
137 StringStorage *result = reinterpret_cast<StringStorage *>(
138 system_allocator.allocate(user_context, sizeof(StringStorage)));
139
140 if (result == nullptr) {
141 halide_error(user_context, "StringStorage: Failed to create instance! Out of memory!\n");
142 return nullptr;
143 }
144
145 result->initialize(user_context, 32, system_allocator);
146 return result;
147}
148
150 halide_abort_if_false(user_context, instance != nullptr);
151 SystemMemoryAllocatorFns system_allocator = instance->current_allocator();
152 instance->destroy(user_context);
153 halide_abort_if_false(user_context, system_allocator.deallocate != nullptr);
154 system_allocator.deallocate(user_context, instance);
155}
156
158 if (&other != this) {
159 assign(nullptr, other.data(), other.length());
160 }
161 return *this;
162}
163
164bool StringStorage::contains(const char *str) const {
165 if (contents.empty()) {
166 return false;
167 }
168 const char *this_str = static_cast<const char *>(contents.data());
169 return StringUtils::contains(this_str, str, contents.size());
170}
171
172bool StringStorage::contains(const StringStorage &other) const {
173 if (contents.empty()) {
174 return false;
175 }
176 if (other.contents.empty()) {
177 return false;
178 }
179 const char *this_str = static_cast<const char *>(contents.data());
180 const char *other_str = static_cast<const char *>(other.contents.data());
181 return StringUtils::contains(this_str, other_str, contents.size());
182}
183
184bool StringStorage::operator==(const StringStorage &other) const {
185 if (contents.size() != other.contents.size()) {
186 return false;
187 }
188 const char *this_str = static_cast<const char *>(contents.data());
189 const char *other_str = static_cast<const char *>(other.contents.data());
190 return strncmp(this_str, other_str, contents.size()) == 0;
191}
192
193bool StringStorage::operator!=(const StringStorage &other) const {
194 return !(*this == other);
195}
196
197void StringStorage::reserve(void *user_context, size_t length) {
198 contents.reserve(user_context, length + 1); // leave room for termination
199 contents.resize(user_context, length, false);
201}
202
205 char *ptr = static_cast<char *>(contents[0]);
206 (*ptr) = ch;
208}
209
210void StringStorage::assign(void *user_context, const char *str, size_t length) {
211 if (StringUtils::is_empty(str)) {
212 return;
213 }
214 if (length == 0) {
215 length = strlen(str);
216 }
218 contents.replace(user_context, 0, str, length);
220}
221
222void StringStorage::append(void *user_context, const char *str, size_t length) {
223 if (StringUtils::is_empty(str)) {
224 return;
225 }
226 if (length == 0) {
227 length = strlen(str);
228 }
229 const size_t old_length = StringUtils::count_length(data(), contents.size());
230 size_t new_length = old_length + length;
231 reserve(user_context, new_length);
232 contents.insert(user_context, old_length, str, length);
233 terminate(user_context, new_length);
234}
235
237 const size_t old_length = StringUtils::count_length(data(), contents.size());
238 size_t new_length = old_length + 1;
239 reserve(user_context, new_length);
240 contents.insert(user_context, old_length, &ch, 1);
241 terminate(user_context, new_length);
242}
243
244void StringStorage::prepend(void *user_context, const char *str, size_t length) {
245 if (StringUtils::is_empty(str)) {
246 return;
247 }
248 if (length == 0) {
249 length = strlen(str);
250 }
251 const size_t old_length = StringUtils::count_length(data(), contents.size());
252 size_t new_length = old_length + length;
253 reserve(user_context, new_length);
254 contents.insert(user_context, 0, str, length);
255 terminate(user_context, new_length);
256}
257
259 const size_t old_length = StringUtils::count_length(data(), contents.size());
260 size_t new_length = old_length + 1;
261 reserve(user_context, new_length);
262 contents.prepend(user_context, &ch);
263 terminate(user_context, new_length);
264}
265
266void StringStorage::terminate(void *user_context, size_t length) {
267 if (contents.is_valid(length)) {
268 char *end_ptr = static_cast<char *>(contents[length]);
269 (*end_ptr) = '\0';
270 } else {
271 halide_error(user_context, "StringStorage: Failed to terminate string! Out of bounds!\n");
272 }
273}
274
279
281 contents.initialize(user_context, {sizeof(char), 32, 32}, sma);
282 reserve(user_context, capacity);
284}
285
287 contents.destroy(user_context);
288}
289
290size_t StringStorage::length() const {
291 return StringUtils::count_length(data(), contents.size());
292}
293
294const char *StringStorage::data() const {
295 return static_cast<const char *>(contents.data());
296}
297
300 return contents.current_allocator();
301}
302
307
308// --
309
310} // namespace Internal
311} // namespace Runtime
312} // namespace Halide
313
314#endif // HALIDE_RUNTIME_STRING_STORAGE_H
This file declares the routines used by Halide internally in its runtime.
void halide_error(void *user_context, const char *)
Halide calls this function on runtime errors (for example bounds checking failures).
void resize(void *user_context, size_t entry_count, bool realloc=true)
void replace(void *user_context, size_t index, const void *array, size_t array_size)
void prepend(void *user_context, const void *entry_ptr)
void insert(void *user_context, size_t index, const void *entry_ptr)
void initialize(void *user_context, const Config &cfg, const SystemMemoryAllocatorFns &sma=default_allocator())
static const SystemMemoryAllocatorFns & default_allocator()
const SystemMemoryAllocatorFns & current_allocator() const
void reserve(void *user_context, size_t capacity, bool free_existing=false)
const SystemMemoryAllocatorFns & current_allocator() const
void assign(void *user_context, char ch)
void prepend(void *user_context, char ch)
StringStorage(void *user_context=nullptr, uint32_t capacity=0, const SystemMemoryAllocatorFns &sma=default_allocator())
StringStorage & operator=(const StringStorage &other)
static const SystemMemoryAllocatorFns & default_allocator()
bool operator==(const StringStorage &other) const
void reserve(void *user_context, size_t length)
bool operator!=(const StringStorage &other) const
StringStorage(const StringStorage &other)=default
void initialize(void *user_context, uint32_t capacity=0, const SystemMemoryAllocatorFns &sma=default_allocator())
static StringStorage * create(void *user_context, const SystemMemoryAllocatorFns &ma)
bool contains(const char *str) const
void append(void *user_context, char ch)
void terminate(void *user_context, size_t length)
static void destroy(void *user_context, StringStorage *string_storage)
size_t strlen(const char *string)
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
int strncmp(const char *s, const char *t, size_t n)
void * memcpy(void *s1, const void *s2, size_t n)
__SIZE_TYPE__ size_t
unsigned __INT32_TYPE__ uint32_t
#define halide_abort_if_false(user_context, cond)
const char * strstr(const char *, const char *)
static size_t count_tokens(const char *str, const char *delim)
static bool contains(const char *s1, const char *s2, size_t n)
static size_t count_length(const char *str, size_t max_chars)
static bool is_empty(const char *str)
static size_t copy_up_to(char *dst, const char *src, size_t max_chars)
void * user_context