kiba-engine
string.c
Go to the documentation of this file.
1 
6 #include <kiba/core/string.h>
7 
8 #include <kiba/core/log.h>
9 #include <kiba/core/memory.h>
10 
11 #include <string.h>
12 
13 string string_from_raw(const char *raw) { return string_from_raw_n(raw, strlen(raw)); }
14 
15 KB_API string string_copy_raw(const char *raw, allocator *alloc) {
16  string base = string_from_raw(raw);
17  string res = {0};
18  res.data = allocator_allocate(alloc, base.length);
19  if (res.data != KB_NULL) {
20  memory_copy(res.data, base.data, base.length * sizeof(char));
21  res.length = base.length;
22  res.alloc = alloc;
23  }
24  return res;
25 }
26 
27 string string_from_raw_n(const char *raw, usize n) {
28  return (string){
29  .data = (char *) raw,
30  .length = n,
31  .alloc = KB_NULL,
32  };
33 }
34 
35 string string_join_views(const array_of(string_view) views, const char sep, allocator *alloc) {
36  KB_ASSERT(views != KB_NULL, "input views must be a valid array pointer");
37  KB_ASSERT(alloc != KB_NULL, "allocator to use must be a valid pointer");
38  usize length = array_size(views) - 1;
39  array_for_each(const string_view, view, views) { length += view->length; }
40  char *new_data = allocator_allocate(alloc, sizeof(char) * length);
41 
42  usize i = 0;
43  if (new_data != KB_NULL) {
44  array_for_each(const string_view, view, views) {
45  if (view->is_valid && memory_copy(new_data + i, string_view_data(*view), sizeof(char) * view->length)) {
46  i += view->length;
47  if (i < length) {
48  new_data[i++] = sep;
49  }
50  }
51  }
52  }
53 
54  return (string){
55  .data = new_data,
56  .length = i == length ? length : 0,
57  .alloc = alloc,
58  };
59 }
60 
61 string string_from_view(const string_view src, allocator *alloc) {
62  KB_ASSERT(alloc != KB_NULL, "allocator to use must be a valid pointer");
63  char *new_data = KB_NULL;
64  if (src.is_valid && src.length > 0) {
65  new_data = allocator_allocate(alloc, sizeof(char) * src.length);
66  if (new_data != KB_NULL) {
67  memory_copy(new_data, string_view_data(src), src.length);
68  }
69  }
70  return (string){
71  .data = new_data,
72  .length = new_data != KB_NULL ? src.length : 0,
73  .alloc = alloc,
74  };
75 }
76 
77 string string_from_views(const array_of(string_view) views, allocator *alloc) {
78  KB_ASSERT(views != KB_NULL, "input views must be a valid array pointer");
79  KB_ASSERT(alloc != KB_NULL, "allocator to use must be a valid pointer");
80  usize length = 0;
81  array_for_each(const string_view, view, views) { length += view->length; }
82  char *new_data = allocator_allocate(alloc, sizeof(char) * length);
83 
84  usize i = 0;
85  if (new_data != KB_NULL) {
86  array_for_each(const string_view, view, views) {
87  if (view->is_valid
88  && memory_copy(new_data + i, string_view_data(*view), sizeof(char) * view->length) != KB_NULL) {
89  i += view->length;
90  }
91  }
92  }
93 
94  return (string){
95  .data = new_data,
96  .length = i == length ? length : 0,
97  .alloc = alloc,
98  };
99 }
100 
101 void string_destroy(string *str) {
102  if (string_is_valid(*str) && str->alloc != KB_NULL) {
103  allocator_free(str->alloc, str->data);
104  }
105  str->data = KB_NULL;
106  str->length = 0;
107 }
108 
109 b8 string_is_valid(const string str) { return string_view_from_string(str).is_valid; }
110 
111 usize string_index_of(const string str, const char c) { return string_view_index_of(string_view_from_string(str), c); }
112 
113 string string_clone(const string str, allocator *alloc) {
114  KB_ASSERT(alloc != KB_NULL, "allocator to use must be a valid pointer");
115  return string_from_view(string_view_from_string(str), alloc);
116 }
117 
118 b8 string_equal(const string lhs, const string rhs) {
120 }
121 
122 b8 string_n_equal(const string lhs, const string rhs, usize n) {
124 }
125 
127  return (string_view){
128  .str = str,
129  .length = str.length,
130  .offset = 0,
131  .is_valid = str.data != KB_NULL && str.length != 0,
132  };
133 }
134 
135 const char *string_view_data(const string_view view) { return view.is_valid ? view.str.data + view.offset : KB_NULL; }
136 
137 b8 string_view_equal(const string_view lhs, const string_view rhs) {
138  if (!lhs.is_valid || !rhs.is_valid || lhs.length != rhs.length) {
139  return false;
140  }
141  for (usize i = 0; i < lhs.length; ++i) {
142  if (lhs.str.data[lhs.offset + i] != rhs.str.data[rhs.offset + i]) {
143  return false;
144  }
145  }
146  return true;
147 }
148 
149 b8 string_view_n_equal(const string_view lhs, const string_view rhs, usize n) {
150  // lhs and rhs must have at least length n
151  if (KB_MIN(n, KB_MIN(lhs.length, rhs.length)) != n) {
152  return false;
153  }
154  if (!lhs.is_valid || !rhs.is_valid) {
155  return false;
156  }
157  for (usize i = 0; i < n; ++i) {
158  if (lhs.str.data[lhs.offset + i] != rhs.str.data[rhs.offset + i]) {
159  return false;
160  }
161  }
162  return true;
163 }
164 
166  return (string_view){
167  .str = src.str,
168  .length = src.length - offset,
169  .offset = src.offset + offset,
170  .is_valid = src.is_valid && offset < src.length,
171  };
172 }
173 
174 string_view string_view_subview(const string_view view, usize start, usize length) {
175  return (string_view){
176  .str = view.str,
177  .offset = view.offset + start,
178  .length = length,
179  .is_valid = view.is_valid && view.length > start && view.length >= start + length,
180  };
181 }
182 
183 char string_view_char_at(const string_view view, usize index) {
184  if (view.is_valid && index < view.length) {
185  return view.str.data[view.offset + index];
186  }
187  return -1;
188 }
189 
190 usize string_view_index_of(const string_view view, const char c) {
191  if (view.is_valid) {
192  for (usize i = 0; i < view.length; ++i) {
193  if (view.str.data[view.offset + i] == c) {
194  return i;
195  }
196  }
197  }
198  return USIZE_MAX;
199 }
200 
202  usize index = string_view_index_of(view, c);
203  return (string_view){
204  .str = view.str,
205  .length = view.length - index - 1,
206  .offset = view.offset + index + 1,
207  .is_valid = view.is_valid && index != USIZE_MAX,
208  };
209 }
210 
212  usize index = string_view_index_of(view, c);
213  return (string_view){
214  .str = view.str,
215  .length = index,
216  .offset = view.offset,
217  .is_valid = view.is_valid && index != USIZE_MAX,
218  };
219 }
220 
222  usize new_offset = src.offset;
223  usize new_length = src.length;
224  if (src.is_valid) {
225  while (new_offset < src.offset + src.length && character_is_whitespace(src.str.data[new_offset])) {
226  ++new_offset;
227  --new_length;
228  }
229  while (new_length > 0 && character_is_whitespace(src.str.data[new_offset + new_length - 1])) {
230  --new_length;
231  }
232  }
233  return (string_view){
234  .str = src.str,
235  .length = new_length,
236  .offset = new_offset,
237  .is_valid = src.is_valid,
238  };
239 }
240 
241 b8 string_view_split(const string_view view, const char sep, array_of(string_view) * arr) {
242  KB_ASSERT(arr, "provided array must be valid");
243  usize end = string_view_index_of(view, sep);
244  string_view window_view = view;
245  while (end != USIZE_MAX) {
246  string_view cur_view = string_view_subview(window_view, 0, end);
247  if (!cur_view.is_valid || !array_push_checked(arr, &cur_view)) {
248  return false;
249  }
250  window_view = string_view_at_offset(window_view, end + 1);
251  end = string_view_index_of(window_view, sep);
252  }
253  // pick up remainder if string does not end in separator
254  if (window_view.is_valid && window_view.offset < view.length) {
255  string_view remaining_view = string_view_subview(window_view, 0, view.length - window_view.offset);
256  if (!remaining_view.is_valid || !array_push_checked(arr, &remaining_view)) {
257  return false;
258  }
259  }
260  return true;
261 }
void * allocator_allocate(allocator *alloc, usize size)
Allocate unaligned memory.
Definition: allocator.c:92
void allocator_free(allocator *alloc, void *mem)
Give back memory to the allocator.
Definition: allocator.c:134
void * memory_copy(void *dst, const void *src, usize size)
Copy memory.
Definition: memory.c:83
Lightweight layer between platform and other engine components to enable tracing/monitoring.
string_view string_view_after_next_char(const string_view view, const char c)
Create a new string_view of an existing string_view after a certain character.
Definition: string.c:201
b8 string_view_split(const string_view view, const char sep, array_of(string_view) *arr)
Split a single string_view into multiple based on a separator.
Definition: string.c:241
string_view string_view_at_offset(const string_view src, usize offset)
Create a new string_view of an existing string_view.
Definition: string.c:165
b8 string_view_equal(const string_view lhs, const string_view rhs)
Check if the contents of two string views are equal.
Definition: string.c:137
void string_destroy(string *str)
Free data of the string.
Definition: string.c:101
usize string_view_index_of(const string_view view, const char c)
Get the first index of a letter in a string_view.
Definition: string.c:190
string string_from_raw_n(const char *raw, usize n)
Construct a string from n chars of raw character data.
Definition: string.c:27
b8 string_is_valid(const string str)
Check if string is valid.
Definition: string.c:109
string_view string_view_trim(const string_view src)
Create a new string_view which does not start or end in whitespace.
Definition: string.c:221
usize string_index_of(const string str, const char c)
Get the first index of a letter in a string.
Definition: string.c:111
string string_from_view(const string_view src, allocator *alloc)
Creates a new string from a string view.
Definition: string.c:61
const char * string_view_data(const string_view view)
Get raw pointer to beginning of the string_view data.
Definition: string.c:135
char string_view_char_at(const string_view view, usize index)
Get the letter at an specific index in a string_view.
Definition: string.c:183
string_view string_view_subview(const string_view view, usize start, usize length)
Create a new string_view of an existing string_view.
Definition: string.c:174
string_view string_view_from_string(const string str)
Create a new string view of a whole string.
Definition: string.c:126
b8 string_equal(const string lhs, const string rhs)
Check if the contents of two strings are equal.
Definition: string.c:118
string string_clone(const string str, allocator *alloc)
Clone a complete string.
Definition: string.c:113
string string_from_views(const array_of(string_view) views, allocator *alloc)
Creates a new single string based on all provided views.
Definition: string.c:77
b8 string_view_n_equal(const string_view lhs, const string_view rhs, usize n)
Check if the contents of two string views are equal.
Definition: string.c:149
b8 string_n_equal(const string lhs, const string rhs, usize n)
Check if the contents of two strings are equal.
Definition: string.c:122
string_view string_view_until_next_char(const string_view view, const char c)
Create a new string_view of an existing string_view until a certain character.
Definition: string.c:211
string string_join_views(const array_of(string_view) views, const char sep, allocator *alloc)
Creates a new single string based on all provided views separated by a separator.
Definition: string.c:35
string string_from_raw(const char *raw)
Construct a string from a raw string.
Definition: string.c:13
Custom library for interactions with strings using string views.
#define KB_MIN(x, y)
Ternary to get the minimum of two numbers.
Definition: defines.h:35
#define KB_NULL
Value of an invalid ptr (nullptr).
Definition: defines.h:18
Logging system.
#define KB_ASSERT(expr,...)
Perform runtime assertion and log failures.
Definition: log.h:133
Central allocator structure.
Definition: allocator.h:87
Non owning views on actual strings.
Definition: string.h:31
string str
The string the view is defined on.
Definition: string.h:33
b8 is_valid
Indicates if the view is valid and can be used/accessed.
Definition: string.h:39
usize length
The length of the view.
Definition: string.h:35
usize offset
The offset into the string.
Definition: string.h:37
allocator * alloc
The allocator used for construction. KB_NULL if constructed from a raw literal.
Definition: string.h:23
char * data
The character sequence of the string.
Definition: string.h:19
usize length
The length of the string.
Definition: string.h:21