~donmcc/astr

4b4d0e6ef80e75ab67f8fce9b7065ee4f8887389 — Don McCaughey 1 year, 9 months ago a09a083
Added `astr_alloc_formatted_args()` function.

Extracted this function from `astr_alloc_formatted()` to separate the
`va_list` processing (which stays in `astr_alloc_formatted()`) from the
string formatting logic, which moved into `astr_alloc_formatted_args()`.

Added tests and updated the readme and man page.
5 files changed, 74 insertions(+), 15 deletions(-)

M README.md
M astr.3
M astr.c
M astr.h
M astr_tests.c
M README.md => README.md +5 -0
@@ 24,6 24,11 @@ Allocate an empty string.

Allocate a formatted string.

    char *
    astr_alloc_formatted_args(char const *format, va_list arguments);

Allocate a formatted string using a `va_list` object.

    bool
    astr_eq_bytes(char const *s1, char const *s2);


M astr.3 => astr.3 +20 -7
@@ 1,5 1,3 @@
.\" Modified from man(1) of FreeBSD, the NetBSD mdoc.template and mdoc.samples
.\" See man mdoc for the short list of editing options
.Dd February 23, 2020
.Dt ASTR 3
.Os


@@ 14,6 12,8 @@
.Fn astr_alloc_empty "void"
.Ft char *
.Fn astr_alloc_formatted "char const *format" "..."
.Ft char *
.Fn astr_alloc_formatted_args "char const *format" "va_list arguments"
.Ft bool
.Fn astr_eq_bytes "char const s1" "char const s2"
.Sh DESCRIPTION


@@ 26,27 26,37 @@ building on top of
All functions in the
.Nm astr
library begin with the
.Sy astr
.Sy astr_
prefix.
Functions that return newly allocated strings will contain
.Sy alloc
.Sy _alloc
in their name; the caller is responsible for calling
.Fn free
on the returned pointer.
Functions with
.Sy formatted
.Sy _formatted
in their name take a
.Fa format
string as specified for
.Xr printf 3
along with zero or more additional arguments as determined by the given format
and produce formatted output.
Functions that end with the suffix
.Sy _args
take a variable number of
.Fa arguments
as a
.Sy va_list
object defined in
.Xr stdarg 3 .
.Pp
.Fn astr_alloc_empty
allocates an empty string.
.Pp
.Fn astr_alloc_formatted
allocates a formatted string.
and
.Fn astr_alloc_formatted_args
allocate formatted strings.
.Pp
.Fn astr_eq_bytes
compares two string pointers for equality in an encoding agnostic way.


@@ 60,7 70,9 @@ may be
.Fn astr_alloc_empty
returns a pointer to a zero-length string on success.
.Fn astr_alloc_formatted
returns a pointer to a formatted string on success.
and
.Fn astr_alloc_formatted_args
return a pointer to a formatted string on success.
.Pp
If there is an error, these functions return a
.Dv NULL


@@ 76,6 88,7 @@ if the two string pointers are equal or point to the same sequence of bytes.
.Sh SEE ALSO
.Xr free 3 ,
.Xr printf 3 ,
.Xr stdarg 3 ,
.Xr vasprintf 3
.Sh AUTHORS
.An Don McCaughey

M astr.c => astr.c +11 -6
@@ 1,7 1,6 @@
#include "astr.h"

#include <errno.h>
#include <stdarg.h>
#include <stdio.h>




@@ 12,18 11,24 @@ astr_alloc_empty(void);
char *
astr_alloc_formatted(char const *format, ...)
{
    va_list arguments;
    va_start(arguments, format);
    char *s = astr_alloc_formatted_args(format, arguments);
    va_end(arguments);
    return s;
}


char *
astr_alloc_formatted_args(char const *format, va_list arguments)
{
    if (!format) {
        errno = EINVAL;
        return NULL;
    }

    char *s;

    va_list arguments;
    va_start(arguments, format);
    int chars_printed = vasprintf(&s, format, arguments);
    va_end(arguments);

    if (chars_printed < 0) return NULL;
    return s;
}

M astr.h => astr.h +3 -1
@@ 2,6 2,7 @@
#define ASTR_H_INCLUDED


#include <stdarg.h>
#include <stdbool.h>
#include <string.h>



@@ 9,6 10,8 @@
char *
astr_alloc_formatted(char const *format, ...);

char *
astr_alloc_formatted_args(char const *format, va_list arguments);

inline char *
astr_alloc_empty(void)


@@ 16,7 19,6 @@ astr_alloc_empty(void)
    return astr_alloc_formatted("");
}


inline bool
astr_eq_bytes(char const *s1, char const *s2)
{

M astr_tests.c => astr_tests.c +35 -1
@@ 17,7 17,6 @@ test_astr_alloc_empty(void)
static void
test_astr_alloc_formatted(void)
{

    char *s = astr_alloc_formatted("answer: %i", 42);
    assert(s);
    assert(10 == strlen(s));


@@ 37,6 36,39 @@ test_astr_alloc_formatted_for_NULL_format(void)
}


static char *
helper_alloc_formatted(char const *format, ...)
{
    va_list arguments;
    va_start(arguments, format);
    char *s = astr_alloc_formatted_args(format, arguments);
    va_end(arguments);
    return s;
}


static void
test_astr_alloc_formatted_args(void)
{
    char *s = helper_alloc_formatted("answer: %i", 42);
    assert(s);
    assert(10 == strlen(s));
    assert(astr_eq_bytes("answer: 42", s));
    free(s);
}


static void
test_astr_alloc_formatted_args_for_NULL_format(void)
{
    errno = 0;
    char *s = helper_alloc_formatted(NULL);
    assert(!s);
    assert(EINVAL == errno);
    free(s);
}


static void
test_astr_eq_bytes(void)
{


@@ 68,6 100,8 @@ main(int argc, char *argv[])
    test_astr_alloc_empty();
    test_astr_alloc_formatted();
    test_astr_alloc_formatted_for_NULL_format();
    test_astr_alloc_formatted_args();
    test_astr_alloc_formatted_args_for_NULL_format();
    test_astr_eq_bytes();
    test_astr_eq_bytes_for_NULL_string();
    return EXIT_SUCCESS;