Halide
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 //
85 public:
86  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
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 
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 
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  const 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 
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 
300  return contents.current_allocator();
301 }
302 
306 }
307 
308 // --
309 
310 } // namespace Internal
311 } // namespace Runtime
312 } // namespace Halide
313 
314 #endif // HALIDE_RUNTIME_STRING_STORAGE_H
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::StringStorage
Definition: string_storage.h:84
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::BlockStorage::default_allocator
static const SystemMemoryAllocatorFns & default_allocator()
Definition: block_storage.h:429
Halide::Runtime::Internal::StringStorage::operator==
bool operator==(const StringStorage &other) const
Definition: string_storage.h:184
Halide::Runtime::Internal::StringStorage::prepend
void prepend(void *user_context, char ch)
Definition: string_storage.h:258
Halide::Runtime::Internal::BlockStorage::data
void * data()
Definition: block_storage.h:354
Halide::Runtime::Internal::StringStorage::terminate
void terminate(void *user_context, size_t length)
Definition: string_storage.h:266
Halide::Runtime::Internal::BlockStorage::clear
void clear(void *user_context)
Definition: block_storage.h:190
Halide::Runtime::Internal::BlockStorage
Definition: block_storage.h:18
Halide::Runtime::Internal::BlockStorage::prepend
void prepend(void *user_context, const void *entry_ptr)
Definition: block_storage.h:172
Halide::Runtime::Internal::StringStorage::operator!=
bool operator!=(const StringStorage &other) const
Definition: string_storage.h:193
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::BlockStorage::empty
bool empty() const
Definition: block_storage.h:324
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::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::SystemMemoryAllocatorFns::allocate
AllocateSystemFn allocate
Definition: memory_resources.h:194
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AbstractGenerator.h:19
Halide::Runtime::Internal::BlockStorage::current_allocator
const SystemMemoryAllocatorFns & current_allocator() const
Definition: block_storage.h:413
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::StringStorage::default_allocator
static const SystemMemoryAllocatorFns & default_allocator()
Definition: string_storage.h:304
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
Halide::Runtime::Internal::StringStorage::~StringStorage
~StringStorage()
Definition: string_storage.h:131
Halide::Runtime::Internal::StringStorage::clear
void clear(void *user_context)
Definition: string_storage.h:275
Halide::Runtime::Internal::StringStorage::create
static StringStorage * create(void *user_context, const SystemMemoryAllocatorFns &ma)
Definition: string_storage.h:135
size_t
__SIZE_TYPE__ size_t
Definition: runtime_internal.h:31
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::SystemMemoryAllocatorFns::deallocate
DeallocateSystemFn deallocate
Definition: memory_resources.h:195
Halide::Runtime::Internal::StringStorage::append
void append(void *user_context, char ch)
Definition: string_storage.h:236
Halide::Runtime::Internal::StringUtils
Definition: string_storage.h:12
Halide::Runtime::Internal::BlockStorage::reserve
void reserve(void *user_context, size_t capacity, bool free_existing=false)
Definition: block_storage.h:194
strncmp
int strncmp(const char *s, const char *t, size_t n)
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::BlockStorage::destroy
void destroy(void *user_context)
Definition: block_storage.h:116
Halide::Runtime::Internal::StringUtils::is_empty
static bool is_empty(const char *str)
Definition: string_storage.h:13
Halide::Runtime::Internal::strlen
size_t strlen(const char *string)
Halide::Runtime::Internal::StringStorage::destroy
static void destroy(void *user_context, StringStorage *string_storage)
Definition: string_storage.h:149
Halide::Runtime::Internal::StringStorage::data
const char * data() const
Definition: string_storage.h:294
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::StringStorage::current_allocator
const SystemMemoryAllocatorFns & current_allocator() const
Definition: string_storage.h:299
memcpy
void * memcpy(void *s1, const void *s2, size_t n)
Halide::Runtime::Internal::SystemMemoryAllocatorFns
Definition: memory_resources.h:193
strstr
const char * strstr(const char *, const char *)
Halide::Runtime::Internal::StringStorage::operator=
StringStorage & operator=(const StringStorage &other)
Definition: string_storage.h:157
halide_abort_if_false
#define halide_abort_if_false(user_context, cond)
Definition: runtime_internal.h:262
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::StringStorage::assign
void assign(void *user_context, char ch)
Definition: string_storage.h:203
Halide::Runtime::Internal::StringUtils::contains
static bool contains(const char *s1, const char *s2, size_t n)
Definition: string_storage.h:44
uint32_t
unsigned __INT32_TYPE__ uint32_t
Definition: runtime_internal.h:25
Halide::Runtime::Internal::BlockStorage::is_valid
bool is_valid(size_t index) const
Definition: block_storage.h:332
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::StringStorage::contains
bool contains(const char *str) const
Definition: string_storage.h:164
Halide::Runtime::Internal::BlockStorage::size
size_t size() const
Definition: block_storage.h:336
Halide::Runtime::Internal::StringStorage::reserve
void reserve(void *user_context, size_t length)
Definition: string_storage.h:197
Halide::Runtime::Internal::StringStorage::length
size_t length() const
Definition: string_storage.h:290