Skip to content

Commit 5e92524

Browse files
Merge pull request #19 from dreamer-coding/add_cstring
2 parents 7a79d66 + 6f33026 commit 5e92524

File tree

8 files changed

+1696
-2
lines changed

8 files changed

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

0 commit comments

Comments
 (0)