Skip to content

Commit 73501ba

Browse files
add strings
1 parent 96f4e72 commit 73501ba

File tree

5 files changed

+947
-1
lines changed

5 files changed

+947
-1
lines changed

code/logic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ set(TEST_CODE
1717
stream.c
1818
keyboard.c
1919
network.c
20+
cstring.c
2021
)
2122

2223
# Create the library target

code/logic/cstring.c

Lines changed: 387 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,387 @@
1+
/*
2+
* -----------------------------------------------------------------------------
3+
* Project: Fossil Logic
4+
*
5+
* This file is part of the Fossil Logic project, which aims to develop high-
6+
* performance, cross-platform applications and libraries. The code contained
7+
* herein is subject to the terms and conditions defined in the project license.
8+
*
9+
* Author: Michael Gene Brockus (Dreamer)
10+
*
11+
* Copyright (C) 2024 Fossil Logic. All rights reserved.
12+
* -----------------------------------------------------------------------------
13+
*/
14+
#include "fossil/io/string.h"
15+
16+
// ============================================================================
17+
// C String Functions
18+
// ============================================================================
19+
20+
cstring fossil_io_cstring_create(const char *init) {
21+
if (!init) return NULL;
22+
size_t length = strlen(init);
23+
cstring str = (cstring)malloc(length + 1);
24+
if (str) {
25+
strcpy(str, init);
26+
}
27+
return str;
28+
}
29+
30+
void fossil_io_cstring_free(cstring str) {
31+
if (str) {
32+
free(str);
33+
}
34+
}
35+
36+
cstring fossil_io_cstring_copy(ccstring str) {
37+
if (!str) return NULL;
38+
return fossil_io_cstring_create(str);
39+
}
40+
41+
cstring fossil_io_cstring_dup(ccstring str) {
42+
if (!str) return NULL;
43+
size_t length = strlen(str);
44+
cstring new_str = (cstring)malloc(length + 1);
45+
if (new_str) {
46+
strcpy(new_str, str);
47+
}
48+
return new_str;
49+
}
50+
51+
cstring fossil_io_cstring_concat(ccstring s1, ccstring s2) {
52+
if (!s1 || !s2) return NULL;
53+
size_t length1 = strlen(s1);
54+
size_t length2 = strlen(s2);
55+
cstring str = (cstring)malloc(length1 + length2 + 1);
56+
if (str) {
57+
strcpy(str, s1);
58+
strcpy(str + length1, s2);
59+
}
60+
return str;
61+
}
62+
63+
size_t fossil_io_cstring_length(ccstring str) {
64+
if (!str) return 0;
65+
return strlen(str);
66+
}
67+
68+
int fossil_io_cstring_compare(ccstring s1, ccstring s2) {
69+
if (!s1 || !s2) return -1;
70+
return strcmp(s1, s2);
71+
}
72+
73+
void fossil_io_cstring_trim(cstring str) {
74+
if (!str) return;
75+
size_t length = strlen(str);
76+
size_t start = 0;
77+
size_t end = length - 1;
78+
while (start < length && isspace(str[start])) {
79+
start++;
80+
}
81+
while (end > start && isspace(str[end])) {
82+
end--;
83+
}
84+
size_t count = end - start + 1;
85+
if (start > 0) {
86+
memmove(str, str + start, count);
87+
}
88+
str[count] = '\0';
89+
}
90+
91+
cstring *fossil_io_cstring_split(ccstring str, char delimiter, size_t *count) {
92+
if (!str || !count) return NULL;
93+
size_t length = strlen(str);
94+
size_t num_delimiters = 0;
95+
for (size_t i = 0; i < length; i++) {
96+
if (str[i] == delimiter) {
97+
num_delimiters++;
98+
}
99+
}
100+
*count = num_delimiters + 1;
101+
cstring *result = (cstring*)malloc(*count * sizeof(cstring));
102+
if (result) {
103+
size_t start = 0;
104+
size_t index = 0;
105+
for (size_t i = 0; i < length; i++) {
106+
if (str[i] == delimiter) {
107+
size_t count = i - start;
108+
result[index] = (cstring)malloc(count + 1);
109+
if (result[index]) {
110+
memcpy(result[index], str + start, count);
111+
result[index][count] = '\0';
112+
start = i + 1;
113+
index++;
114+
} else {
115+
// Free previously allocated memory on error
116+
for (size_t j = 0; j < index; j++) {
117+
free(result[j]);
118+
}
119+
free(result);
120+
return NULL;
121+
}
122+
}
123+
}
124+
size_t count = length - start;
125+
result[index] = (cstring)malloc(count + 1);
126+
if (result[index]) {
127+
memcpy(result[index], str + start, count);
128+
result[index][count] = '\0';
129+
} else {
130+
// Free previously allocated memory on error
131+
for (size_t j = 0; j < index; j++) {
132+
free(result[j]);
133+
}
134+
free(result);
135+
return NULL;
136+
}
137+
}
138+
return result;
139+
}
140+
141+
cstring fossil_io_cstring_replace(ccstring str, ccstring old, ccstring new_str) {
142+
if (!str || !old || !new_str) return NULL;
143+
size_t old_length = strlen(old);
144+
size_t new_length = strlen(new_str);
145+
size_t count = 0;
146+
size_t index = 0;
147+
size_t length = strlen(str);
148+
while (index < length) {
149+
if (strstr(str + index, old) == str + index) {
150+
count++;
151+
index += old_length;
152+
} else {
153+
index++;
154+
}
155+
}
156+
cstring result = (cstring)malloc(length + count * (new_length - old_length) + 1);
157+
if (result) {
158+
index = 0;
159+
size_t start = 0;
160+
while (index < length) {
161+
if (strstr(str + index, old) == str + index) {
162+
strcpy(result + start, new_str);
163+
start += new_length;
164+
index += old_length;
165+
} else {
166+
result[start] = str[index];
167+
start++;
168+
index++;
169+
}
170+
}
171+
result[start] = '\0';
172+
}
173+
return result;
174+
}
175+
176+
cstring fossil_io_cstring_to_upper(cstring str) {
177+
if (!str) return NULL;
178+
size_t length = strlen(str);
179+
cstring result = (cstring)malloc(length + 1);
180+
if (result) {
181+
for (size_t i = 0; i < length; i++) {
182+
result[i] = toupper(str[i]);
183+
}
184+
result[length] = '\0';
185+
}
186+
return result;
187+
}
188+
189+
cstring fossil_io_cstring_to_lower(cstring str) {
190+
if (!str) return NULL;
191+
size_t length = strlen(str);
192+
cstring result = (cstring)malloc(length + 1);
193+
if (result) {
194+
for (size_t i = 0; i < length; i++) {
195+
result[i] = tolower(str[i]);
196+
}
197+
result[length] = '\0';
198+
}
199+
return result;
200+
}
201+
202+
int fossil_io_cstring_starts_with(ccstring str, ccstring prefix) {
203+
if (!str || !prefix) return 0;
204+
size_t str_length = strlen(str);
205+
size_t prefix_length = strlen(prefix);
206+
if (prefix_length > str_length) {
207+
return 0;
208+
}
209+
return strncmp(str, prefix, prefix_length) == 0;
210+
}
211+
212+
int fossil_io_cstring_ends_with(ccstring str, ccstring suffix) {
213+
if (!str || !suffix) return 0;
214+
size_t str_length = strlen(str);
215+
size_t suffix_length = strlen(suffix);
216+
if (suffix_length > str_length) {
217+
return 0;
218+
}
219+
return strncmp(str + str_length - suffix_length, suffix, suffix_length) == 0;
220+
}
221+
222+
cstring fossil_io_cstring_substring(ccstring str, size_t start, size_t length) {
223+
if (!str) return NULL;
224+
size_t str_length = strlen(str);
225+
if (start >= str_length) {
226+
return NULL;
227+
}
228+
cstring result = (cstring)malloc(length + 1);
229+
if (result) {
230+
size_t count = str_length - start;
231+
if (length < count) {
232+
count = length;
233+
}
234+
memcpy(result, str + start, count);
235+
result[count] = '\0';
236+
}
237+
return result;
238+
}
239+
240+
cstring fossil_io_cstring_reverse(cstring str) {
241+
if (!str) return NULL;
242+
size_t length = strlen(str);
243+
cstring result = (cstring)malloc(length + 1);
244+
if (result) {
245+
for (size_t i = 0; i < length; i++) {
246+
result[i] = str[length - i - 1];
247+
}
248+
result[length] = '\0';
249+
}
250+
return result;
251+
}
252+
253+
int fossil_io_cstring_contains(ccstring str, ccstring substr) {
254+
if (!str || !substr) return 0;
255+
return strstr(str, substr) != NULL;
256+
}
257+
258+
cstring fossil_io_cstring_repeat(ccstring str, size_t count) {
259+
if (!str || count == 0) return NULL;
260+
size_t length = strlen(str);
261+
size_t new_length = length * count;
262+
cstring result = (cstring)malloc(new_length + 1);
263+
if (result) {
264+
for (size_t i = 0; i < count; i++) {
265+
memcpy(result + i * length, str, length);
266+
}
267+
result[new_length] = '\0';
268+
}
269+
return result;
270+
}
271+
272+
cstring fossil_io_cstring_strip(ccstring str, char ch) {
273+
if (!str) return NULL;
274+
size_t length = strlen(str);
275+
size_t start = 0;
276+
size_t end = length - 1;
277+
while (start < length && str[start] == ch) {
278+
start++;
279+
}
280+
while (end > start && str[end] == ch) {
281+
end--;
282+
}
283+
size_t count = end - start + 1;
284+
cstring result = (cstring)malloc(count + 1);
285+
if (result) {
286+
memcpy(result, str + start, count);
287+
result[count] = '\0';
288+
}
289+
return result;
290+
}
291+
292+
size_t fossil_io_cstring_count(ccstring str, ccstring substr) {
293+
if (!str || !substr) return 0;
294+
size_t count = 0;
295+
size_t length = strlen(substr);
296+
while ((str = strstr(str, substr)) != NULL) {
297+
count++;
298+
str += length;
299+
}
300+
return count;
301+
}
302+
303+
cstring fossil_io_cstring_pad_left(ccstring str, size_t total_length, char pad_char) {
304+
if (!str || total_length == 0) return NULL;
305+
size_t length = strlen(str);
306+
if (length >= total_length) {
307+
return fossil_io_cstring_copy(str);
308+
}
309+
size_t pad_length = total_length - length;
310+
cstring result = (cstring)malloc(total_length + 1);
311+
if (result) {
312+
memset(result, pad_char, pad_length);
313+
strcpy(result + pad_length, str);
314+
result[total_length] = '\0';
315+
}
316+
return result;
317+
}
318+
319+
cstring fossil_io_cstring_pad_right(ccstring str, size_t total_length, char pad_char) {
320+
if (!str || total_length == 0) return NULL;
321+
size_t length = strlen(str);
322+
if (length >= total_length) {
323+
return fossil_io_cstring_copy(str);
324+
}
325+
size_t pad_length = total_length - length;
326+
cstring result = (cstring)malloc(total_length + 1);
327+
if (result) {
328+
strcpy(result, str);
329+
memset(result + length, pad_char, pad_length);
330+
result[total_length] = '\0';
331+
}
332+
return result;
333+
}
334+
335+
// ============================================================================
336+
// String Stream Functions
337+
// ============================================================================
338+
339+
fossil_io_cstring_stream* fossil_io_cstring_stream_create(size_t initial_size) {
340+
if (initial_size == 0) return NULL;
341+
fossil_io_cstring_stream *stream = (fossil_io_cstring_stream*)malloc(sizeof(fossil_io_cstring_stream));
342+
if (stream) {
343+
stream->buffer = (char*)malloc(initial_size);
344+
if (stream->buffer) {
345+
stream->length = 0;
346+
stream->capacity = initial_size;
347+
} else {
348+
free(stream);
349+
stream = NULL;
350+
}
351+
}
352+
return stream;
353+
}
354+
355+
void fossil_io_cstring_stream_free(fossil_io_cstring_stream *stream) {
356+
if (stream) {
357+
free(stream->buffer);
358+
free(stream);
359+
}
360+
}
361+
362+
void fossil_io_cstring_stream_write(fossil_io_cstring_stream *stream, ccstring str) {
363+
if (!stream || !str) return;
364+
size_t length = strlen(str);
365+
size_t new_length = stream->length + length;
366+
if (new_length > stream->capacity) {
367+
size_t new_capacity = stream->capacity * 2;
368+
if (new_capacity < new_length) {
369+
new_capacity = new_length;
370+
}
371+
char *new_buffer = (char*)realloc(stream->buffer, new_capacity);
372+
if (new_buffer) {
373+
stream->buffer = new_buffer;
374+
stream->capacity = new_capacity;
375+
} else {
376+
return;
377+
}
378+
}
379+
memcpy(stream->buffer + stream->length, str, length);
380+
stream->length = new_length;
381+
stream->buffer[stream->length] = '\0';
382+
}
383+
384+
ccstring fossil_io_cstring_stream_read(fossil_io_cstring_stream *stream) {
385+
if (!stream) return NULL;
386+
return stream->buffer;
387+
}

0 commit comments

Comments
 (0)