Compare commits

...

2 Commits

@ -207,6 +207,36 @@ nstr_t *nstrcat(const nstr_t *s1, const nstr_t *s2, error *err);
*/
nstr_t *nstrcat_put(nstr_t *s1, nstr_t *s2, error *err);
/**
* @brief Remove whitespace from the beginning and end of a string.
*
* Whether a character is whitespace is deteermined by the `isspace()` function
* from POSIX. In the default C locale, this includes:
*
* - space (ASCII `0x20`)
* - form feed (`'\f'`, ASCII `0x0c`)
* - line feed (`'\n'`, ASCII `0x0a`)
* - carriage return (`'\r'`, ASCII `0x0d`)
* - horizontal tab (`'\t'`, ASCII `0x09`)
* - vertical tab (`'\v'`, ASCII `0x0b`)
*
* @param s String to trim
* @param err Error pointer
* @returns A new string instance with outer whitespace removed,
* unless an error occurred
*/
nstr_t *nstrtrim(const nstr_t *s, error *err);
/**
* @brief The same as `nstrtrim()`, but `nput()` is called on `s` afterwards.
*
* @param s String to trim
* @param err Error pointer
* @returns A new string instance with outer whitespace removed,
* unless an error occurred
*/
nstr_t *nstrtrim_put(nstr_t *s, error *err);
/**
* @brief Compare two strings character by character.
*

@ -0,0 +1,57 @@
/* See the end of this file for copyright and license terms. */
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include "neo/_error.h"
#include "neo/_nalloc.h"
#include "neo/_nref.h"
#include "neo/_nstr.h"
#include "neo/_stddef.h"
#include "neo/_types.h"
nstr_t *nstrtrim(const nstr_t *s, error *err)
{
if (s == nil) {
yeet(err, EFAULT, "String is nil");
return nil;
}
const char *start = s->_data;
const char *end = start + s->_size - 5; /* 4 NUL terminators */
while (isspace(*start++));
/* nothing */
start--;
while (isspace(*end) && end > start)
end--;
end++;
return nnstr(start, end - start, err);
}
nstr_t *nstrtrim_put(nstr_t *s, error *err)
{
nstr_t *ret = nstrtrim(s, err);
catch(err) {
return nil;
}
nput(s);
return ret;
}
/*
* This file is part of libneo.
* Copyright (c) 2021 Fefie <owo@fef.moe>.
*
* libneo is non-violent software: you may only use, redistribute,
* and/or modify it under the terms of the CNPLv6+ as found in
* the LICENSE file in the source code root directory or at
* <https://git.pixie.town/thufie/CNPL>.
*
* libneo comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPLv6+ for details.
*/

@ -4,6 +4,7 @@ target_sources(neo PRIVATE
./string/nstrcmp.c
./string/nstrdup.c
./string/nstrmul.c
./string/nstrtrim.c
./string/leftpad.c
./string/utf.c
./string/x2nstr.c

@ -17,7 +17,7 @@
usize utf8_check(const char *restrict s, error *err)
{
usize ret = 0;
nchar c;
nchar c = 0xffffffff; /* not a valid Unicode character */
while (*s != '\0') {
ret++;
@ -27,13 +27,16 @@ usize utf8_check(const char *restrict s, error *err)
}
}
if (c == 0xffffffff) /* loop hasn't executed at all */
neat(err);
return ret;
}
usize utf8_ncheck(const char *restrict s, usize maxsize, error *err)
{
usize ret = 0;
nchar c;
nchar c = 0xffffffff; /* not a valid Unicode character */
while (*s != '\0' && maxsize != 0) {
ret++;
@ -45,6 +48,9 @@ usize utf8_ncheck(const char *restrict s, usize maxsize, error *err)
}
}
if (c == 0xffffffff) /* loop hasn't executed at all */
neat(err);
return ret;
}

