fix: (str) return str_t instead of caller allocted

This commit is contained in:
thetek 2023-02-15 10:18:29 +01:00
parent 6b1ad69a34
commit 8c8695fec4
3 changed files with 68 additions and 55 deletions

View File

@ -13,10 +13,11 @@ typedef struct
size_t cap; /* capacity (allocated size) */
} str_t;
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. */
str_t str_new (); /* initialize a str_t string. */
str_t str_new_cap (size_t want_cap); /* initialize a str_t string with a given capacity. */
str_t str_new_from (const char *src); /* initialize a str_t string with a given data. */
str_t str_new_from_len (const char *src, size_t len); /* initialize a str_t string with a given data and length. */
str_t str_clone (const str_t *orig); /* clone the contents of a str_t string into a new str_t string. */
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. */
@ -31,7 +32,6 @@ ssize_t str_pos (const str_t *str, const char *find); /* find the index of a sub
bool str_is_blank (const str_t *str); /* check if a string only consists of whitespace characters. */
void str_downcase (str_t *str); /* transform all uppercase characters in a str_t string to lowercase */
void str_upcase (str_t *str); /* transform all lowercase characters in a str_t string to uppercase */
void str_clone (const str_t *str, str_t *new); /* clone the contents of a str_t string into a new str_t string. */
void str_resize (str_t *str, size_t cap); /* resize the allocated data of a str_t string. */
#endif // CUTILS_STR_H_

103
lib/str.c
View File

@ -10,72 +10,95 @@
/**
* initialize a str_t string and allocte some memory for the data
*
* @param str: a pointer to the string to initialize. `str` has to be
* caller-allocated.
* @return a new, empty str_t instance
*/
void
str_new (str_t *str)
str_t
str_new ()
{
str->str = smalloc (STR_MIN_ALLOC * sizeof (char));
str->str[0] = '\0';
str->len = 0;
str->cap = STR_MIN_ALLOC;
str_t str;
str.str = smalloc (STR_MIN_ALLOC * sizeof (char));
str.str[0] = '\0';
str.len = 0;
str.cap = STR_MIN_ALLOC;
return str;
}
/**
* initialize a str_t string with a given capacity (allocation size). can be
* used in oder to reduce the amount of calls to realloc.
* used in oder to reduce the amount of calls to `realloc()`.
*
* @param str: a pointer to the string to initialize. `str` has to be
* caller-allocated.
* @param want_cap: the minimum wanted capacity
*
* @return a new, empty str_t instance with given capacity.
*/
void
str_new_cap (str_t *str, size_t want_cap)
str_t
str_new_cap (size_t want_cap)
{
size_t cap;
str_t str;
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;
str.str = smalloc (cap);
str.str[0] = '\0';
str.len = 0;
str.cap = cap;
return str;
}
/**
* 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. `str` has to be
* caller-allocated.
* @param src: the data to put into the string
*
* @return a new, empty str_t with given data.
*/
inline void
str_new_from (str_t *str, const char *src)
inline str_t
str_new_from (const char *src)
{
return str_new_from_len (str, src, strlen (src));
return str_new_from_len (src, strlen (src));
}
/**
* 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. `str` has to be
* caller-allocated.
* @param src: the data to put into the string
* @param len: the length of `src`. undefined behaviour occurs if `len !=
* strlen (src)`
*
* @return a new, empty str_t with given data.
*/
void
str_new_from_len (str_t *str, const char *src, size_t len)
str_t
str_new_from_len (const char *src, size_t len)
{
size_t cap;
str_t str;
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';
str.str = smalloc (cap * sizeof (char));
str.len = len;
str.cap = cap;
strncpy (str.str, src, len);
str.str[len] = '\0';
return str;
}
/**
* clone the contents of a str_t string into a new str_t string.
*
* @param orig: the original str_t string
*
* @return a new str_t instance with the same data as `str`
*/
inline str_t
str_clone (const str_t *orig)
{
return str_new_from_len (orig->str, orig->len);
}
/**
@ -168,7 +191,8 @@ str_starts_with (const str_t *str, const char *find)
*
* @param str: the str_t string to search in
* @param find: the cstring to search for
* @param len: the length of `find`
* @param len: the length of `find`. undefined behaviour occurs if `len !=
* strlen (src)`
*
* @return true if `str` starts with `find`, else false
*/
@ -197,7 +221,8 @@ str_ends_with (const str_t *str, const char *find)
*
* @param str: the str_t string to search in
* @param find: the cstring to search for
* @param len: the length of `find`
* @param len: the length of `find`. undefined behaviour occurs if `len !=
* strlen (src)`
*
* @return true if `str` ends with `find`, else false
*/
@ -281,18 +306,6 @@ str_upcase (str_t *str)
strupcase (str->str);
}
/**
* clone the contents of a str_t string into a new str_t string.
*
* @param str: the original str_t string
* @param new: the new str_t string. `new` has to be caller-allocated.
*/
inline void
str_clone (const str_t *str, str_t *new)
{
str_new_from_len (new, str->str, str->len);
}
/**
* resize the allocated data of a str_t string.
*

View File

@ -61,30 +61,30 @@ test_str (void)
group = test_group_new ();
str_new (&str);
str = str_new ();
test_add (&group, test_assert (str.str != NULL && str.cap > 0), "str_new");
str_free (&str);
str_new_cap (&str, 1000);
str = str_new_cap (1000);
test_add (&group, test_assert (str.cap == next_pow_of_two (1000)), "str_new_cap");
str_free (&str);
s = "Hello, World!\n";
str_new_from (&str, s);
str = str_new_from (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");
str_free (&str);
s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
str_new_from (&str, s);
str = str_new_from (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");
str_free (&str);
str_new_from (&str, s);
str = str_new_from (s);
test_add (&group, test_assert (str_eq (&str, s)), "str_eq true");
test_add (&group, test_assert (!str_eq (&str, "foo")), "str_eq false");
test_add (&group, test_assert (str_cmp (&str, "A") > 0), "str_eq greater");