Halide 22.0.0 Halide compiler and libraries

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
7 namespace Halide {
8 namespace Runtime {
9 namespace Internal {
10
11// Static utility functions for dealing with string data
12 struct StringUtils {
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//
84 class StringStorage {
85 public:
86 explicit StringStorage(void *user_context = nullptr, uint32_t capacity = 0, const SystemMemoryAllocatorFns &sma = default_allocator());
87 StringStorage(const StringStorage &other) = default;
88 ~StringStorage();
89
90 // Factory methods for creation / destruction
91 static StringStorage *create(void *user_context, const SystemMemoryAllocatorFns &ma);
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
97 StringStorage &operator=(const StringStorage &other);
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
117 const SystemMemoryAllocatorFns &current_allocator() const;
118 static const SystemMemoryAllocatorFns &default_allocator();
119
120 private:
121 BlockStorage contents;
122};
123
124 StringStorage::StringStorage(void *user_context, uint32_t capacity, const SystemMemoryAllocatorFns &sma)
125 : contents(user_context, {sizeof(char), 32, 32}, sma) {
126 if (capacity) {
127 contents.reserve(user_context, capacity);
128 }
129}
130
131 StringStorage::~StringStorage() {
132 destroy(nullptr);
133}
134
135 StringStorage *StringStorage::create(void *user_context, const SystemMemoryAllocatorFns &system_allocator) {
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
149 void StringStorage::destroy(void *user_context, StringStorage *instance) {
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
157 StringStorage &StringStorage::operator=(const StringStorage &other) {
158 if (&other != this) {
159 assign(nullptr, other.data(), other.length());
160 }
161 return *this;
162}
163
164 bool 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
172 bool 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
184 bool 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
193 bool StringStorage::operator!=(const StringStorage &other) const {
194 return !(*this == other);
195}
196
197 void 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);
200 terminate(user_context, length);
201}
202
203 void StringStorage::assign(void *user_context, char ch) {
204 reserve(user_context, 1);
205 char *ptr = static_cast<char *>(contents[0]);
206 (*ptr) = ch;
207 terminate(user_context, 1);
208}
209
210 void 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 }
217 reserve(user_context, length);
218 contents.replace(user_context, 0, str, length);
219 terminate(user_context, length);
220}
221
222 void 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
236 void StringStorage::append(void *user_context, char ch) {
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
244 void 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
258 void StringStorage::prepend(void *user_context, char ch) {
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
266 void 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
275 void StringStorage::clear(void *user_context) {
276 contents.clear(user_context);
277 terminate(user_context, 0);
278}
279
280 void StringStorage::initialize(void *user_context, uint32_t capacity, const SystemMemoryAllocatorFns &sma) {
281 contents.initialize(user_context, {sizeof(char), 32, 32}, sma);
282 reserve(user_context, capacity);
283 terminate(user_context, 0);
284}
285
286 void StringStorage::destroy(void *user_context) {
287 contents.destroy(user_context);
288}
289
290 size_t StringStorage::length() const {
291 return StringUtils::count_length(data(), contents.size());
292}
293
294 const char *StringStorage::data() const {
295 return static_cast<const char *>(contents.data());
296}
297
298 const SystemMemoryAllocatorFns &
299 StringStorage::current_allocator() const {
300 return contents.current_allocator();
301}
302
303 const SystemMemoryAllocatorFns &
304 StringStorage::default_allocator() {
305 return BlockStorage::default_allocator();
306}
307
308// --
309
310} // namespace Internal
311} // namespace Runtime
312} // namespace Halide
313
314#endif // HALIDE_RUNTIME_STRING_STORAGE_H
halide_error
void halide_error(void *user_context, const char *)
Halide calls this function on runtime errors (for example bounds checking failures).
block_storage.h
Halide::Runtime::Internal::BlockStorage
Definition: block_storage.h:18
Halide::Runtime::Internal::BlockStorage::destroy
void destroy(void *user_context)
Definition: block_storage.h:116
Halide::Runtime::Internal::BlockStorage::size
size_t size() const
Definition: block_storage.h:336
Halide::Runtime::Internal::BlockStorage::clear
void clear(void *user_context)
Definition: block_storage.h:190
Halide::Runtime::Internal::BlockStorage::resize
void resize(void *user_context, size_t entry_count, bool realloc=true)
Definition: block_storage.h:204
Halide::Runtime::Internal::BlockStorage::replace
void replace(void *user_context, size_t index, const void *array, size_t array_size)
Definition: block_storage.h:278
Halide::Runtime::Internal::BlockStorage::prepend
void prepend(void *user_context, const void *entry_ptr)
Definition: block_storage.h:172
Halide::Runtime::Internal::BlockStorage::data
void * data()
Definition: block_storage.h:354
Halide::Runtime::Internal::BlockStorage::insert
void insert(void *user_context, size_t index, const void *entry_ptr)
Definition: block_storage.h:245
Halide::Runtime::Internal::BlockStorage::initialize
void initialize(void *user_context, const Config &cfg, const SystemMemoryAllocatorFns &sma=default_allocator())
Definition: block_storage.h:125
Halide::Runtime::Internal::BlockStorage::default_allocator
static const SystemMemoryAllocatorFns & default_allocator()
Definition: block_storage.h:429
Halide::Runtime::Internal::BlockStorage::empty
bool empty() const
Definition: block_storage.h:324
Halide::Runtime::Internal::BlockStorage::current_allocator
const SystemMemoryAllocatorFns & current_allocator() const
Definition: block_storage.h:413
Halide::Runtime::Internal::BlockStorage::is_valid
bool is_valid(size_t index) const
Definition: block_storage.h:332
Halide::Runtime::Internal::BlockStorage::reserve
void reserve(void *user_context, size_t capacity, bool free_existing=false)
Definition: block_storage.h:194
Halide::Runtime::Internal::StringStorage
Definition: string_storage.h:84
Halide::Runtime::Internal::StringStorage::current_allocator
const SystemMemoryAllocatorFns & current_allocator() const
Definition: string_storage.h:299
Halide::Runtime::Internal::StringStorage::assign
void assign(void *user_context, char ch)
Definition: string_storage.h:203
Halide::Runtime::Internal::StringStorage::prepend
void prepend(void *user_context, char ch)
Definition: string_storage.h:258
Halide::Runtime::Internal::StringStorage::StringStorage
StringStorage(void *user_context=nullptr, uint32_t capacity=0, const SystemMemoryAllocatorFns &sma=default_allocator())
Definition: string_storage.h:124
Halide::Runtime::Internal::StringStorage::operator=
StringStorage & operator=(const StringStorage &other)
Definition: string_storage.h:157
Halide::Runtime::Internal::StringStorage::default_allocator
static const SystemMemoryAllocatorFns & default_allocator()
Definition: string_storage.h:304
Halide::Runtime::Internal::StringStorage::operator==
bool operator==(const StringStorage &other) const
Definition: string_storage.h:184
Halide::Runtime::Internal::StringStorage::data
const char * data() const
Definition: string_storage.h:294
Halide::Runtime::Internal::StringStorage::reserve
void reserve(void *user_context, size_t length)
Definition: string_storage.h:197
Halide::Runtime::Internal::StringStorage::~StringStorage
~StringStorage()
Definition: string_storage.h:131
Halide::Runtime::Internal::StringStorage::operator!=
bool operator!=(const StringStorage &other) const
Definition: string_storage.h:193
Halide::Runtime::Internal::StringStorage::length
size_t length() const
Definition: string_storage.h:290
Halide::Runtime::Internal::StringStorage::StringStorage
StringStorage(const StringStorage &other)=default
Halide::Runtime::Internal::StringStorage::initialize
void initialize(void *user_context, uint32_t capacity=0, const SystemMemoryAllocatorFns &sma=default_allocator())
Definition: string_storage.h:280
Halide::Runtime::Internal::StringStorage::create
static StringStorage * create(void *user_context, const SystemMemoryAllocatorFns &ma)
Definition: string_storage.h:135
Halide::Runtime::Internal::StringStorage::contains
bool contains(const char *str) const
Definition: string_storage.h:164
Halide::Runtime::Internal::StringStorage::clear
void clear(void *user_context)
Definition: string_storage.h:275
Halide::Runtime::Internal::StringStorage::append
void append(void *user_context, char ch)
Definition: string_storage.h:236
Halide::Runtime::Internal::StringStorage::terminate
void terminate(void *user_context, size_t length)
Definition: string_storage.h:266
Halide::Runtime::Internal::StringStorage::destroy
static void destroy(void *user_context, StringStorage *string_storage)
Definition: string_storage.h:149
Halide::Internal::starts_with
bool starts_with(const std::string &str, const std::string &prefix)
Test if the first string starts with the second string.
Halide::Runtime::Internal::strlen
size_t strlen(const char *string)
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AbstractGenerator.h:19
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
strncmp
int strncmp(const char *s, const char *t, size_t n)
memcpy
void * memcpy(void *s1, const void *s2, size_t n)
size_t
__SIZE_TYPE__ size_t
Definition: runtime_internal.h:31
uint32_t
unsigned __INT32_TYPE__ uint32_t
Definition: runtime_internal.h:25
halide_abort_if_false
#define halide_abort_if_false(user_context, cond)
Definition: runtime_internal.h:271
strstr
const char * strstr(const char *, const char *)
Halide::Runtime::Internal::StringUtils
Definition: string_storage.h:12
Halide::Runtime::Internal::StringUtils::count_tokens
static size_t count_tokens(const char *str, const char *delim)
Definition: string_storage.h:24
Halide::Runtime::Internal::StringUtils::contains
static bool contains(const char *s1, const char *s2, size_t n)
Definition: string_storage.h:44
Halide::Runtime::Internal::StringUtils::count_length
static size_t count_length(const char *str, size_t max_chars)
Definition: string_storage.h:64
Halide::Runtime::Internal::StringUtils::is_empty
static bool is_empty(const char *str)
Definition: string_storage.h:13
Halide::Runtime::Internal::StringUtils::copy_up_to
static size_t copy_up_to(char *dst, const char *src, size_t max_chars)
Definition: string_storage.h:72
Halide::Runtime::Internal::SystemMemoryAllocatorFns
Definition: memory_resources.h:193
Halide::Runtime::Internal::SystemMemoryAllocatorFns::deallocate
DeallocateSystemFn deallocate
Definition: memory_resources.h:195
Halide::Runtime::Internal::SystemMemoryAllocatorFns::allocate
AllocateSystemFn allocate
Definition: memory_resources.h:194
user_context
void * user_context
Definition: vulkan_resources.h:178