Compare commits

..

No commits in common. "aae039ae29e7a0315734abbeb543efb9bed2af0d" and "5b46a05ce7ede3aa3a5e405f1a64100a64dab5a2" have entirely different histories.

12 changed files with 38 additions and 275 deletions

View file

@ -8,11 +8,7 @@ extern "C" {
#include "neo/_types.h"
#ifdef __cplusplus
# define nil nullptr
#else
# define nil ((void *)0)
#endif
#define nil ((void *)0)
#if !defined(__cplusplus) && !defined(true)
# define true ((bool)1)

View file

@ -22,20 +22,6 @@ extern "C" {
*/
string *nstr(const char *__restrict s, error *err);
/**
* Copy a regular C string to a neo string, but at most `maxsize` bytes.
*
* The string is copied until a NUL terminator is encountered, or until
* `maxsize` bytes have been read. If `maxsize` is 0, an empty string is
* returned. If `s` is `nil` or allocation fails, an error is yeeted.
* Strings in libneo are reference counted, see `nget` and `nput`.
*
* @param s: String to convert
* @param err: Error pointer
* @returns The converted string, unless an error occurred
*/
string *nnstr(const char *__restrict s, usize maxsize, error *err);
/**
* Get the Unicode code point in a string at the specified index.
*
@ -147,7 +133,7 @@ int nstrcmp(const string *s1, const string *s2, error *err);
* @param err: Error pointer
* @returns Whether the two strings are equal, unless an error occurred
*/
#define nstreq(s1, s2, err) ( (bool)(nstrcmp(s1, s2, err) == 0) )
#define nstreq(s1, s2, err) ( (bool)(nstrcmp(s1, s2, err) != 0) )
/**
* Prepend fill characters to a string to make it a specific length, and return

View file

@ -16,22 +16,22 @@
void yeet(error *err, u32 number, const char *restrict fmt, ...)
{
va_list vargs;
usize msg_size = 64;
usize msg_capacity = 64;
char *msg = nil;
int vsnprintf_ret;
if (fmt != nil) {
do {
msg = nalloc(msg_size, nil);
msg = nalloc(msg_capacity, nil);
va_start(vargs, fmt);
int required_size = vsnprintf(msg, msg_size, fmt, vargs);
vsnprintf_ret = vsnprintf(msg, msg_capacity, fmt, vargs);
va_end(vargs);
/* required_size excludes NUL, therefore >= */
if (required_size >= msg_size) {
msg_size = required_size + 1;
if (vsnprintf_ret > msg_capacity) {
msg_capacity = vsnprintf_ret;
nfree(msg);
msg = nil;
} else if (required_size < 0) {
write(2, "Runtime error\n", strlen("Runtime error\n"));
} else if (vsnprintf_ret < 0) {
write(1, "Runtime error\n", 14);
exit(1);
}
} while (msg == nil);
@ -46,7 +46,6 @@ void yeet(error *err, u32 number, const char *restrict fmt, ...)
err->_number = number;
err->_message = nstr(msg, nil);
nfree(msg);
}
void neat(error *err)

View file

@ -19,13 +19,7 @@ static inline string *leftpad_unsafe(const string *s, usize len, nchar fillchr,
}
usize extra_chars = len - s->_len;
/*
* This is actually three bytes larger than the actual size because neo
* strings are terminated with four NUL characters rather than just one,
* but that's okay because if we don't even have enough memory for three
* extra bytes we are screwed anyway.
*/
usize size_now = s->_capacity;
usize size_now = s->_capacity + 1;
usize size_after = size_now + (extra_chars * fillchr_size);
char *dest = nalloc(size_after, err);
catch(err) {
@ -56,10 +50,10 @@ string *leftpad(const string *s, usize len, nchar fillchr, error *err)
string *padded;
if (len < nlen(s)) {
if (len < s->_len) {
yeet(err, ERANGE, "String is longer than requested length");
padded = nil;
} else if (nlen(s) == len) {
} else if (s->_len == len) {
padded = nstrdup(s, err);
} else {
padded = leftpad_unsafe(s, len, fillchr, err);

View file

@ -1,8 +1,5 @@
/** See the end of this file for copyright and license terms. */
/* strnlen */
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <string.h>
@ -19,10 +16,10 @@ static void nstr_destroy(string *str)
nfree(str);
}
static string *nstr_unsafe(const char *restrict s, usize size_without_nul, error *err)
string *nstr(const char *restrict s, error *err)
{
usize len = utf8_check(s, err);
catch(err) {
if (s == nil) {
yeet(err, EFAULT, "String must not be nil");
return nil;
}
@ -43,48 +40,24 @@ static string *nstr_unsafe(const char *restrict s, usize size_without_nul, error
*
* Yeah, this is definitely never gonna break my legs.
*/
str->_data = nalloc(size_without_nul + 4, err);
usize nbytes = strlen(s) + 4;
str->_data = nalloc(nbytes, err);
catch(err) {
nfree(str);
return nil;
}
str->_len = len;
str->_capacity = size_without_nul + 4;
strcpy(str->_data, s);
str->_data[nbytes - 3] = '\0';
str->_data[nbytes - 2] = '\0';
str->_data[nbytes - 1] = '\0';
str->_len = utf8_strlen(str->_data);
str->_capacity = nbytes;
nref_init(str, nstr_destroy);
memcpy(str->_data, s, size_without_nul);
str->_data[size_without_nul] = '\0';
str->_data[size_without_nul + 1] = '\0';
str->_data[size_without_nul + 2] = '\0';
str->_data[size_without_nul + 3] = '\0';
return str;
}
string *nstr(const char *restrict s, error *err)
{
if (s == nil) {
yeet(err, EFAULT, "String is nil");
return nil;
}
usize size_without_nul = strlen(s);
return nstr_unsafe(s, size_without_nul, err);
}
string *nnstr(const char *restrict s, usize maxsize, error *err)
{
if (s == nil) {
yeet(err, EFAULT, "String is nil");
return nil;
}
usize size_without_nul = strnlen(s, maxsize);
return nstr_unsafe(s, size_without_nul, err);
}
nchar nchrat(const string *s, usize index, error *err)
{
if (s == nil) {

View file

@ -1,8 +1,5 @@
/** See the end of this file for copyright and license terms. */
/* strnlen */
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <string.h>
@ -24,17 +21,15 @@ string *nstrcat(const string *s1, const string *s2, error *err)
return nil;
}
usize s1_size_without_nul = strlen(s1->_data);
usize s2_size_without_nul = strlen(s2->_data);
usize cat_size = s1_size_without_nul + s2_size_without_nul + 1;
char *cat = nalloc(cat_size, err);
usize s1_size = strlen(s1->_data);
usize s2_size = strlen(s2->_data);
char *cat = nalloc(s1_size + s2_size + 1, err);
catch(err) {
return nil;
}
memcpy(cat, s1->_data, s1_size_without_nul);
memcpy(cat + s1_size_without_nul, s2->_data, s2_size_without_nul);
cat[s1_size_without_nul + s2_size_without_nul] = '\0';
strcpy(cat, s1->_data);
strcpy(cat + s1_size, s2->_data);
string *ret = nstr(cat, err);
nfree(cat);

View file

@ -22,13 +22,13 @@ int nstrcmp(const string *s1, const string *s2, error *err)
int ret;
usize maxbytes;
if (s1->_capacity > s2->_capacity)
maxbytes = s2->_capacity;
if (nlen(s1) > nlen(s2))
ret = 1;
else if (nlen(s1) < nlen(s2))
ret = -1;
else
maxbytes = s1->_capacity;
ret = strcmp(s1->_data, s2->_data);
ret = strncmp(s1->_data, s2->_data, maxbytes);
neat(err);
return ret;
}

View file

@ -57,7 +57,7 @@ string *nchrmul(nchar c, usize n, error *err)
char *pos = multiplied;
while (n-- != 0) {
memcpy(pos, &s[0], s_size);
strncpy(pos, &s[0], s_size);
pos += s_size;
}

View file

@ -1,8 +1,7 @@
# See the end of this file for copyright and license terms.
enable_language(CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 17)
include(CTest)
include(FetchContent)
@ -12,15 +11,13 @@ FetchContent_Declare(
GIT_TAG v2.13.6
)
FetchContent_MakeAvailable(Catch2)
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/contrib)
include(Catch)
add_executable(neo_test neo_test.cpp)
include(string/string.cmake)
target_compile_features(neo_test PRIVATE cxx_std_17)
target_link_libraries(neo_test PRIVATE neo Catch2::Catch2)
catch_discover_tests(neo_test)
add_test(NAME neo COMMAND neo_test)
# This file is part of libneo.
# Copyright (c) 2021 Fefie <owo@fef.moe>.

View file

@ -1,14 +0,0 @@
# See the end of this file for copyright and license terms.
include(string/utf/utf.cmake)
# 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.

View file

@ -1,17 +0,0 @@
# See the end of this file for copyright and license terms.
target_sources(neo_test PRIVATE
string/utf/utf8_to_nchr.cpp
)
# 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.

View file

@ -1,146 +0,0 @@
/** See the end of this file for copyright and license terms. */
#include <catch2/catch.hpp>
#include <errno.h>
#include <neo.h>
#include <neo/utf.h>
TEST_CASE( "Decode 1-byte character sequence", "[utf]" )
{
error err;
nchar c;
usize size = utf8_to_nchr(&c, ",", &err);
REQUIRE( size == 1 );
REQUIRE( c == ',' );
REQUIRE( errnum(&err) == 0 );
REQUIRE( errmsg(&err) == nil );
}
TEST_CASE( "Decode 2-byte character sequence", "[utf]" )
{
error err;
nchar c;
/* U+03B1 Greek Smol Letter Alpha */
usize size = utf8_to_nchr(&c, "\xce\xb1", &err);
REQUIRE( size == 2 );
REQUIRE( c == 0x03b1 );
REQUIRE( errnum(&err) == 0 );
REQUIRE( errmsg(&err) == nil );
}
TEST_CASE( "Decode 3-byte character sequence", "[utf]" )
{
error err;
nchar c;
/* U+3042 Hiragana Letter A */
usize size = utf8_to_nchr(&c, "\xe3\x81\x82", &err);
REQUIRE( size == 3 );
REQUIRE( c == 0x3042 );
REQUIRE( errnum(&err) == 0 );
REQUIRE( errmsg(&err) == nil );
}
TEST_CASE( "Decode 4-byte character sequence", "[utf]" )
{
error err;
nchar c;
/* U+1F97A The Bottom Emoji(TM) */
usize size = utf8_to_nchr(&c, "\xf0\x9f\xa5\xba", &err);
REQUIRE( size == 4 );
REQUIRE( c == 0x01f97a );
REQUIRE( errnum(&err) == 0 );
REQUIRE( errmsg(&err) == nil );
}
TEST_CASE( "Error on malformed sequence start", "[utf8]" )
{
error err;
nchar c;
utf8_to_nchr(&c, "\xff", &err);
string *expected = nstr("Illegal UTF-8 sequence start byte: 0xff", nil);
string *actual = errmsg(&err);
REQUIRE( c == '\0' );
REQUIRE( errnum(&err) == EINVAL );
REQUIRE( nstreq(expected, actual, nil) );
errput(&err);
}
TEST_CASE( "Error on wrong second byte", "[utf8]" )
{
error err;
nchar c;
utf8_to_nchr(&c, "\xce\xff", &err);
string *expected = nstr("Byte 2 in UTF-8 sequence invalid: 0xff", nil);
string *actual = errmsg(&err);
REQUIRE( c == '\0' );
REQUIRE( errnum(&err) == EINVAL );
REQUIRE( nstreq(expected, actual, nil) );
errput(&err);
}
TEST_CASE( "Error on wrong third byte", "[utf8]" )
{
error err;
nchar c;
utf8_to_nchr(&c, "\xe3\x81\xff", &err);
string *expected = nstr("Byte 3 in UTF-8 sequence invalid: 0xff", nil);
string *actual = errmsg(&err);
REQUIRE( c == '\0' );
REQUIRE( errnum(&err) == EINVAL );
REQUIRE( nstreq(expected, actual, nil) );
errput(&err);
}
TEST_CASE( "Error on wrong fourth byte", "[utf8]" )
{
error err;
nchar c;
utf8_to_nchr(&c, "\xf0\x9f\xa5\xff", &err);
string *expected = nstr("Byte 4 in UTF-8 sequence invalid: 0xff", nil);
string *actual = errmsg(&err);
REQUIRE( c == '\0' );
REQUIRE( errnum(&err) == EINVAL );
REQUIRE( nstreq(expected, actual, nil) );
errput(&err);
}
TEST_CASE( "Error on non canonical encoding", "[utf8]" )
{
error err;
nchar c;
utf8_to_nchr(&c, "\xf0\x80\x80\xa0", &err);
string *expected = nstr("Non canonical UTF-8 encoding: 1 byte character stored in 4 bytes", nil);
string *actual = errmsg(&err);
REQUIRE( c == '\0' );
REQUIRE( errnum(&err) == EINVAL );
REQUIRE( nstreq(expected, actual, 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.
*/