string: add static NSTR_DEFINE initializer macro
This commit is contained in:
parent
0bafd7d9b7
commit
b6659a321d
7 changed files with 120 additions and 15 deletions
|
@ -33,20 +33,11 @@
|
|||
})
|
||||
|
||||
/**
|
||||
* Declare a length field in a structure.
|
||||
* This makes it compatible with the `nlen` macro.
|
||||
* Quickly get the length (as in amount of items, not bytes) of any libneo data
|
||||
* structure that supports it. This includes strings, buffers, lists, and more.
|
||||
*
|
||||
* @param name: field name, will be of type `usize`
|
||||
*/
|
||||
#define NLEN_FIELD(name) \
|
||||
union { \
|
||||
usize name; \
|
||||
const usize __neo_nlen; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickly get the length (as a `const usize`) of any libneo data structure
|
||||
* that supports it. This includes strings, buffers, lists, and more.
|
||||
* @param thing: Thing to get the length of
|
||||
* @returns: The length as a `const usize`
|
||||
*/
|
||||
#define nlen(thing) ((thing)->__neo_nlen)
|
||||
|
||||
|
|
|
@ -5,6 +5,33 @@
|
|||
#include "neo/_types.h"
|
||||
#include "neo/_toolchain.h"
|
||||
|
||||
/**
|
||||
* Used internally for statically initializing strings created with
|
||||
* the `NSTR_DEFINE` macro. This is written to a special data section that
|
||||
* is iterated over before program start; see `_neo_nstr_init_array` in
|
||||
* `src/string/nstr.c` for details.
|
||||
*/
|
||||
struct _neo_nstr_init_info {
|
||||
string **dest;
|
||||
const char *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Statically define a neo string.
|
||||
*
|
||||
* The string will be initialized before `main` is called.
|
||||
*
|
||||
* @param name: Name of the `string *` variable to be declared
|
||||
* @param content: A `const char *` with the contents of the string
|
||||
*/
|
||||
#define NSTR_DEFINE(name, content) \
|
||||
string *name = nil; \
|
||||
__neo_section(.data.__neo.nstr_array) \
|
||||
struct _neo_nstr_init_info __neo_nstr_init_info_##name = { \
|
||||
.dest = &name, \
|
||||
.data = content, \
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a regular C string to a neo string.
|
||||
*
|
||||
|
|
|
@ -37,6 +37,18 @@ typedef long double f128;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Declare a length field in a structure.
|
||||
* This makes it compatible with the `nlen` macro.
|
||||
*
|
||||
* @param name: field name, will be of type `usize`
|
||||
*/
|
||||
#define NLEN_FIELD(name) \
|
||||
union { \
|
||||
usize name; \
|
||||
const usize __neo_nlen; \
|
||||
}
|
||||
|
||||
struct _neo_nref {
|
||||
void (*_destroy)(void *);
|
||||
/** byte offset into the struct this is embedded in */
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
add_library(neo STATIC)
|
||||
|
||||
add_compile_options(-nodefaultlibs)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
target_link_options(neo INTERFACE -T${CMAKE_SOURCE_DIR}/src/neo.ld)
|
||||
|
||||
execute_process(COMMAND uname -m OUTPUT_VARIABLE HOST_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
string(TOLOWER "${HOST_ARCH}" HOST_ARCH)
|
||||
|
@ -26,6 +25,7 @@ target_include_directories(neo PRIVATE
|
|||
|
||||
target_sources(neo PRIVATE
|
||||
./error.c
|
||||
./list.c
|
||||
./nalloc.c
|
||||
./nref.c
|
||||
)
|
||||
|
|
40
src/neo.ld
Normal file
40
src/neo.ld
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
/*
|
||||
* The INSERT command at the end makes this linker script merely augment the
|
||||
* default one rather than entirely replace it. This allows us to inject
|
||||
* arbitrary extra sections we can reference in init and fini code without
|
||||
* having to maintain a complete linker script for each architecture.
|
||||
*/
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.__neo_data :
|
||||
{
|
||||
/*
|
||||
* global strings defined with the NSTR_DEFINE macro are
|
||||
* referenced in this section because their length cannot be
|
||||
* calculated at compile time (because UTF-8).
|
||||
*
|
||||
* See nstr_init_array() in src/string/nstr.c for the
|
||||
* initialization routine.
|
||||
*/
|
||||
__neo_nstr_array_start = .;
|
||||
KEEP(*(.data.__neo.nstr_array))
|
||||
__neo_nstr_array_end = .;
|
||||
}
|
||||
}
|
||||
INSERT AFTER .data;
|
||||
|
||||
/*
|
||||
* 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 @@
|
|||
#include "neo/_nalloc.h"
|
||||
#include "neo/_nref.h"
|
||||
#include "neo/_string.h"
|
||||
#include "neo/_toolchain.h"
|
||||
#include "neo/_types.h"
|
||||
#include "neo/utf.h"
|
||||
|
||||
|
@ -108,6 +109,20 @@ nchar nchrat(const string *s, usize index, error *err)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* see src/neo.ld */
|
||||
extern struct _neo_nstr_init_info __neo_nstr_array_start;
|
||||
extern struct _neo_nstr_init_info __neo_nstr_array_end;
|
||||
|
||||
void _neo_nstr_init_array(void)
|
||||
{
|
||||
struct _neo_nstr_init_info *ptr = &__neo_nstr_array_start;
|
||||
while (ptr != &__neo_nstr_array_end) {
|
||||
*ptr->dest = nstr(ptr->data, nil);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
__neo_init(_neo_nstr_init_array);
|
||||
|
||||
/*
|
||||
* This file is part of libneo.
|
||||
* Copyright (c) 2021 Fefie <owo@fef.moe>.
|
||||
|
|
|
@ -60,6 +60,26 @@ TEST_CASE( "nnstr: Error if raw strig is nil", "[string/nstr,c]")
|
|||
errput(&err);
|
||||
}
|
||||
|
||||
NSTR_DEFINE(static_test_string_1, "i'm gay,,,");
|
||||
|
||||
TEST_CASE( "_neo_nstr_init_array: Statically initialize ASCII string", "[string/nstr.c]" )
|
||||
{
|
||||
string *expected_s1 = nstr("i'm gay,,,", nil);
|
||||
|
||||
REQUIRE( nstreq(expected_s1, static_test_string_1, nil) );
|
||||
REQUIRE( nlen(static_test_string_1) == 10 );
|
||||
}
|
||||
|
||||
NSTR_DEFINE(static_test_string_2, "i'm gay\xf0\x9f\xa5\xba,,,");
|
||||
|
||||
TEST_CASE( "_neo_nstr_init_array: Statically initialize UTF-8 string", "[string/nstr.c]" )
|
||||
{
|
||||
string *expected_s2 = nstr("i'm gay\xf0\x9f\xa5\xba,,,", nil);
|
||||
|
||||
REQUIRE( nstreq(expected_s2, static_test_string_2, nil) );
|
||||
REQUIRE( nlen(static_test_string_2) == 11 );
|
||||
}
|
||||
|
||||
/*
|
||||
* This file is part of libneo.
|
||||
* Copyright (c) 2021 Fefie <owo@fef.moe>.
|
||||
|
|
Loading…
Reference in a new issue