doc: (str) add str documentation

This commit is contained in:
thetek 2023-02-14 16:26:34 +01:00
parent df4d6036fc
commit b39ba90bc9
3 changed files with 76 additions and 53 deletions

View File

@ -3,19 +3,20 @@
#include <stddef.h>
/* represents a string, where length and capacity are stored alongside the string data. */
typedef struct
{
char *str;
size_t len;
size_t cap;
char *str; /* string data */
size_t len; /* string length */
size_t cap; /* capacity (allocated size) */
} str_t;
int str_new (str_t *str);
int str_new_cap (str_t *str, size_t want_cap);
int str_new_from (str_t *str, const char *src);
int str_new_from_len (str_t *str, const char *src, size_t len);
void str_free (str_t *str);
int str_append (str_t *str, const char *src);
int str_append_len (str_t *str, const char *src, size_t len);
void str_new (str_t *str); /* initialize a str_t string. */
void str_new_cap (str_t *str, size_t want_cap); /* initialize a str_t string with a given capacity. */
void str_new_from (str_t *str, const char *src); /* initialize a str_t string with a given data. */
void str_new_from_len (str_t *str, const char *src, size_t len); /* initialize a str_t string with a given data and length. */
void str_free (str_t *str); /* free the contents of a str_t string. */
void str_append (str_t *str, const char *src); /* append a string to the end of a str_t string. */
void str_append_len (str_t *str, const char *src, size_t len); /* append a string to the end of a str_t string with a given length. */
#endif // CUTILS_STR_H_

View File

@ -4,60 +4,80 @@
#include <string.h>
#include "common.h"
#define STR_MIN_ALLOC 64
#define STR_MIN_ALLOC 64 /* minimum allocation size for string data */
int
/**
* initialize a str_t string and allocte some memory for the data
*
* @param str: a pointer to the string to initialize
*/
void
str_new (str_t *str)
{
if (!str)
return errno = EINVAL, -1;
str->str = smalloc (STR_MIN_ALLOC * sizeof (char));
str->str[0] = '\0';
str->len = 0;
str->cap = STR_MIN_ALLOC;
return 0;
}
int
/**
* initialize a str_t string with a given capacity (allocation size). can be
* used in oder to reduce the amount of calls to realloc.
*
* @param str: a pointer to the string to initialize
*/
void
str_new_cap (str_t *str, size_t want_cap)
{
size_t cap;
if (!str)
return errno = EINVAL, -1;
cap = max (next_pow_of_two (want_cap), STR_MIN_ALLOC);
str->str = smalloc (cap);
str->str[0] = '\0';
str->len = 0;
str->cap = cap;
return 0;
}
inline int
/**
* initialize a str_t string with a given data. the data will be copied into
* the string.
*
* @param str: a pointer to the string to initialize
* @param src: the data to put into the string
*/
inline void
str_new_from (str_t *str, const char *src)
{
if (str && src)
return str_new_from_len (str, src, strlen (src));
else
return errno = EINVAL, -1;
return str_new_from_len (str, src, strlen (src));
}
int
/**
* initialize a str_t string with a given data. the data will be copied into
* the string. the length of the data is provided as a parameter.
*
* @param str: a pointer to the string to initialize
* @param src: the data to put into the string
* @param len: the length of `src`. undefined behaviour occurs if `len !=
* strlen (src)`
*/
void
str_new_from_len (str_t *str, const char *src, size_t len)
{
size_t cap;
if (!str || !src)
return errno = EINVAL, -1;
cap = max (next_pow_of_two (len + 1), STR_MIN_ALLOC);
str->str = smalloc (cap * sizeof (char));
str->len = len;
str->cap = cap;
strncpy (str->str, src, len);
str->str[len] = '\0';
return 0;
}
/**
* free the contents of a str_t string.
*
* @param str: a pointer to the string to free
*/
inline void
str_free (str_t *str)
{
@ -65,27 +85,39 @@ str_free (str_t *str)
free (str->str);
}
inline int
/**
* append a string to the end of a str_t string.
*
* @param str: the str_t string to append to
* @param src: the cstring to append
*/
inline void
str_append (str_t *str, const char *src)
{
if (str && src)
return str_append_len (str, src, strlen (src));
else
return errno = EINVAL, -1;
str_append_len (str, src, strlen (src));
}
int
/**
* append a string to the end of a str_t string. the length of the appended
* string is provided as a parameter.
*
* @param str: the str_t string to append to
* @param src: the cstring to append
* @param len: the length of `src`. undefined behaviour occurs if `len !=
* strlen (src)`
*/
void
str_append_len (str_t *str, const char *src, size_t len)
{
size_t cap;
if (!str || !src)
return errno = EINVAL, -1;
cap = max (next_pow_of_two (str->len + len + 1), STR_MIN_ALLOC);
str->str = srealloc (str->str, cap * sizeof (char));
if (cap > str->cap)
{
str->str = srealloc (str->str, cap * sizeof (char));
str->cap = cap;
}
strncpy (str->str + str->len, src, len);
str->len += len;
str->cap = cap;
str->str[str->len] = '\0';
return 0;
}

View File

@ -57,41 +57,31 @@ test_str (void)
{
test_group_t group;
str_t str;
int res;
char *s;
group = test_group_new ();
res = str_new (&str);
str_new (&str);
test_add (&group, test_assert (str.str != NULL && str.cap > 0), "str_new");
str_free (&str);
res = str_new_cap (&str, 1000);
str_new_cap (&str, 1000);
test_add (&group, test_assert (str.cap == next_pow_of_two (1000)), "str_new_cap");
str_free (&str);
s = "Hello, World!\n";
res = str_new_from (&str, s);
str_new_from (&str, s);
test_add (&group, test_assert (!strcmp (str.str, s)), "str_new_from .str");
test_add (&group, test_assert (str.len == strlen (s)), "str_new_from .len");
test_add (&group, test_assert (str.cap >= str.len), "str_new_from .cap");
test_add (&group, test_assert (res >= 0), "str_new_from success return value");
str_free (&str);
res = str_new_from (&str, NULL);
test_add (&group, test_assert (res < 0), "str_new_from failure return value");
if (res >= 0)
str_free (&str);
s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
str_new_from (&str, s);
res = str_append (&str, s);
str_append (&str, s);
test_add (&group, test_assert (!strncmp (str.str, s, strlen (s)) && !strncmp (str.str + strlen (s), s, strlen (s))), "str_append .str");
test_add (&group, test_assert (str.len = 2 * strlen (s)), "str_append .len");
test_add (&group, test_assert (str.cap = next_pow_of_two (2 * strlen (s))), "str_append .cap");
test_add (&group, test_assert (res >= 0), "str_append success return value");
res = str_append (&str, NULL);
test_add (&group, test_assert (res < 0), "str_append failure return value");
str_free (&str);
return test_group_get_results (&group);