~donmcc/astr

a866d791a9ff1b3abd82ac3f25adf37fd8183dbf — Don McCaughey 1 year, 6 months ago 279dfe3
Added the `astr_cmp()` function for comparing strings.

The `astr_cmp()` function is an inline wrapper around `strcmp()` that
included `NULL` handling.

Reimplemented `astr_eq()` in terms of `astr_cmp()`.
5 files changed, 78 insertions(+), 6 deletions(-)

M README.md
M astr.3
M astr.c
M astr.h
M astr_tests.c
M README.md => README.md +8 -0
@@ 35,6 35,14 @@ Allocate an empty string.

Allocate a formatted string.

    int
    astr_cmp(char const *s1, char const *s2);

Compare the bytes of two strings; `s1` and `s2` may be `NULL`.  The return
value is negative if `s1` is ordered before `s2`, positive if `s1` is ordered
after `s2` and zero if `s1` equals `s2`.  A `NULL` string pointers is ordered 
before all non-`NULL` string pointers.

    bool
    astr_empty(char const *s);


M astr.3 => astr.3 +34 -3
@@ 5,6 5,7 @@
.Nm astr_alloc_empty ,
.Nm astr_alloc_formatted ,
.Nm astr_alloc_formatted_from_va_list ,
.Nm astr_cmp ,
.Nm astr_empty ,
.Nm astr_eq ,
.Nm astr_formatted_length ,


@@ 20,10 21,12 @@
.Fn astr_alloc_formatted "char const *format" "..."
.Ft char *
.Fn astr_alloc_formatted_from_va_list "char const *format" "va_list arguments"
.Ft int
.Fn astr_cmp "char const *s1" "char const *s2"
.Ft bool
.Fn astr_empty "char const *s"
.Ft bool
.Fn astr_eq "char const s1" "char const s2"
.Fn astr_eq "char const *s1" "char const *s2"
.Ft size_t
.Fn astr_formatted_length "char const *format" "..."
.Ft size_t


@@ 84,14 87,23 @@ and
.Fn astr_alloc_formatted_from_va_list
allocate formatted strings.
.Pp
.Fn astr_cmp
compares the bytes of two strings.
The string pointer arguments
.Fa s1
and
.Fa s2
may be
.Dv NULL .
.Pp
.Fn astr_empty
tests if a given string pointer is
.Dv NULL
or zero-length.
.Pp
.Fn astr_eq
compares two string pointers for equality in an encoding agnostic way.
The arguments
compares the bytes of two strings for equality.
The string pointer arguments
.Fa s1
and
.Fa s2


@@ 124,6 136,25 @@ pointer and set
to
.Er EINVAL .
.Pp
.Fn astr_cmp
returns a negative integer if
.Fa s1
is ordered before
.Fa s2 ,
a positive integer if
.Fa s1
is ordered after
.Fa s2
and zero if
.Fa s1
equals
.Fa s2 .
A
.Dv NULL
string pointer is ordered before all
.Pf non- Dv NULL
string pointers.
.Pp
.Fn astr_empty
returns
.Dv true

M astr.c => astr.c +3 -0
@@ 100,6 100,9 @@ astr_realloc_append_formatted_from_va_list(char **s,
extern char *
astr_alloc_empty(void);

extern int 
astr_cmp(char const *s1, char const *s2);

extern bool
astr_empty(char const *s);


M astr.h => astr.h +10 -3
@@ 35,6 35,15 @@ astr_alloc_empty(void)
    return calloc(1, sizeof(char));
}

inline int
astr_cmp(char const *s1, char const *s2)
{
    if (s1 == s2) return 0;
    if (!s1) return -1;
    if (!s2) return 1;
    return strcmp(s1, s2);
}

inline bool
astr_empty(char const *s)
{


@@ 44,9 53,7 @@ astr_empty(char const *s)
inline bool
astr_eq(char const *s1, char const *s2)
{
    if (s1 == s2) return true;
    if (!s1 || !s2) return false;
    return 0 == strcmp(s1, s2);
    return 0 == astr_cmp(s1, s2);
}



M astr_tests.c => astr_tests.c +23 -0
@@ 37,6 37,28 @@ test_astr_alloc_formatted_for_NULL_format(void)


static void
test_astr_cmp(void)
{
    assert(0 == astr_cmp(NULL, NULL));
    assert(0 == astr_cmp("foo", "foo"));

    assert(astr_cmp(NULL, "") < 0);
    assert(astr_cmp("", NULL) > 0);

    assert(astr_cmp(NULL, "foo") < 0);
    assert(astr_cmp("foo", NULL) > 0);

    assert(astr_cmp("", "foo") < 0);
    assert(astr_cmp("foo", "") > 0);

    assert(astr_cmp("bar", "foo") < 0);
    assert(astr_cmp("foo", "bar") > 0);

    assert(astr_cmp("foo", "foobar") < 0);
    assert(astr_cmp("foobar", "foo") > 0);
}

static void
test_astr_empty(void)
{
    assert(astr_empty(NULL));


@@ 163,6 185,7 @@ main(int argc, char *argv[])
    test_astr_alloc_empty();
    test_astr_alloc_formatted();
    test_astr_alloc_formatted_for_NULL_format();
    test_astr_cmp();
    test_astr_empty();
    test_astr_eq();
    test_astr_eq_for_NULL_string();