~donmcc/astr

f73ed69a6d61c7eac7c6c7733b692f21190ca55c — Don McCaughey 3 years ago f4dd4ca
Added `astr_len_format()` and `astr_len_format_args()`.

These two functions use `vsnprintf()` to calculate the number of bytes
needed to hold the formatted string that would result from the
equivalent call to `astr_alloc_format()`.

Added tests and updated the readme and man page for these functions.

Removed tests for the `astr_alloc_format_args()` function, since the
tests for `astr_alloc_format()` cover this function as well.
4 files changed, 77 insertions(+), 40 deletions(-)

M README.md
M astr.c
M astr.h
M astr_tests.c
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;
}