doc: (str) add str documentation
This commit is contained in:
parent
df4d6036fc
commit
b39ba90bc9
|
@ -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_
|
||||
|
|
90
lib/str.c
90
lib/str.c
|
@ -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;
|
||||
}
|
||||
|
|
18
test/main.c
18
test/main.c
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue