diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | include/zix/attributes.h | 8 | ||||
-rw-r--r-- | include/zix/string_view.h | 107 | ||||
-rw-r--r-- | include/zix/zix.h | 1 | ||||
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | src/string_view.c | 18 | ||||
-rw-r--r-- | test/headers/test_headers.c | 1 |
7 files changed, 136 insertions, 5 deletions
@@ -1,4 +1,4 @@ -zix (0.2.0) unstable; urgency=medium +zix (0.3.0) unstable; urgency=medium * Initial release diff --git a/include/zix/attributes.h b/include/zix/attributes.h index 1fe1183..b076fa7 100644 --- a/include/zix/attributes.h +++ b/include/zix/attributes.h @@ -34,13 +34,15 @@ // GCC function attributes #ifdef __GNUC__ +# define ZIX_ALWAYS_INLINE_FUNC __attribute__((always_inline)) # define ZIX_PURE_FUNC __attribute__((pure)) # define ZIX_CONST_FUNC __attribute__((const)) # define ZIX_MALLOC_FUNC __attribute__((malloc)) #else -# define ZIX_PURE_FUNC ///< Only reads memory -# define ZIX_CONST_FUNC ///< Only reads its parameters -# define ZIX_MALLOC_FUNC ///< Allocates memory +# define ZIX_ALWAYS_INLINE_FUNC ///< Should absolutely always be inlined +# define ZIX_PURE_FUNC ///< Only reads memory +# define ZIX_CONST_FUNC ///< Only reads its parameters +# define ZIX_MALLOC_FUNC ///< Allocates memory #endif /// A pure function in the public API that only reads memory diff --git a/include/zix/string_view.h b/include/zix/string_view.h new file mode 100644 index 0000000..f4cd6c2 --- /dev/null +++ b/include/zix/string_view.h @@ -0,0 +1,107 @@ +// Copyright 2011-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#ifndef ZIX_STRING_VIEW_H +#define ZIX_STRING_VIEW_H + +#include "zix/allocator.h" +#include "zix/attributes.h" + +#include <stddef.h> +#include <string.h> + +ZIX_BEGIN_DECLS + +/** + @defgroup zix_string_view String View + @ingroup zix_utilities + @{ +*/ + +/** + An immutable slice of a string. + + This type is used for many string parameters, to allow referring to slices + of strings in-place and to avoid redundant string measurement. +*/ +typedef struct { + const char* ZIX_NONNULL data; ///< Pointer to the first character + size_t length; ///< Length of string in bytes +} ZixStringView; + +/// Return a view of an empty string +ZIX_ALWAYS_INLINE_FUNC +ZIX_CONST_FUNC +static inline ZixStringView +zix_empty_string(void) +{ + const ZixStringView view = {"", 0U}; + return view; +} + +/** + Return a view of a substring, or a premeasured string. + + This makes either a view of a slice of a string (which may not be null + terminated), or a view of a string that has already been measured. This is + faster than zix_string() for dynamic strings since it does not call + `strlen`, so should be used when the length of the string is already known. + + @param str Pointer to the start of the substring. + + @param len Length of the substring in bytes, not including the trailing null + terminator if present. +*/ +ZIX_ALWAYS_INLINE_FUNC +ZIX_CONST_FUNC +static inline ZixStringView +zix_substring(const char* const ZIX_NONNULL str, const size_t len) +{ + const ZixStringView view = {str, len}; + return view; +} + +/** + Return a view of an entire string by measuring it. + + This makes a view of the given string by measuring it with `strlen`. + + @param str Pointer to the start of a null-terminated C string, or null. +*/ +ZIX_ALWAYS_INLINE_FUNC +ZIX_PURE_FUNC +static inline ZixStringView +zix_string(const char* const ZIX_NONNULL str) +{ + const ZixStringView view = {str, strlen(str)}; + return view; +} + +/** + Return a view of an entire string by measuring it. + + This makes a view of the given string by measuring it with `strlen`. + + @param str Pointer to the start of a null-terminated C string, or null. +*/ +ZIX_PURE_FUNC +static inline ZixStringView +zix_optional_string(const char* const ZIX_NULLABLE str) +{ + return str ? zix_string(str) : zix_empty_string(); +} + +/** + Copy a string view into a newly allocated null-terminated string. +*/ +ZIX_API +char* ZIX_ALLOCATED +zix_string_view_copy(ZixAllocator* ZIX_NULLABLE allocator, ZixStringView view); + +/** + @} +*/ + +ZIX_END_DECLS + +#endif // ZIX_STRING_VIEW_H diff --git a/include/zix/zix.h b/include/zix/zix.h index 02ab31f..223d1dc 100644 --- a/include/zix/zix.h +++ b/include/zix/zix.h @@ -20,6 +20,7 @@ #include "zix/digest.h" #include "zix/function_types.h" #include "zix/status.h" +#include "zix/string_view.h" /** @} diff --git a/meson.build b/meson.build index c56a10e..9a64ba6 100644 --- a/meson.build +++ b/meson.build @@ -2,7 +2,7 @@ # SPDX-License-Identifier: 0BSD OR ISC project('zix', ['c'], - version: '0.2.0', + version: '0.3.0', license: 'ISC', meson_version: '>= 0.56.0', default_options: [ @@ -103,6 +103,7 @@ c_headers = files( 'include/zix/ring.h', 'include/zix/sem.h', 'include/zix/status.h', + 'include/zix/string_view.h', 'include/zix/thread.h', 'include/zix/tree.h', 'include/zix/zix.h', @@ -118,6 +119,7 @@ sources = files( 'src/hash.c', 'src/ring.c', 'src/status.c', + 'src/string_view.c', 'src/tree.c', ) diff --git a/src/string_view.c b/src/string_view.c new file mode 100644 index 0000000..9d98258 --- /dev/null +++ b/src/string_view.c @@ -0,0 +1,18 @@ +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#include "zix/string_view.h" +#include "zix/allocator.h" + +#include <string.h> + +char* +zix_string_view_copy(ZixAllocator* const allocator, const ZixStringView view) +{ + char* const copy = (char*)zix_malloc(allocator, view.length + 1U); + if (copy) { + memcpy(copy, view.data, view.length); + copy[view.length] = '\0'; + } + return copy; +} diff --git a/test/headers/test_headers.c b/test/headers/test_headers.c index c1a9fc3..dc580ea 100644 --- a/test/headers/test_headers.c +++ b/test/headers/test_headers.c @@ -12,6 +12,7 @@ #include "zix/ring.h" // IWYU pragma: keep #include "zix/sem.h" // IWYU pragma: keep #include "zix/status.h" // IWYU pragma: keep +#include "zix/string_view.h" // IWYU pragma: keep #include "zix/thread.h" // IWYU pragma: keep #include "zix/tree.h" // IWYU pragma: keep #include "zix/zix.h" // IWYU pragma: keep |