M README.md => README.md +20 -4
@@ 7,8 7,11 @@ A C99 library for working with dynamically allocated strings.
## Overview
All functions in *astr* begin with the `astr_` prefix. Functions that return
-newly allocated strings will contain `alloc_` in their names; the caller is
+newly allocated strings will contain `_alloc` in their names; the caller is
responsible for calling [`free()`][1] on the returned pointer.
+Functions with `_format` take a `printf()` style format string.
+Functions that end with the suffix `_args` take variable arguments as a
+`va_list` object from `stdarg.h`.
[1]: http://man7.org/linux/man-pages/man3/free.3.html
@@ 34,12 37,25 @@ Allocate a formatted string using a `va_list` object.
Compare the bytes of two strings for equality; `s1` and `s2` may be `NULL`.
+ size_t
+ astr_len_format(char const *format, ...);
+
+Calculate the length in bytes needed for the formatted string.
+
+ size_t
+ astr_len_format_args(char const *format, va_list arguments);
+
+Calculate the length in bytes needed for the formatted string using a `va_list`
+object.
+
## Dependencies
-`astr` requires that `<stdio.h>` defines the [`vasprintf()`][2] function.
-Building from repository source requires [GNU Autotools][3].
+`astr` requires that `<stdio.h>` defines the [`vasprintf()`][2] and
+[`vsnprintf()`][3] functions.
+Building from repository source requires [GNU Autotools][4].
[2]: http://man7.org/linux/man-pages/man3/asprintf.3.html
-[3]: https://www.gnu.org/software/automake/faq/autotools-faq.html
+[3]: http://man7.org/linux/man-pages/man3/printf.3.html
+[4]: https://www.gnu.org/software/automake/faq/autotools-faq.html
## Building from Repository Source
M astr.c => astr.c +29 -1
@@ 28,7 28,9 @@ astr_alloc_format_args(char const *format, va_list arguments)
}
char *s;
- int chars_printed = vasprintf(&s, format, arguments);
+ va_list arguments_copy;
+ va_copy(arguments_copy, arguments);
+ int chars_printed = vasprintf(&s, format, arguments_copy);
if (chars_printed < 0) return NULL;
return s;
}
@@ 37,3 39,29 @@ astr_alloc_format_args(char const *format, va_list arguments)
extern bool
astr_eq_bytes(char const *s1, char const *s2);
+
+size_t
+astr_len_format(char const *format, ...)
+{
+ va_list arguments;
+ va_start(arguments, format);
+ size_t length = astr_len_format_args(format, arguments);
+ va_end(arguments);
+ return length;
+}
+
+
+size_t
+astr_len_format_args(char const *format, va_list arguments)
+{
+ if (!format) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ va_list arguments_copy;
+ va_copy(arguments_copy, arguments);
+ int length = vsnprintf(NULL, 0, format, arguments_copy);
+ return length < 0 ? 0 : length;
+}
+
M astr.h => astr.h +6 -0
@@ 27,6 27,12 @@ astr_eq_bytes(char const *s1, char const *s2)
return 0 == strcmp(s1, s2);
}
+size_t
+astr_len_format(char const *format, ...);
+
+size_t
+astr_len_format_args(char const *format, va_list arguments);
+
#endif
M astr_tests.c => astr_tests.c +22 -35
@@ 36,39 36,6 @@ test_astr_alloc_format_for_NULL_format(void)
}
-static char *
-helper_alloc_format(char const *format, ...)
-{
- va_list arguments;
- va_start(arguments, format);
- char *s = astr_alloc_format_args(format, arguments);
- va_end(arguments);
- return s;
-}
-
-
-static void
-test_astr_alloc_format_args(void)
-{
- char *s = helper_alloc_format("answer: %i", 42);
- assert(s);
- assert(10 == strlen(s));
- assert(astr_eq_bytes("answer: 42", s));
- free(s);
-}
-
-
-static void
-test_astr_alloc_format_args_for_NULL_format(void)
-{
- errno = 0;
- char *s = helper_alloc_format(NULL);
- assert(!s);
- assert(EINVAL == errno);
- free(s);
-}
-
-
static void
test_astr_eq_bytes(void)
{
@@ 94,16 61,36 @@ test_astr_eq_bytes_for_NULL_string(void)
}
+static void
+test_astr_len_format(void)
+{
+ errno = 0;
+ size_t length = astr_len_format("answer: %i", 42);
+ assert(10 == length);
+ assert(0 == errno);
+}
+
+
+static void
+test_astr_len_format_for_NULL_format(void)
+{
+ errno = 0;
+ size_t length = astr_len_format(NULL);
+ assert(0 == length);
+ assert(EINVAL == errno);
+}
+
+
int
main(int argc, char *argv[])
{
test_astr_alloc_empty();
test_astr_alloc_format();
test_astr_alloc_format_for_NULL_format();
- test_astr_alloc_format_args();
- test_astr_alloc_format_args_for_NULL_format();
test_astr_eq_bytes();
test_astr_eq_bytes_for_NULL_string();
+ test_astr_len_format();
+ test_astr_len_format_for_NULL_format();
return EXIT_SUCCESS;
}