@ -0,0 +1,157 @@
/* See the end of this file for copyright and license terms. */
#include <catch2/catch.hpp>
#include <errno.h>
#include <neo.h>
TEST_CASE( "nstrtrim: Trim leading whitespace", "[string/nstrtrim.c]" )
{
error err;
nstr_t *s = nstr(" \v\v aaaaa", nil);
nstr_t *expected = nstr("aaaaa", nil);
nstr_t *actual = nstrtrim(s, &err);
REQUIRE( actual != nil );
REQUIRE( nlen(actual) == 5 );
REQUIRE( nstreq(expected, actual, nil) );
REQUIRE( errnum(&err) == 0 );
nput(s);
nput(expected);
nput(actual);
}
TEST_CASE( "nstrtrim: Trim trailing whitespace", "[string/nstrtrim.c]" )
{
error err;
nstr_t *s = nstr("aaaaa \t \r\n \f \n", nil);
nstr_t *expected = nstr("aaaaa", nil);
nstr_t *actual = nstrtrim(s, &err);
REQUIRE( actual != nil );
REQUIRE( nlen(actual) == 5 );
REQUIRE( nstreq(expected, actual, nil) );
REQUIRE( errnum(&err) == 0 );
nput(s);
nput(expected);
nput(actual);
}
TEST_CASE( "nstrtrim: Trim both leading and trailing whitespace", "[string/nstrtrim.c]" )
{
error err;
nstr_t *s = nstr(" \v\v aaaaa \t \r\n \f \n", nil);
nstr_t *expected = nstr("aaaaa", nil);
nstr_t *actual = nstrtrim(s, &err);
REQUIRE( actual != nil );
REQUIRE( nlen(actual) == 5 );
REQUIRE( nstreq(expected, actual, nil) );
REQUIRE( errnum(&err) == 0 );
nput(s);
nput(expected);
nput(actual);
}
TEST_CASE( "nstrtrim: Don't modify empty string", "[string/nstrtrim.c]" )
{
error err;
nstr_t *s = nstr("", nil);
nstr_t *expected = nstr("", nil);
nstr_t *actual = nstrtrim(s, &err);
REQUIRE( actual != nil );
REQUIRE( nlen(actual) == 0 );
REQUIRE( nstreq(expected, actual, nil) );
REQUIRE( errnum(&err) == 0 );
nput(s);
nput(expected);
nput(actual);
}
TEST_CASE( "nstrtrim: Empty string if input is whitespace only", "[string/nstrtrim.c]" )
{
error err;
nstr_t *s = nstr(" ", nil);
nstr_t *expected = nstr("", nil);
nstr_t *actual = nstrtrim(s, &err);
REQUIRE( actual != nil );
REQUIRE( nlen(actual) == 0 );
REQUIRE( nstreq(expected, actual, nil) );
REQUIRE( errnum(&err) == 0 );
nput(s);
nput(expected);
nput(actual);
}
TEST_CASE( "nstrtrim: Error if string is nil", "[string/nstrtim.c]" )
{
error err;
nstr_t *tr = nstrtrim(nil, &err);
nstr_t *expected_msg = nstr("String is nil", nil);
REQUIRE( tr == nil );
REQUIRE( errnum(&err) == EFAULT );
REQUIRE( nstreq(expected_msg, errmsg(&err), nil) );
errput(&err);
}
TEST_CASE( "nstrtrim_put: Decrement refcount", "[string/nstrtrim.c]" )
{
error err;
nstr_t *s = nstr(" aaaaa ", nil);
nstr_t *expected = nstr("aaaaa", nil);
nget(s);
nstr_t *actual = nstrtrim_put(s, &err);
REQUIRE( nref_count(s) == 1 );
REQUIRE( actual != nil );
REQUIRE( nstreq(expected, actual, nil) );
REQUIRE( errnum(&err) == 0 );
nput(s);
nput(expected);
nput(actual);
}
TEST_CASE( "nstrtrim_put: Error if string is nil", "[string/nstrtim.c]" )
{
error err;
nstr_t *tr = nstrtrim_put(nil, &err);
nstr_t *expected_msg = nstr("String is nil", nil);
REQUIRE( tr == nil );
REQUIRE( errnum(&err) == EFAULT );
REQUIRE( nstreq(expected_msg, errmsg(&err), nil) );
errput(&err);
}
/*
* This file is part of libneo.
* Copyright (c) 2021 Fefie <owo@fef.moe>.
*
* libneo is non-violent software: you may only use, redistribute,
* and/or modify it under the terms of the CNPLv6+ as found in
* the LICENSE file in the source code root directory or at
* <https://git.pixie.town/thufie/CNPL>.
*
* libneo comes with ABSOLUTELY NO WARRANTY, to the extent
* permitted by applicable law. See the CNPLv6+ for details.
*/

@ -10,6 +10,7 @@ target_sources(neo_test PRIVATE
string/nstrcmp.cpp
string/nstrdup.cpp
string/nstrmul.cpp
string/nstrtrim.cpp
string/u2nstr.cpp
)

Loading…
Cancel
Save