@@ -31,9 +31,28 @@ struct StringUtils {
3131 return count;
3232 }
3333
34- static size_t count_length (const char *str) {
34+ // retuns true if s1 contains s2 (within n characters)
35+ static bool contains (const char *s1, const char *s2, size_t n) {
36+ if (is_empty (s2)) { return true ; } // s2 is empty ... return true to match strstr
37+ char starts_with = *s2;
38+ for (size_t length = strlen (s2); length <= n; n--, s1++) {
39+ if (*s1 == starts_with) {
40+ for (size_t i = 1 ; i <= length; i++) {
41+ if (i == length) {
42+ return true ;
43+ }
44+ if (s1[i] != s2[i]) {
45+ break ;
46+ }
47+ }
48+ }
49+ }
50+ return false ;
51+ }
52+
53+ static size_t count_length (const char *str, size_t max_chars) {
3554 const char *ptr = str;
36- while (!StringUtils::is_empty (ptr)) {
55+ while (!StringUtils::is_empty (ptr) && (( size_t (ptr - str)) < max_chars) ) {
3756 ++ptr;
3857 }
3958 return size_t (ptr - str);
@@ -50,6 +69,10 @@ class StringStorage {
5069 StringStorage (const StringStorage &other) = default ;
5170 ~StringStorage ();
5271
72+ // Factory methods for creation / destruction
73+ static StringStorage *create (void *user_context, const SystemMemoryAllocatorFns &ma);
74+ static void destroy (void *user_context, StringStorage *string_storage);
75+
5376 void initialize (void *user_context, uint32_t capacity = 0 , const SystemMemoryAllocatorFns &sma = default_allocator());
5477 void destroy (void *user_context);
5578
@@ -89,6 +112,28 @@ StringStorage::~StringStorage() {
89112 destroy (nullptr );
90113}
91114
115+ StringStorage *StringStorage::create (void *user_context, const SystemMemoryAllocatorFns &system_allocator) {
116+ halide_abort_if_false (user_context, system_allocator.allocate != nullptr );
117+ StringStorage *result = reinterpret_cast <StringStorage *>(
118+ system_allocator.allocate (user_context, sizeof (StringStorage)));
119+
120+ if (result == nullptr ) {
121+ halide_error (user_context, " StringStorage: Failed to create instance! Out of memory!\n " );
122+ return nullptr ;
123+ }
124+
125+ result->initialize (user_context, 32 , system_allocator);
126+ return result;
127+ }
128+
129+ void StringStorage::destroy (void *user_context, StringStorage *instance) {
130+ halide_abort_if_false (user_context, instance != nullptr );
131+ const SystemMemoryAllocatorFns &system_allocator = instance->current_allocator ();
132+ instance->destroy (user_context);
133+ halide_abort_if_false (user_context, system_allocator.deallocate != nullptr );
134+ system_allocator.deallocate (user_context, instance);
135+ }
136+
92137StringStorage &StringStorage::operator =(const StringStorage &other) {
93138 if (&other != this ) {
94139 assign (nullptr , other.data (), other.length ());
@@ -97,14 +142,17 @@ StringStorage &StringStorage::operator=(const StringStorage &other) {
97142}
98143
99144bool StringStorage::contains (const char *str) const {
145+ if (contents.empty ()) { return false ; }
100146 const char *this_str = static_cast <const char *>(contents.data ());
101- return strstr (this_str, str) != nullptr ;
147+ return StringUtils::contains (this_str, str, contents. size ()) ;
102148}
103149
104150bool StringStorage::contains (const StringStorage &other) const {
151+ if (contents.empty ()) { return false ; }
152+ if (other.contents .empty ()) { return false ; }
105153 const char *this_str = static_cast <const char *>(contents.data ());
106154 const char *other_str = static_cast <const char *>(other.contents .data ());
107- return strstr (this_str, other_str) != nullptr ;
155+ return StringUtils::contains (this_str, other_str, contents. size ()) ;
108156}
109157
110158bool StringStorage::operator ==(const StringStorage &other) const {
@@ -125,72 +173,80 @@ void StringStorage::reserve(void *user_context, size_t length) {
125173}
126174
127175void StringStorage::assign (void *user_context, char ch) {
128- contents. resize (user_context, 1 );
176+ reserve (user_context, 1 );
129177 char *ptr = static_cast <char *>(contents[0 ]);
130178 (*ptr) = ch;
179+ terminate (user_context, 1 );
131180}
132181
133182void StringStorage::assign (void *user_context, const char *str, size_t length) {
134183 if (StringUtils::is_empty (str)) { return ; }
135184 if (length == 0 ) { length = strlen (str); }
136- char *this_str = static_cast <char *>(contents.data ());
137185 reserve (user_context, length);
138- memcpy (this_str , str, length);
186+ contents. replace (user_context, 0 , str, length);
139187 terminate (user_context, length);
140188}
141189
142190void StringStorage::append (void *user_context, const char *str, size_t length) {
143191 if (StringUtils::is_empty (str)) { return ; }
144192 if (length == 0 ) { length = strlen (str); }
145- const size_t old_size = contents.size ();
146- size_t new_length = old_size + length;
147- char *this_str = static_cast <char *>(contents[old_size]);
148- reserve (user_context, length);
149- memcpy (this_str, str, length);
193+ const size_t old_length = StringUtils::count_length (data (), contents.size ());
194+ size_t new_length = old_length + length;
195+ reserve (user_context, new_length);
196+ contents.insert (user_context, old_length, str, length);
150197 terminate (user_context, new_length);
151198}
152199
153200void StringStorage::append (void *user_context, char ch) {
154- contents.append (user_context, &ch);
201+ const size_t old_length = StringUtils::count_length (data (), contents.size ());
202+ size_t new_length = old_length + 1 ;
203+ reserve (user_context, new_length);
204+ contents.insert (user_context, old_length, &ch, 1 );
205+ terminate (user_context, new_length);
155206}
156207
157208void StringStorage::prepend (void *user_context, const char *str, size_t length) {
158209 if (StringUtils::is_empty (str)) { return ; }
159210 if (length == 0 ) { length = strlen (str); }
160- const size_t old_size = contents.size ();
161- size_t new_length = old_size + length;
162- char *this_str = static_cast <char *>(contents.data ());
211+ const size_t old_length = StringUtils::count_length (data (), contents.size ());
212+ size_t new_length = old_length + length;
163213 reserve (user_context, new_length);
164- memcpy (this_str + length, this_str, old_size);
165- memcpy (this_str, str, length);
214+ contents.insert (user_context, 0 , str, length);
166215 terminate (user_context, new_length);
167216}
168217
169218void StringStorage::prepend (void *user_context, char ch) {
219+ const size_t old_length = StringUtils::count_length (data (), contents.size ());
220+ size_t new_length = old_length + 1 ;
221+ reserve (user_context, new_length);
170222 contents.prepend (user_context, &ch);
223+ terminate (user_context, new_length);
171224}
172225
173226void StringStorage::terminate (void *user_context, size_t length) {
174- char *end_ptr = static_cast <char *>(contents[length]);
175- (*end_ptr) = ' \0 ' ;
227+ if (contents.data () && (length < contents.size ())) {
228+ char *end_ptr = static_cast <char *>(contents[length]);
229+ (*end_ptr) = ' \0 ' ;
230+ }
176231}
177232
178233void StringStorage::clear (void *user_context) {
179234 contents.clear (user_context);
180- if (contents. data ()) { terminate (user_context, 0 ); }
235+ terminate (user_context, 0 );
181236}
182237
183238void StringStorage::initialize (void *user_context, uint32_t capacity, const SystemMemoryAllocatorFns &sma) {
184239 contents.initialize (user_context, {sizeof (char ), 32 , 32 }, sma);
185- if (capacity) { contents.reserve (user_context, capacity); }
240+ reserve (user_context, capacity);
241+ terminate (user_context, 0 );
186242}
187243
188244void StringStorage::destroy (void *user_context) {
189245 contents.destroy (user_context);
190246}
191247
192248size_t StringStorage::length () const {
193- return StringUtils::count_length (data ());
249+ return StringUtils::count_length (data (), contents. size () );
194250}
195251
196252const char *StringStorage::data () const {
0 commit comments