CSTR v1.2.0-build
Simple yet powerful string manipulation in C
Loading...
Searching...
No Matches
cstr.h
Go to the documentation of this file.
1// cstr.h
2
3#pragma once
4
5#include "CSTRpredefines.h"
6
7#ifdef __cplusplus
8# define __CSTR_DIRUTILS_CSTR_CPP_OPEN extern "C" {
9# define __CSTR_DIRUTILS_CSTR_CPP_CLOSE }
10#else
11# define __CSTR_DIRUTILS_CSTR_CPP_OPEN
12# define __CSTR_DIRUTILS_CSTR_CPP_CLOSE
13#endif // __cplusplus
14
15__CSTR_DIRUTILS_CSTR_CPP_OPEN
16
17#ifdef __CSTR_OK
18# undef __CSTR_OK
19#endif // defined(__CSTR_OK)
20
21#if __STDC_VERSION__ >= CSTR_DEFAULT_C_STD || defined(__cplusplus)
22
23#ifdef CSTR_sys_strdup
24# undef CSTR_sys_strdup
25#endif
26
27#if defined(CSTR_OS_WIN32)
28# include <string.h>
29# define CSTR_sys_strdup _strdup
30#else
31# ifdef _POSIX_C_SOURCE
32# undef _POSIX_C_SOURCE
33# endif
34# define _POSIX_C_SOURCE 200809L
35# include <string.h>
36# define CSTR_sys_strdup strdup
37#endif // defined(CSTR_OS_WIN32)
38
39#include <stdbool.h>
40#include <stdlib.h>
41
42#define CSTR_NPOS -1
43#define CSTR_SUCCESS 0
44#define CSTR_FAIL 1
45#define CSTR_FORCECAP_LIMIT 2
46
47// NOTE: Dear developer, check all the available macros here
48#ifdef CSTR_RECOMMENDED
49# define CSTR_DYNAMIC_CAPACITY
50# define CSTR_ENABLE_GET_RETURN
51# define CSTR_ENABLE_GET_CONST_RETURN
52#endif // CSTR_RECOMMENDED
53
54// NOTE:
55// Other macros that are not recommended but available for flexibility are:
56// CSTR_DEFINE_INTERNAL : Define the internal files inside of the header file (cstr.h)
57// Check the definitions below the definition of the CSTR struct
58// CSTR_RECOMMENDED : Enable recommended macros, such as CSTR_DYNAMIC_CAPACITY, CSTR_ENABLE_GET_RETURN, ...
59
60/**
61 * @brief Custom dynamic string type
62 *
63 * The fields should typically be managed only through the cstr_* API
64 * Directly modifying them can lead to undefined behavior unless explicitly intended
65 */
66typedef struct
67{
68 /**
69 * @brief Tracks whether this CSTR has been initialized
70 * @note Should only be set by internal or initialization functions
71 */
73
74 /**
75 * @brief Pointer to the character buffer
76 * Always NULL terminated if properly managed through the API
77 */
78 char *data;
79
80 /**
81 * @brief If true, capacity is fixed and operations that exceed
82 * it return an error instead of reallocating the size
83 */
85
86 /**
87 * @brief Current string length (not counting the NULL terminator)
88 */
89 size_t len;
90
91 /**
92 * @brief Total allocated capacity (including NULL terminator)
93 */
94 size_t cap;
95} CSTR;
96
97#ifdef CSTR_DEFINE_INTERNAL
98/**
99 * @brief Update the capacity automatically
100 * IMPORTANT:
101 * This function won't do anything if macro `CSTR_DYNAMIC_CAPACITY` is NOT defined
102 *
103 * @return Return if fail or success
104 * @note Typically used in the other defined functions for CSTR inner API
105 */
107
108/**
109 * @brief Internal helper to format and set the string content.
110 *
111 * Uses a printf-style format string and variadic arguments to
112 * overwrite the content of a CSTR. The function computes the
113 * required buffer size, reallocates if needed (unless forceCap
114 * is active), formats the string, and updates length/capacity.
115 *
116 * @param _str Pointer to the CSTR to modify.
117 * @param _fmt printf-style format string.
118 * @param ... Variadic arguments corresponding to the format.
119 *
120 * @return
121 * - CSTR_SUCCESS on success
122 * - CSTR_FAIL if parameters are invalid, allocation fails,
123 * or vsnprintf reports an error
124 * - CSTR_FORCECAP_LIMIT if forceCap is enabled and the
125 * required size exceeds current capacity
126 *
127 * @note Typically used in the other defined functions for CSTR inner API
128 */
129static int __cstr_setFormat(CSTR *_str, const char *_fmt, ...);
130#endif // defined(CSTR_DEFINE_INTERNAL)
131
132/**
133 * @brief Initialize a new empty CSTR
134 *
135 * @return A new CSTR instance. Check `.initialized` or if CSTR is not NULL to confirm success
136 */
138
139/**
140 * @brief Initialize a CSTR with a copy of an original C-string
141 *
142 * @param _dest Pointer to the destination CSTR
143 * @param _src NULL terminated string to copy from
144 * @return CSTR_SUCCESS on success, otherwise CSTR_FAIL
145 */
146int cstr_initCopy(CSTR *_dest, const char *_src);
147
148/**
149 * @brief Destroy and clean up a CSTR and its allocated objects
150 *
151 * @param _str Pointer to the CSTR to destroy
152 * @return CSTR_SUCCESS on success, otherwise CSTR_FAIL
153 */
155
156/**
157 * @brief Set the content of a CSTR to a new C-string in `.data`
158 *
159 * @param _str Pointer to the CSTR to modify
160 * @param _data Null terminated string to set
161 * @return CSTR_SUCCESS, CSTR_FAIL, or CSTR_FORCECAP_LIMIT
162 */
163int cstr_set(CSTR *_str, const char *_data);
164
165/**
166 * @brief Add content using an array (From Private API)
167 * @param _str Pointer to the CSTR to modify
168 * @param _arr Array to add to the string
169 * @param count The size of the array
170 * @return CSTR_SUCCESS, CSTR_FAIL, or others from the `cstr_add()` function
171 */
172int __cstr_join(CSTR *_str, const char *_arr[], const size_t _count);
173
174/**
175 * @brief Append a suffix to the end of a CSTR
176 *
177 * @param _str Pointer to the CSTR to modify
178 * @param _suffix NULL terminated string to append
179 * @return CSTR_SUCCESS, CSTR_FAIL, or CSTR_FORCECAP_LIMIT
180 */
181int cstr_add(CSTR *_str, const char *_suffix);
182
183/**
184 * @brief Extract a substring in place from a CSTR
185 *
186 * @param _str Pointer to the CSTR to modify
187 * @param _start Starting index of the substring
188 * @param _len Length of the substring
189 * @return CSTR_SUCCESS or CSTR_FAIL
190 */
191int cstr_substr(CSTR *_str, size_t _start, size_t _len);
192
193/**
194 * @brief Clear a CSTR to an empty string without freeing memory
195 *
196 * @param _str Pointer to the CSTR to clear
197 * @return CSTR_SUCCESS or CSTR_FAIL
198 */
199int cstr_clear(CSTR *_str);
200
201/**
202 * @brief Convert all characters in a CSTR to uppercase
203 *
204 * @param _str Pointer to the CSTR to modify
205 * @return CSTR_SUCCESS or CSTR_FAIL
206 */
207int cstr_upper(CSTR *_str);
208
209/**
210 * @brief Convert all characters in a CSTR to lowercase
211 *
212 * @param _str Pointer to the CSTR to modify
213 * @return CSTR_SUCCESS or CSTR_FAIL
214 */
215int cstr_lower(CSTR *_str);
216
217/**
218 * @brief Insert a string at a specific position in a CSTR
219 *
220 * @param _str Pointer to the CSTR to modify
221 * @param _data NULL terminated string to insert
222 * @param _pos Position at which to insert, 0-based
223 * @return CSTR_SUCCESS, CSTR_FAIL, or CSTR_FORCECAP_LIMIT
224 */
225int cstr_insert(CSTR *_str, const char *_data, size_t _pos);
226
227/**
228 * @brief Reverse the content of a CSTR in place
229 *
230 * @param _str Pointer to the CSTR to modify
231 * @return CSTR_SUCCESS or CSTR_FAIL
232 */
234
235/**
236 * @brief Clear the content of a CSTR and optionally shrink capacity
237 *
238 * @param _str Pointer to the CSTR to shrink
239 * @param _len New length (characters to keep)
240 * @return CSTR_SUCCESS or CSTR_FAIL
241 */
242int cstr_shrink(CSTR *_str, const size_t _len);
243
244/**
245 * @brief Create a numeric string from an integer
246 */
247int cstr_fromInt(CSTR *_str, int _val);
248
249/**
250 * @brief Create a numeric string from a long
251 */
252int cstr_fromLong(CSTR *_str, long _val);
253
254/**
255 * @brief Create a numeric string from a float
256 */
257int cstr_fromFloat(CSTR *_str, float _val);
258
259/**
260 * @brief Create a numeric string from a double
261 */
262int cstr_fromDouble(CSTR *_str, double _val);
263
264/**
265 * @brief Create a hexadecimal string from an unsigned integer
266 */
267int cstr_fromHex(CSTR *_str, unsigned int _val);
268
269/**
270 * @brief Replace only the first occurrence of a substring
271 *
272 * @param _str Pointer to the CSTR
273 * @param _old Substring to locate
274 * @param _new Replacement string
275 * @return CSTR_SUCCESS or an error code (CSTR_FAIL, ...)
276 */
277int cstr_replace(CSTR *_str, const char *_old, const char *_new);
278
279/**
280 * @brief Replace all occurrences of a substring
281 *
282 * @param _str Pointer to the CSTR
283 * @param _old Substring to locate
284 * @param _new Replacement string
285 * @return CSTR_SUCCESS or CSTR_FAIL
286 */
287int cstr_replaceAll(CSTR *_str, const char *_old, const char *_new);
288
289/**
290 * @brief Erase a portion of the string
291 *
292 * @param _str Pointer to the CSTR
293 * @param _pos Starting position
294 * @param _len Number of characters to remove
295 * @return CSTR_SUCCESS or CSTR_FAIL
296 */
297int cstr_erase(CSTR *_str, int _pos, size_t _len);
298
299/**
300 * @brief Find the first occurrence of a substring
301 *
302 * @param _str Pointer to the CSTR to search
303 * @param _find Substring to locate
304 * @return Index of first match, or CSTR_NPOS if not found
305 */
306size_t cstr_find(const CSTR *_str, const char *_find);
307
308/**
309 * @brief Find a substring starting from a specific index
310 *
311 * @param _str Pointer to the CSTR to search
312 * @param _find Substring to locate
313 * @param pos Starting index
314 * @return Index of match, or CSTR_NPOS if not found
315 */
316size_t cstr_findFrom(const CSTR *_str, const char *_find, size_t pos);
317
318/**
319 * @brief Count occurrences of a single character within a CSTR
320 *
321 * Iterates through the string and counts how many times the specified
322 * character appears in the `.data` buffer.
323 *
324 * @param _str Pointer to the CSTR to inspect
325 * @param ch Character to count
326 *
327 * @return Number of occurrences of `ch` in the string
328 * Returns 0 if `_str` is NULL or not initialized
329 *
330 * @note This function performs a linear scan across all characters.
331 */
332size_t cstr_countChar(const CSTR *_str, const char ch);
333
334/**
335 * @brief Count occurrences of a substring within a CSTR
336 *
337 * Searches for non-overlapping occurrences of a null-terminated substring
338 * inside the CSTR’s `.data` buffer using strstr. Each found instance advances
339 * the scan position by the length of the substring, preventing overlapping matches.
340 *
341 * @param _str Pointer to the CSTR to inspect
342 * @param ch Null-terminated substring to count
343 *
344 * @return Number of non-overlapping occurrences found
345 * Returns 0 if parameters are invalid (`_str`, `.data`, `ch`, or `*ch`)
346 */
347size_t cstr_count(const CSTR *_str, const char *ch);
348
349/**
350 * @brief Check if a CSTR begins with the given prefix
351 *
352 * @param _str The CSTR to check by value
353 * @param _prefix The prefix string
354 * @return true if it starts with prefix, else return false
355 */
356bool cstr_startsWith(CSTR _str, const char *_prefix);
357
358/**
359 * @brief Check if a CSTR ends with the given suffix
360 *
361 * @param _str The CSTR to check (by value)
362 * @param _suffix The suffix string
363 * @return true if it ends with suffix, false otherwise
364 */
365bool cstr_endsWith(const CSTR _str, const char *_suffix);
366
367/**
368 * @brief Compare two CSTR instances for equality
369 *
370 * @param _s1 First CSTR (by value)
371 * @param _s2 Second CSTR (by value)
372 * @return true if equal, false otherwise
373 */
374bool cstr_comp(const CSTR _s1, const CSTR _s2);
375
376/**
377 * @brief Return "true" or "false" based on a boolean value
378 *
379 * @param _bool Boolean value
380 * @return "true" if _bool is true, otherwise "false".
381 */
382const char *cstr_bool(const bool _bool);
383
384/**
385 * @brief Get if the string is empty
386 * Return true if:
387 * `.len` smaller or equal to 0
388 * `.data` is empty ("")
389 * `.initialized` is false
390 * `_str` is NULL
391 * If none of the requirements are met, means that it's not empty, hence, return false
392 *
393 * @return Is the string empty? Yes (true), No (false)
394 */
395bool cstr_empty(const CSTR *_str);
396
397/**
398 * @brief `__cstr_join()` function wrapper
399 * USAGE: cstr_join(&str, "param1", "param2")
400 * @param _str CSTR to modify
401 * @param ... Extra params to add
402 * @return Same return as `__cstr_join()` function
403 */
404#define cstr_join(_str, ...) \
405 ({ \
406 const char *__arr[] = { __VA_ARGS__ }; \
407 const size_t __count = sizeof(__arr) / sizeof(__arr[0]); \
408 __cstr_join(_str, __arr, __count); \
409 })
410
411#define __CSTR_OK
412
413#ifdef __CSTR_OK
414# ifdef CSTR_ENABLE_GET_RETURN
415# define CSTR_GET_RETURN(_cstr, _call, ...) ((_call(&_cstr, __VA_ARGS__)), _cstr)
416# else
417# define CSTR_GET_RETURN(_cstr, _call, ...)
418# endif // defined(CSTR_ENABLE_GET_RETURN)
419
420# ifdef CSTR_CONST_RETURN_USE_PTR_METHOD
421# define CSTR_CONST_RETURN_PTR_METHOD ->
422# else
423# define CSTR_CONST_RETURN_PTR_METHOD .
424# endif
425
426# ifdef CSTR_ENABLE_GET_CONST_RETURN
427static inline void CSTR_GET_CONST_RETURN_warning(void) __attribute__((deprecated("CSTR_GET_CONST_RETURN is no longer maintained; memory leaks can't be removed")));
428static inline void CSTR_GET_CONST_RETURN_warning(void) { }
429# define CSTR_GET_CONST_RETURN(_str, _call, ...) \
430 ({ \
431 CSTR_GET_CONST_RETURN_warning(); \
432 CSTR tmpS; \
433 cstr_initCopy(&tmpS, _str CSTR_CONST_RETURN_PTR_METHOD data); \
434 _call(&tmpS, __VA_ARGS__); \
435 tmpS; \
436 })
437# else
438# define CSTR_GET_CONST_RETURN(_str, _call, ...)
439# endif // defined(CSTR_ENABLE_GET_CONST_RETURN)
440#endif // __CSTR_OK
441
442__CSTR_DIRUTILS_CSTR_CPP_CLOSE
443
444#else
445# error "Must use C11 as the minimum standard"
446#endif // __STDC_VERSION__
447
int cstr_insert(CSTR *_str, const char *_data, size_t _pos)
Insert a string at a specific position in a CSTR.
int cstr_reverse(CSTR *_str)
Reverse the content of a CSTR in place.
bool cstr_comp(const CSTR _s1, const CSTR _s2)
Compare two CSTR instances for equality.
int cstr_lower(CSTR *_str)
Convert all characters in a CSTR to lowercase.
int cstr_replaceAll(CSTR *_str, const char *_old, const char *_new)
Replace all occurrences of a substring.
int __cstr_join(CSTR *_str, const char *_arr[], const size_t _count)
Add content using an array (From Private API).
int cstr_fromFloat(CSTR *_str, float _val)
Create a numeric string from a float.
int cstr_fromHex(CSTR *_str, unsigned int _val)
Create a hexadecimal string from an unsigned integer.
int cstr_shrink(CSTR *_str, const size_t _len)
Clear the content of a CSTR and optionally shrink capacity.
int cstr_destroy(CSTR *_str)
Destroy and clean up a CSTR and its allocated objects.
int cstr_substr(CSTR *_str, size_t _start, size_t _len)
Extract a substring in place from a CSTR.
int cstr_fromInt(CSTR *_str, int _val)
Create a numeric string from an integer.
int cstr_set(CSTR *_str, const char *_data)
Set the content of a CSTR to a new C-string in .data.
bool cstr_startsWith(CSTR _str, const char *_prefix)
Check if a CSTR begins with the given prefix.
int cstr_fromDouble(CSTR *_str, double _val)
Create a numeric string from a double.
static void CSTR_GET_CONST_RETURN_warning(void) __attribute__((deprecated("CSTR_GET_CONST_RETURN is no longer maintained
Definition cstr.h:428
int cstr_erase(CSTR *_str, int _pos, size_t _len)
Erase a portion of the string.
int cstr_add(CSTR *_str, const char *_suffix)
Append a suffix to the end of a CSTR.
int cstr_initCopy(CSTR *_dest, const char *_src)
Initialize a CSTR with a copy of an original C-string.
int cstr_upper(CSTR *_str)
Convert all characters in a CSTR to uppercase.
static int __cstr_setFormat(CSTR *_str, const char *_fmt,...)
Internal helper to format and set the string content.
int __cstr_updateCap(CSTR *_str)
Update the capacity automatically IMPORTANT: This function won't do anything if macro CSTR_DYNAMIC_CA...
bool cstr_empty(const CSTR *_str)
Get if the string is empty Return true if: .len smaller or equal to 0 .data is empty ("") ....
int cstr_fromLong(CSTR *_str, long _val)
Create a numeric string from a long.
size_t cstr_find(const CSTR *_str, const char *_find)
Find the first occurrence of a substring.
CSTR cstr_init(void)
Initialize a new empty CSTR.
const char * cstr_bool(const bool _bool)
Return "true" or "false" based on a boolean value.
size_t cstr_countChar(const CSTR *_str, const char ch)
Count occurrences of a single character within a CSTR.
int cstr_replace(CSTR *_str, const char *_old, const char *_new)
Replace only the first occurrence of a substring.
size_t cstr_count(const CSTR *_str, const char *ch)
Count occurrences of a substring within a CSTR.
size_t cstr_findFrom(const CSTR *_str, const char *_find, size_t pos)
Find a substring starting from a specific index.
int cstr_clear(CSTR *_str)
Clear a CSTR to an empty string without freeing memory.
bool cstr_endsWith(const CSTR _str, const char *_suffix)
Check if a CSTR ends with the given suffix.
Custom dynamic string type.
Definition cstr.h:67
bool initialized
Tracks whether this CSTR has been initialized.
Definition cstr.h:72
size_t len
Current string length (not counting the NULL terminator).
Definition cstr.h:89
size_t cap
Total allocated capacity (including NULL terminator).
Definition cstr.h:94
char * data
Pointer to the character buffer Always NULL terminated if properly managed through the API.
Definition cstr.h:78
bool forceCap
If true, capacity is fixed and operations that exceed it return an error instead of reallocating the ...
Definition cstr.h:84