summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/zix/allocator.h13
-rw-r--r--include/zix/attributes.h16
-rw-r--r--include/zix/btree.h58
-rw-r--r--include/zix/bump_allocator.h7
-rw-r--r--include/zix/digest.h20
-rw-r--r--include/zix/environment.h39
-rw-r--r--include/zix/filesystem.h82
-rw-r--r--include/zix/hash.h72
-rw-r--r--include/zix/path.h74
-rw-r--r--include/zix/ring.h124
-rw-r--r--include/zix/sem.h32
-rw-r--r--include/zix/status.h5
-rw-r--r--include/zix/string_view.h32
-rw-r--r--include/zix/thread.h10
-rw-r--r--include/zix/tree.h59
-rw-r--r--include/zix/zix.h38
16 files changed, 344 insertions, 337 deletions
diff --git a/include/zix/allocator.h b/include/zix/allocator.h
index 619697e..5e796ff 100644
--- a/include/zix/allocator.h
+++ b/include/zix/allocator.h
@@ -4,7 +4,7 @@
#ifndef ZIX_ALLOCATOR_H
#define ZIX_ALLOCATOR_H
-#include "zix/attributes.h"
+#include <zix/attributes.h>
#include <stddef.h>
@@ -103,12 +103,11 @@ struct ZixAllocatorImpl {
};
/// Return the default allocator which simply uses the system allocator
-ZIX_CONST_API
-ZixAllocator* ZIX_NONNULL
+ZIX_CONST_API ZixAllocator* ZIX_NONNULL
zix_default_allocator(void);
/// Convenience wrapper that defers to malloc() if allocator is null
-static inline void* ZIX_ALLOCATED
+ZIX_MALLOC_FUNC static inline void* ZIX_ALLOCATED
zix_malloc(ZixAllocator* const ZIX_NULLABLE allocator, const size_t size)
{
ZixAllocator* const actual = allocator ? allocator : zix_default_allocator();
@@ -117,7 +116,7 @@ zix_malloc(ZixAllocator* const ZIX_NULLABLE allocator, const size_t size)
}
/// Convenience wrapper that defers to calloc() if allocator is null
-static inline void* ZIX_ALLOCATED
+ZIX_MALLOC_FUNC static inline void* ZIX_ALLOCATED
zix_calloc(ZixAllocator* const ZIX_NULLABLE allocator,
const size_t nmemb,
const size_t size)
@@ -128,7 +127,7 @@ zix_calloc(ZixAllocator* const ZIX_NULLABLE allocator,
}
/// Convenience wrapper that defers to realloc() if allocator is null
-static inline void* ZIX_ALLOCATED
+ZIX_NODISCARD static inline void* ZIX_ALLOCATED
zix_realloc(ZixAllocator* const ZIX_NULLABLE allocator,
void* const ZIX_NULLABLE ptr,
const size_t size)
@@ -149,7 +148,7 @@ zix_free(ZixAllocator* const ZIX_NULLABLE allocator,
}
/// Convenience wrapper that defers to the system allocator if allocator is null
-static inline void* ZIX_ALLOCATED
+ZIX_MALLOC_FUNC static inline void* ZIX_ALLOCATED
zix_aligned_alloc(ZixAllocator* const ZIX_NULLABLE allocator,
const size_t alignment,
const size_t size)
diff --git a/include/zix/attributes.h b/include/zix/attributes.h
index 518e5fb..f92f2b0 100644
--- a/include/zix/attributes.h
+++ b/include/zix/attributes.h
@@ -38,27 +38,23 @@
# define ZIX_PURE_FUNC __attribute__((pure))
# define ZIX_CONST_FUNC __attribute__((const))
# define ZIX_MALLOC_FUNC __attribute__((malloc))
+# define ZIX_NODISCARD __attribute__((warn_unused_result))
#else
# 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
+# define ZIX_MALLOC_FUNC ///< Allocates memory with no pointers in it
+# define ZIX_NODISCARD ///< Returns a value that must be used
#endif
/// A pure function in the public API that only reads memory
-#define ZIX_PURE_API \
- ZIX_API \
- ZIX_PURE_FUNC
+#define ZIX_PURE_API ZIX_API ZIX_PURE_FUNC ZIX_NODISCARD
/// A const function in the public API that is pure and only reads parameters
-#define ZIX_CONST_API \
- ZIX_API \
- ZIX_CONST_FUNC
+#define ZIX_CONST_API ZIX_API ZIX_CONST_FUNC ZIX_NODISCARD
/// A malloc function in the public API that returns allocated memory
-#define ZIX_MALLOC_API \
- ZIX_API \
- ZIX_MALLOC_FUNC
+#define ZIX_MALLOC_API ZIX_API ZIX_MALLOC_FUNC ZIX_NODISCARD
// Printf-like format functions
#ifdef __GNUC__
diff --git a/include/zix/btree.h b/include/zix/btree.h
index 3161817..859e092 100644
--- a/include/zix/btree.h
+++ b/include/zix/btree.h
@@ -4,9 +4,9 @@
#ifndef ZIX_BTREE_H
#define ZIX_BTREE_H
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/status.h>
#include <stdbool.h>
#include <stddef.h>
@@ -21,7 +21,7 @@ ZIX_BEGIN_DECLS
*/
/**
- @defgroup zix_btree_setup Setup
+ @defgroup zix_btree_types Types
@{
*/
@@ -51,6 +51,12 @@ typedef void (*ZixBTreeDestroyFunc)(void* ZIX_UNSPECIFIED ptr,
const void* ZIX_UNSPECIFIED user_data);
/**
+ @}
+ @defgroup zix_btree_setup Setup
+ @{
+*/
+
+/**
Create a new (empty) B-Tree.
The given comparator must be a total ordering and is used to internally
@@ -59,8 +65,7 @@ typedef void (*ZixBTreeDestroyFunc)(void* ZIX_UNSPECIFIED ptr,
Searching can be done with a custom comparator that supports wildcards, see
zix_btree_lower_bound() for details.
*/
-ZIX_API
-ZixBTree* ZIX_ALLOCATED
+ZIX_API ZIX_NODISCARD ZixBTree* ZIX_ALLOCATED
zix_btree_new(ZixAllocator* ZIX_NULLABLE allocator,
ZixBTreeCompareFunc ZIX_NONNULL cmp,
const void* ZIX_UNSPECIFIED cmp_data);
@@ -75,8 +80,7 @@ zix_btree_new(ZixAllocator* ZIX_NULLABLE allocator,
@param destroy_data Opaque user data pointer to pass to `destroy`.
*/
-ZIX_API
-void
+ZIX_API void
zix_btree_free(ZixBTree* ZIX_NULLABLE t,
ZixBTreeDestroyFunc ZIX_NULLABLE destroy,
const void* ZIX_NULLABLE destroy_data);
@@ -91,15 +95,13 @@ zix_btree_free(ZixBTree* ZIX_NULLABLE t,
@param destroy_data Opaque user data pointer to pass to `destroy`.
*/
-ZIX_API
-void
+ZIX_API void
zix_btree_clear(ZixBTree* ZIX_NONNULL t,
ZixBTreeDestroyFunc ZIX_NULLABLE destroy,
const void* ZIX_NULLABLE destroy_data);
/// Return the number of elements in `t`
-ZIX_PURE_API
-size_t
+ZIX_PURE_API size_t
zix_btree_size(const ZixBTree* ZIX_NONNULL t);
/**
@@ -134,40 +136,34 @@ static const ZixBTreeIter zix_btree_end_iter = {
};
/// Return the data at the given position in the tree
-ZIX_PURE_API
-void* ZIX_UNSPECIFIED
+ZIX_PURE_API void* ZIX_UNSPECIFIED
zix_btree_get(ZixBTreeIter ti);
/// Return an iterator to the first (smallest) element in `t`
-ZIX_PURE_API
-ZixBTreeIter
+ZIX_PURE_API ZixBTreeIter
zix_btree_begin(const ZixBTree* ZIX_NONNULL t);
/// Return an iterator to the end of `t` (one past the last element)
-ZIX_CONST_API
-ZixBTreeIter
+ZIX_CONST_API ZixBTreeIter
zix_btree_end(const ZixBTree* ZIX_NULLABLE t);
/// Return true iff `lhs` is equal to `rhs`
-ZIX_CONST_API
-bool
+ZIX_CONST_API bool
zix_btree_iter_equals(ZixBTreeIter lhs, ZixBTreeIter rhs);
/// Return true iff `i` is an iterator at the end of a tree
-static inline bool
+ZIX_NODISCARD static inline bool
zix_btree_iter_is_end(const ZixBTreeIter i)
{
return i.level == 0 && !i.nodes[0];
}
/// Increment `i` to point to the next element in the tree
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_btree_iter_increment(ZixBTreeIter* ZIX_NONNULL i);
/// Return an iterator one past `iter`
-ZIX_API
-ZixBTreeIter
+ZIX_API ZIX_NODISCARD ZixBTreeIter
zix_btree_iter_next(ZixBTreeIter iter);
/**
@@ -182,8 +178,7 @@ zix_btree_iter_next(ZixBTreeIter iter);
@return #ZIX_STATUS_SUCCESS on success, #ZIX_STATUS_EXISTS, or
#ZIX_STATUS_NO_MEM.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_btree_insert(ZixBTree* ZIX_NONNULL t, void* ZIX_UNSPECIFIED e);
/**
@@ -200,8 +195,7 @@ zix_btree_insert(ZixBTree* ZIX_NONNULL t, void* ZIX_UNSPECIFIED e);
@return #ZIX_STATUS_SUCCESS on success, or #ZIX_STATUS_NOT_FOUND.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_btree_remove(ZixBTree* ZIX_NONNULL t,
const void* ZIX_UNSPECIFIED e,
void* ZIX_UNSPECIFIED* ZIX_NONNULL out,
@@ -220,8 +214,7 @@ zix_btree_remove(ZixBTree* ZIX_NONNULL t,
@return #ZIX_STATUS_SUCCESS on success, or #ZIX_STATUS_NOT_FOUND.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_btree_find(const ZixBTree* ZIX_NONNULL t,
const void* ZIX_UNSPECIFIED e,
ZixBTreeIter* ZIX_NONNULL ti);
@@ -242,8 +235,7 @@ zix_btree_find(const ZixBTree* ZIX_NONNULL t,
@return #ZIX_STATUS_SUCCESS.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_btree_lower_bound(const ZixBTree* ZIX_NONNULL t,
ZixBTreeCompareFunc ZIX_NULLABLE compare_key,
const void* ZIX_NULLABLE compare_key_data,
diff --git a/include/zix/bump_allocator.h b/include/zix/bump_allocator.h
index c69de92..b5fdd7e 100644
--- a/include/zix/bump_allocator.h
+++ b/include/zix/bump_allocator.h
@@ -4,8 +4,8 @@
#ifndef ZIX_BUMP_ALLOCATOR_H
#define ZIX_BUMP_ALLOCATOR_H
-#include "zix/allocator.h"
-#include "zix/attributes.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
#include <stddef.h>
@@ -52,8 +52,7 @@ typedef struct {
} ZixBumpAllocator;
/// Return a bump allocator that works within a provided buffer
-ZIX_API
-ZixBumpAllocator
+ZIX_API ZixBumpAllocator
zix_bump_allocator(size_t capacity, void* ZIX_NONNULL buffer);
/**
diff --git a/include/zix/digest.h b/include/zix/digest.h
index deffaf0..82f5b28 100644
--- a/include/zix/digest.h
+++ b/include/zix/digest.h
@@ -4,7 +4,7 @@
#ifndef ZIX_DIGEST_H
#define ZIX_DIGEST_H
-#include "zix/attributes.h"
+#include <zix/attributes.h>
#include <stddef.h>
#include <stdint.h>
@@ -29,8 +29,7 @@ ZIX_BEGIN_DECLS
This can be used for any size or alignment.
*/
-ZIX_PURE_API
-uint32_t
+ZIX_PURE_API uint32_t
zix_digest32(uint32_t seed, const void* ZIX_NONNULL buf, size_t len);
/**
@@ -39,8 +38,7 @@ zix_digest32(uint32_t seed, const void* ZIX_NONNULL buf, size_t len);
Both the buffer and size must be aligned to 32 bits. For data that fits
these requirements, this is equivalent to, but faster than, zix_digest32().
*/
-ZIX_PURE_API
-uint32_t
+ZIX_PURE_API uint32_t
zix_digest32_aligned(uint32_t seed, const void* ZIX_NONNULL buf, size_t len);
/**
@@ -48,8 +46,7 @@ zix_digest32_aligned(uint32_t seed, const void* ZIX_NONNULL buf, size_t len);
This can be used for any size or alignment.
*/
-ZIX_PURE_API
-uint64_t
+ZIX_PURE_API uint64_t
zix_digest64(uint64_t seed, const void* ZIX_NONNULL buf, size_t len);
/**
@@ -58,8 +55,7 @@ zix_digest64(uint64_t seed, const void* ZIX_NONNULL buf, size_t len);
Both the buffer and size must be aligned to 64 bits. For data that fits
these requirements, this is equivalent to, but faster than, zix_digest64().
*/
-ZIX_PURE_API
-uint64_t
+ZIX_PURE_API uint64_t
zix_digest64_aligned(uint64_t seed, const void* ZIX_NONNULL buf, size_t len);
/**
@@ -70,8 +66,7 @@ zix_digest64_aligned(uint64_t seed, const void* ZIX_NONNULL buf, size_t len);
Internally, this simply dispatches to zix_digest32() or zix_digest64() as
appropriate.
*/
-ZIX_PURE_API
-size_t
+ZIX_PURE_API size_t
zix_digest(size_t seed, const void* ZIX_NONNULL buf, size_t len);
/**
@@ -84,8 +79,7 @@ zix_digest(size_t seed, const void* ZIX_NONNULL buf, size_t len);
Internally, this simply dispatches to zix_digest32_aligned() or
zix_digest64_aligned() as appropriate.
*/
-ZIX_PURE_API
-size_t
+ZIX_PURE_API size_t
zix_digest_aligned(size_t seed, const void* ZIX_NONNULL buf, size_t len);
/**
diff --git a/include/zix/environment.h b/include/zix/environment.h
new file mode 100644
index 0000000..095d421
--- /dev/null
+++ b/include/zix/environment.h
@@ -0,0 +1,39 @@
+// Copyright 2024 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#ifndef ZIX_ENVIRONMENT_H
+#define ZIX_ENVIRONMENT_H
+
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+
+ZIX_BEGIN_DECLS
+
+/**
+ @defgroup zix_expand Variable Expansion
+ @ingroup zix_environment
+ @{
+*/
+
+/**
+ Expand shell-style variables in a string.
+
+ On Windows, this expands environment variable references like
+ "%USERPROFILE%". On POSIX systems, it expands environment variable
+ references like "$HOME", and the special path component "~".
+
+ @param allocator Allocator used for returned string.
+ @param string Input string to expand.
+ @return A newly allocated copy of `string` with variables expanded, or null.
+*/
+ZIX_MALLOC_API char* ZIX_ALLOCATED
+zix_expand_environment_strings(ZixAllocator* ZIX_NULLABLE allocator,
+ const char* ZIX_NONNULL string);
+
+/**
+ @}
+*/
+
+ZIX_END_DECLS
+
+#endif /* ZIX_ENVIRONMENT_H */
diff --git a/include/zix/filesystem.h b/include/zix/filesystem.h
index 9abafe1..dff4145 100644
--- a/include/zix/filesystem.h
+++ b/include/zix/filesystem.h
@@ -4,9 +4,9 @@
#ifndef ZIX_FILESYSTEM_H
#define ZIX_FILESYSTEM_H
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/status.h>
#if !(defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
# include <stddef.h>
@@ -51,8 +51,7 @@ typedef uint32_t ZixCopyOptions;
@param options Options to control the kind of copy and error conditions.
@return #ZIX_STATUS_SUCCESS if `dst` was successfully created, or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_copy_file(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NONNULL src,
const char* ZIX_NONNULL dst,
@@ -64,8 +63,7 @@ zix_copy_file(ZixAllocator* ZIX_NULLABLE allocator,
@return #ZIX_STATUS_SUCCESS if `dir_path` was successfully created, or an
error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_create_directory(const char* ZIX_NONNULL dir_path);
/**
@@ -77,8 +75,7 @@ zix_create_directory(const char* ZIX_NONNULL dir_path);
@return #ZIX_STATUS_SUCCESS if `dir_path` was successfully created, or an
error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_create_directory_like(const char* ZIX_NONNULL dir_path,
const char* ZIX_NONNULL existing_path);
@@ -92,8 +89,7 @@ zix_create_directory_like(const char* ZIX_NONNULL dir_path,
@return #ZIX_STATUS_SUCCESS if all directories in `dir_path` were
successfully created (or already existed), or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_create_directories(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NONNULL dir_path);
@@ -102,8 +98,7 @@ zix_create_directories(ZixAllocator* ZIX_NULLABLE allocator,
@return #ZIX_STATUS_SUCCESS, or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_create_hard_link(const char* ZIX_NONNULL target_path,
const char* ZIX_NONNULL link_path);
@@ -116,8 +111,7 @@ zix_create_hard_link(const char* ZIX_NONNULL target_path,
@return #ZIX_STATUS_SUCCESS, or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_create_symlink(const char* ZIX_NONNULL target_path,
const char* ZIX_NONNULL link_path);
@@ -129,8 +123,7 @@ zix_create_symlink(const char* ZIX_NONNULL target_path,
@return #ZIX_STATUS_SUCCESS, or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_create_directory_symlink(const char* ZIX_NONNULL target_path,
const char* ZIX_NONNULL link_path);
@@ -146,14 +139,12 @@ zix_create_directory_symlink(const char* ZIX_NONNULL target_path,
@return The path of the created directory, or null.
*/
-ZIX_API
-char* ZIX_NULLABLE
+ZIX_MALLOC_API char* ZIX_NULLABLE
zix_create_temporary_directory(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NONNULL path_pattern);
/// Remove the file or empty directory at `path`
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_remove(const char* ZIX_NONNULL path);
/**
@@ -163,6 +154,17 @@ zix_remove(const char* ZIX_NONNULL path);
*/
/**
+ Function for reading input bytes from a stream.
+
+ @param path Path to the directory being visited.
+ @param name Name of the directory entry.
+ @param data Opaque user data.
+*/
+typedef void (*ZixDirEntryVisitFunc)(const char* ZIX_NONNULL path,
+ const char* ZIX_NONNULL name,
+ void* ZIX_NONNULL data);
+
+/**
Visit every file in the directory at `path`.
@param path A path to a directory.
@@ -173,13 +175,10 @@ zix_remove(const char* ZIX_NONNULL path);
parameter is always the directory path passed to this function, the `name`
parameter is the name of the directory entry (not its full path).
*/
-ZIX_API
-void
-zix_dir_for_each(const char* ZIX_NONNULL path,
- void* ZIX_NULLABLE data,
- void (*ZIX_NONNULL f)(const char* ZIX_NONNULL path,
- const char* ZIX_NONNULL name,
- void* ZIX_NONNULL data));
+ZIX_API void
+zix_dir_for_each(const char* ZIX_NONNULL path,
+ void* ZIX_NULLABLE data,
+ ZixDirEntryVisitFunc ZIX_NONNULL f);
/**
Return whether the given paths point to files with identical contents.
@@ -193,8 +192,7 @@ zix_dir_for_each(const char* ZIX_NONNULL path,
@return True if the two files have byte-for-byte identical contents.
*/
-ZIX_API
-bool
+ZIX_API ZIX_NODISCARD bool
zix_file_equals(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NONNULL a_path,
const char* ZIX_NONNULL b_path);
@@ -227,8 +225,7 @@ zix_file_equals(ZixAllocator* ZIX_NULLABLE allocator,
@return A new canonical version of `path`, or null if it doesn't exist.
*/
-ZIX_API
-char* ZIX_NULLABLE
+ZIX_MALLOC_API char* ZIX_NULLABLE
zix_canonical_path(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NULLABLE path);
@@ -255,8 +252,7 @@ typedef enum {
@param mode Lock mode.
@return #ZIX_STATUS_SUCCESS if the file was locked, or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_file_lock(FILE* ZIX_NONNULL file, ZixFileLockMode mode);
/**
@@ -266,8 +262,7 @@ zix_file_lock(FILE* ZIX_NONNULL file, ZixFileLockMode mode);
@param mode Lock mode.
@return #ZIX_STATUS_SUCCESS if the file was unlocked, or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_file_unlock(FILE* ZIX_NONNULL file, ZixFileLockMode mode);
/**
@@ -308,8 +303,7 @@ typedef enum {
/**
Return the type of a file or directory, resolving symlinks.
*/
-ZIX_API
-ZixFileType
+ZIX_API ZixFileType
zix_file_type(const char* ZIX_NONNULL path);
/**
@@ -318,8 +312,7 @@ zix_file_type(const char* ZIX_NONNULL path);
On Windows, a directory symlink (actually a "reparse point") always appears
as a directory.
*/
-ZIX_API
-ZixFileType
+ZIX_API ZixFileType
zix_symlink_type(const char* ZIX_NONNULL path);
/**
@@ -331,8 +324,7 @@ zix_symlink_type(const char* ZIX_NONNULL path);
@return A non-negative size in bytes, or -1 on error.
*/
-ZIX_API
-ZixFileOffset
+ZIX_API ZixFileOffset
zix_file_size(const char* ZIX_NONNULL path);
/**
@@ -346,8 +338,7 @@ zix_file_size(const char* ZIX_NONNULL path);
@param allocator Allocator used for the returned path.
*/
-ZIX_API
-char* ZIX_ALLOCATED
+ZIX_MALLOC_API char* ZIX_ALLOCATED
zix_current_path(ZixAllocator* ZIX_NULLABLE allocator);
/**
@@ -357,8 +348,7 @@ zix_current_path(ZixAllocator* ZIX_NULLABLE allocator);
@return A new path to a temporary directory, or null on error.
*/
-ZIX_API
-char* ZIX_ALLOCATED
+ZIX_MALLOC_API char* ZIX_ALLOCATED
zix_temp_directory_path(ZixAllocator* ZIX_NULLABLE allocator);
/**
diff --git a/include/zix/hash.h b/include/zix/hash.h
index e425b9f..3222e58 100644
--- a/include/zix/hash.h
+++ b/include/zix/hash.h
@@ -4,9 +4,9 @@
#ifndef ZIX_HASH_H
#define ZIX_HASH_H
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/status.h>
#include <stdbool.h>
#include <stddef.h>
@@ -20,7 +20,7 @@ ZIX_BEGIN_DECLS
*/
/**
- @defgroup zix_hash_datatypes Datatypes
+ @defgroup zix_hash_types Types
@{
*/
@@ -28,14 +28,14 @@ ZIX_BEGIN_DECLS
#if defined(ZIX_HASH_KEY_TYPE)
typedef ZIX_HASH_KEY_TYPE ZixHashKey;
#else
-typedef void ZixHashKey; ///< The type of a key within a record
+typedef void ZixHashKey; ///< The type of a key within a record
#endif
// ZIX_HASH_RECORD_TYPE can be defined to make the API more type-safe
#if defined(ZIX_HASH_RECORD_TYPE)
typedef ZIX_HASH_RECORD_TYPE ZixHashRecord;
#else
-typedef void ZixHashRecord; ///< The type of a hash table record
+typedef void ZixHashRecord; ///< The type of a hash table record
#endif
// ZIX_HASH_SEARCH_DATA_TYPE can be defined to make the API more type-safe
@@ -77,12 +77,6 @@ typedef struct ZixHashImpl ZixHash;
/// A full hash code for a key which is not folded down to the table size
typedef size_t ZixHashCode;
-/**
- @}
- @defgroup zix_hash_setup Setup
- @{
-*/
-
/// User function for getting the key of a record
typedef const ZixHashKey* ZIX_NONNULL (*ZixKeyFunc)(
const ZixHashRecord* ZIX_NONNULL record);
@@ -95,6 +89,12 @@ typedef bool (*ZixKeyEqualFunc)(const ZixHashKey* ZIX_NONNULL a,
const ZixHashKey* ZIX_NONNULL b);
/**
+ @}
+ @defgroup zix_hash_setup Setup
+ @{
+*/
+
+/**
Create a new hash table.
@param allocator Allocator used for the internal array.
@@ -102,21 +102,18 @@ typedef bool (*ZixKeyEqualFunc)(const ZixHashKey* ZIX_NONNULL a,
@param hash_func The key hashing function.
@param equal_func A function to test keys for equality.
*/
-ZIX_API
-ZixHash* ZIX_ALLOCATED
+ZIX_API ZIX_NODISCARD ZixHash* ZIX_ALLOCATED
zix_hash_new(ZixAllocator* ZIX_NULLABLE allocator,
ZixKeyFunc ZIX_NONNULL key_func,
ZixHashFunc ZIX_NONNULL hash_func,
ZixKeyEqualFunc ZIX_NONNULL equal_func);
/// Free `hash`
-ZIX_API
-void
+ZIX_API void
zix_hash_free(ZixHash* ZIX_NULLABLE hash);
/// Return the number of elements in the hash
-ZIX_PURE_API
-size_t
+ZIX_PURE_API size_t
zix_hash_size(const ZixHash* ZIX_NONNULL hash);
/**
@@ -134,23 +131,19 @@ zix_hash_size(const ZixHash* ZIX_NONNULL hash);
typedef size_t ZixHashIter;
/// Return an iterator to the first record in a hash, or the end if it is empty
-ZIX_PURE_API
-ZixHashIter
+ZIX_PURE_API ZixHashIter
zix_hash_begin(const ZixHash* ZIX_NONNULL hash);
/// Return an iterator one past the last possible record in a hash
-ZIX_PURE_API
-ZixHashIter
+ZIX_PURE_API ZixHashIter
zix_hash_end(const ZixHash* ZIX_NONNULL hash);
/// Return the record pointed to by an iterator
-ZIX_PURE_API
-ZixHashRecord* ZIX_NULLABLE
+ZIX_PURE_API ZixHashRecord* ZIX_NULLABLE
zix_hash_get(const ZixHash* ZIX_NONNULL hash, ZixHashIter i);
/// Return an iterator that has been advanced to the next record in a hash
-ZIX_PURE_API
-ZixHashIter
+ZIX_PURE_API ZixHashIter
zix_hash_next(const ZixHash* ZIX_NONNULL hash, ZixHashIter i);
/**
@@ -188,8 +181,7 @@ typedef struct {
record with this key using zix_hash_insert_at() until the hash table is
modified (which invalidates the position).
*/
-ZIX_API
-ZixHashInsertPlan
+ZIX_API ZixHashInsertPlan
zix_hash_plan_insert(const ZixHash* ZIX_NONNULL hash,
const ZixHashKey* ZIX_NONNULL key);
@@ -213,8 +205,7 @@ zix_hash_plan_insert(const ZixHash* ZIX_NONNULL hash,
be inserted, and the predicate must return true only if the key it is called
with (the first argument) matches the key to be inserted.
*/
-ZIX_API
-ZixHashInsertPlan
+ZIX_API ZixHashInsertPlan
zix_hash_plan_insert_prehashed(const ZixHash* ZIX_NONNULL hash,
ZixHashCode code,
ZixKeyMatchFunc ZIX_NONNULL predicate,
@@ -227,8 +218,7 @@ zix_hash_plan_insert_prehashed(const ZixHash* ZIX_NONNULL hash,
can be used to insert a new record, or to access the existing matching
record.
*/
-ZIX_PURE_API
-ZixHashRecord* ZIX_NULLABLE
+ZIX_PURE_API ZixHashRecord* ZIX_NULLABLE
zix_hash_record_at(const ZixHash* ZIX_NONNULL hash, ZixHashInsertPlan position);
/**
@@ -248,8 +238,7 @@ zix_hash_record_at(const ZixHash* ZIX_NONNULL hash, ZixHashInsertPlan position);
@return ZIX_STATUS_SUCCESS, ZIX_STATUS_EXISTS if a record already exists at
this position, or ZIX_STATUS_NO_MEM if growing the hash table failed.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_hash_insert_at(ZixHash* ZIX_NONNULL hash,
ZixHashInsertPlan position,
ZixHashRecord* ZIX_NONNULL record);
@@ -268,8 +257,7 @@ zix_hash_insert_at(ZixHash* ZIX_NONNULL hash,
@return ZIX_STATUS_SUCCESS, ZIX_STATUS_EXISTS, or ZIX_STATUS_NO_MEM.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_hash_insert(ZixHash* ZIX_NONNULL hash, ZixHashRecord* ZIX_NONNULL record);
/**
@@ -286,8 +274,7 @@ zix_hash_insert(ZixHash* ZIX_NONNULL hash, ZixHashRecord* ZIX_NONNULL record);
@return ZIX_STATUS_SUCCES or ZIX_STATUS_BAD_ARG if `i` does not point at a
removable record.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_hash_erase(ZixHash* ZIX_NONNULL hash,
ZixHashIter i,
ZixHashRecord* ZIX_NULLABLE* ZIX_NONNULL removed);
@@ -300,8 +287,7 @@ zix_hash_erase(ZixHash* ZIX_NONNULL hash,
@param removed Set to the removed record, or null.
@return ZIX_STATUS_SUCCES or ZIX_STATUS_NOT_FOUND.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_hash_remove(ZixHash* ZIX_NONNULL hash,
const ZixHashKey* ZIX_NONNULL key,
ZixHashRecord* ZIX_NULLABLE* ZIX_NONNULL removed);
@@ -322,8 +308,7 @@ zix_hash_remove(ZixHash* ZIX_NONNULL hash,
@return An iterator to the matching record, or the end iterator if no such
record exists.
*/
-ZIX_API
-ZixHashIter
+ZIX_API ZixHashIter
zix_hash_find(const ZixHash* ZIX_NONNULL hash,
const ZixHashKey* ZIX_NONNULL key);
@@ -339,8 +324,7 @@ zix_hash_find(const ZixHash* ZIX_NONNULL hash,
@return A pointer to the matching record, of null if no such record exists.
*/
-ZIX_API
-ZixHashRecord* ZIX_NULLABLE
+ZIX_API ZixHashRecord* ZIX_NULLABLE
zix_hash_find_record(const ZixHash* ZIX_NONNULL hash,
const ZixHashKey* ZIX_NONNULL key);
diff --git a/include/zix/path.h b/include/zix/path.h
index 13225e6..ba23b10 100644
--- a/include/zix/path.h
+++ b/include/zix/path.h
@@ -4,9 +4,9 @@
#ifndef ZIX_PATH_H
#define ZIX_PATH_H
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/string_view.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/string_view.h>
#include <stdbool.h>
@@ -35,8 +35,7 @@ ZIX_BEGIN_DECLS
*/
/// Join path `a` and path `b` with a single directory separator between them
-ZIX_API
-char* ZIX_ALLOCATED
+ZIX_MALLOC_API ZIX_NODISCARD char* ZIX_ALLOCATED
zix_path_join(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NULLABLE a,
const char* ZIX_NULLABLE b);
@@ -54,8 +53,7 @@ zix_path_join(ZixAllocator* ZIX_NULLABLE allocator,
converted to the preferred separator (backslash on Windows, slash everywhere
else).
*/
-ZIX_API
-char* ZIX_ALLOCATED
+ZIX_MALLOC_API ZIX_NODISCARD char* ZIX_ALLOCATED
zix_path_preferred(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NONNULL path);
@@ -64,14 +62,13 @@ zix_path_preferred(ZixAllocator* ZIX_NULLABLE allocator,
Paths in normal form have all dot segments removed and use only a single
preferred separator for all separators (that is, any number of separators is
- replaced with a single "\" on Windows, and a single "/" everwhere else).
+ replaced with a single "\" on Windows, and a single "/" everywhere else).
Note that this function doesn't access the filesystem, so won't do anything
like case normalization or symbolic link dereferencing. For that, use
zix_canonical_path().
*/
-ZIX_API
-char* ZIX_ALLOCATED
+ZIX_MALLOC_API ZIX_NODISCARD char* ZIX_ALLOCATED
zix_path_lexically_normal(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NONNULL path);
@@ -82,8 +79,7 @@ zix_path_lexically_normal(ZixAllocator* ZIX_NULLABLE allocator,
equivalent path relative to `base` is returned (which may contain
up-references).
*/
-ZIX_API
-char* ZIX_ALLOCATED
+ZIX_MALLOC_API ZIX_NODISCARD char* ZIX_ALLOCATED
zix_path_lexically_relative(ZixAllocator* ZIX_NULLABLE allocator,
const char* ZIX_NONNULL path,
const char* ZIX_NONNULL base);
@@ -95,13 +91,11 @@ zix_path_lexically_relative(ZixAllocator* ZIX_NULLABLE allocator,
*/
/// Return the root name of `path` like "C:", or null
-ZIX_PURE_WIN_API
-ZixStringView
+ZIX_PURE_WIN_API ZixStringView
zix_path_root_name(const char* ZIX_NONNULL path);
/// Return the root directory of `path` like "/" or "\", or null
-ZIX_PURE_API
-ZixStringView
+ZIX_PURE_API ZixStringView
zix_path_root_directory(const char* ZIX_NONNULL path);
/**
@@ -117,8 +111,7 @@ zix_path_root_directory(const char* ZIX_NONNULL path);
@return The newly allocated root path of `path`, or null if it has no root
or allocation failed.
*/
-ZIX_PURE_API
-ZixStringView
+ZIX_PURE_API ZixStringView
zix_path_root_path(const char* ZIX_NONNULL path);
/**
@@ -127,8 +120,7 @@ zix_path_root_path(const char* ZIX_NONNULL path);
If the path has no relative path (because it is empty or a root path), this
returns null.
*/
-ZIX_PURE_API
-ZixStringView
+ZIX_PURE_API ZixStringView
zix_path_relative_path(const char* ZIX_NONNULL path);
/**
@@ -147,8 +139,7 @@ zix_path_relative_path(const char* ZIX_NONNULL path);
@return The newly allocated path to the parent of `path`, or null if it has
no parent or allocation failed.
*/
-ZIX_PURE_API
-ZixStringView
+ZIX_PURE_API ZixStringView
zix_path_parent_path(const char* ZIX_NONNULL path);
/**
@@ -157,8 +148,7 @@ zix_path_parent_path(const char* ZIX_NONNULL path);
The filename is the name after the last directory separator. If the path
has no filename, this returns null.
*/
-ZIX_PURE_API
-ZixStringView
+ZIX_PURE_API ZixStringView
zix_path_filename(const char* ZIX_NONNULL path);
/**
@@ -167,8 +157,7 @@ zix_path_filename(const char* ZIX_NONNULL path);
The "stem" is the filename without the extension, that is, everything up to
the last "." if "." is not the first character.
*/
-ZIX_PURE_API
-ZixStringView
+ZIX_PURE_API ZixStringView
zix_path_stem(const char* ZIX_NONNULL path);
/**
@@ -177,8 +166,7 @@ zix_path_stem(const char* ZIX_NONNULL path);
The "extension" is everything past the last "." in the filename, if "." is
not the first character.
*/
-ZIX_PURE_API
-ZixStringView
+ZIX_PURE_API ZixStringView
zix_path_extension(const char* ZIX_NONNULL path);
/**
@@ -188,53 +176,43 @@ zix_path_extension(const char* ZIX_NONNULL path);
*/
/// Return true if `path` has a root path like "/" or "C:\"
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_has_root_path(const char* ZIX_NULLABLE path);
/// Return true if `path` has a root name like "C:"
-ZIX_PURE_WIN_API
-bool
+ZIX_PURE_WIN_API bool
zix_path_has_root_name(const char* ZIX_NULLABLE path);
/// Return true if `path` has a root directory like "/" or "\"
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_has_root_directory(const char* ZIX_NULLABLE path);
/// Return true if `path` has a relative path "dir/file.txt"
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_has_relative_path(const char* ZIX_NULLABLE path);
/// Return true if `path` has a parent path like "dir/"
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_has_parent_path(const char* ZIX_NULLABLE path);
/// Return true if `path` has a filename like "file.txt"
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_has_filename(const char* ZIX_NULLABLE path);
/// Return true if `path` has a stem like "file"
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_has_stem(const char* ZIX_NULLABLE path);
/// Return true if `path` has an extension like ".txt"
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_has_extension(const char* ZIX_NULLABLE path);
/// Return true if `path` is an absolute path
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_is_absolute(const char* ZIX_NULLABLE path);
/// Return true if `path` is a relative path
-ZIX_PURE_API
-bool
+ZIX_PURE_API bool
zix_path_is_relative(const char* ZIX_NULLABLE path);
/**
diff --git a/include/zix/ring.h b/include/zix/ring.h
index 61c99be..4431658 100644
--- a/include/zix/ring.h
+++ b/include/zix/ring.h
@@ -4,9 +4,9 @@
#ifndef ZIX_RING_H
#define ZIX_RING_H
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/status.h>
#include <stdint.h>
@@ -19,7 +19,7 @@ ZIX_BEGIN_DECLS
*/
/**
- @defgroup zix_ring_setup Setup
+ @defgroup zix_ring_types Types
@{
*/
@@ -32,21 +32,30 @@ ZIX_BEGIN_DECLS
typedef struct ZixRingImpl ZixRing;
/**
+ @}
+ @defgroup zix_ring_setup Setup
+ @{
+*/
+
+/**
Create a new ring.
@param allocator Allocator for the ring object and its array.
- @param size Size of the ring in bytes (note this may be rounded up).
+ @param size Minimum size of the ring in bytes (rounded up to a power of 2).
- At most `size` - 1 bytes may be stored in the ring at once.
+ Note that one byte of the ring is reserved, so in order to be able to write
+ `n` bytes to the ring at once, `size` must be `n + 1`.
*/
-ZIX_MALLOC_API
-ZixRing* ZIX_ALLOCATED
+ZIX_API ZIX_NODISCARD ZixRing* ZIX_ALLOCATED
zix_ring_new(ZixAllocator* ZIX_NULLABLE allocator, uint32_t size);
-/// Destroy a ring
-ZIX_API
-void
+/**
+ Destroy a ring.
+
+ This frees the ring structure and its buffer, discarding its contents.
+*/
+ZIX_API void
zix_ring_free(ZixRing* ZIX_NULLABLE ring);
/**
@@ -56,8 +65,7 @@ zix_ring_free(ZixRing* ZIX_NULLABLE ring);
after zix_ring_new() to lock all ring memory to avoid page faults while
using the ring.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_ring_mlock(ZixRing* ZIX_NONNULL ring);
/**
@@ -66,8 +74,7 @@ zix_ring_mlock(ZixRing* ZIX_NONNULL ring);
This function is NOT thread-safe, it may only be called when there is no
reader or writer.
*/
-ZIX_API
-void
+ZIX_API void
zix_ring_reset(ZixRing* ZIX_NONNULL ring);
/**
@@ -76,8 +83,7 @@ zix_ring_reset(ZixRing* ZIX_NONNULL ring);
This function returns a constant for any given ring, and may (but usually
shouldn't) be called anywhere.
*/
-ZIX_PURE_API
-uint32_t
+ZIX_PURE_API uint32_t
zix_ring_capacity(const ZixRing* ZIX_NONNULL ring);
/**
@@ -87,24 +93,47 @@ zix_ring_capacity(const ZixRing* ZIX_NONNULL ring);
@{
*/
-/// Return the number of bytes available for reading
-ZIX_PURE_API
-uint32_t
+/**
+ Return the number of bytes available for reading.
+
+ This function returns at most one less than the ring's buffer size.
+*/
+ZIX_PURE_API uint32_t
zix_ring_read_space(const ZixRing* ZIX_NONNULL ring);
-/// Read from the ring without advancing the read head
-ZIX_API
-uint32_t
+/**
+ Read from the ring without advancing the read head.
+
+ @param ring The ring to read data from.
+ @param dst The buffer to write data to.
+ @param size The number of bytes to read from `ring` and write to `dst`.
+
+ @return The number of bytes read, which is either `size` on success, or zero
+ on failure.
+*/
+ZIX_API uint32_t
zix_ring_peek(ZixRing* ZIX_NONNULL ring, void* ZIX_NONNULL dst, uint32_t size);
-/// Read from the ring and advance the read head
-ZIX_API
-uint32_t
+/**
+ Read from the ring and advance the read head.
+
+ @param ring The ring to read data from.
+ @param dst The buffer to write data to.
+ @param size The number of bytes to read from `ring` and write to `dst`.
+
+ @return The number of bytes read, which is either `size` on success, or zero
+ on failure.
+*/
+ZIX_API uint32_t
zix_ring_read(ZixRing* ZIX_NONNULL ring, void* ZIX_NONNULL dst, uint32_t size);
-/// Advance the read head, ignoring any data
-ZIX_API
-uint32_t
+/**
+ Advance the read head, ignoring any data.
+
+ @return Either `size` on success, or zero if there aren't enough bytes to
+ skip.
+*/
+ZIX_API uint32_t
zix_ring_skip(ZixRing* ZIX_NONNULL ring, uint32_t size);
/**
@@ -122,20 +151,36 @@ zix_ring_skip(ZixRing* ZIX_NONNULL ring, uint32_t size);
written in several chunks before being "committed" and becoming readable.
This can be useful for things like prefixing messages with a header without
needing an allocated buffer to construct the "packet".
+
+ The contents of this structure are an implementation detail and must not be
+ manipulated by the user.
*/
typedef struct {
uint32_t read_head; ///< Read head at the start of the transaction
uint32_t write_head; ///< Write head if the transaction were committed
} ZixRingTransaction;
-/// Return the number of bytes available for writing
-ZIX_PURE_API
-uint32_t
+/**
+ Return the number of bytes available for writing.
+
+ This function returns at most one less than the ring's buffer size.
+*/
+ZIX_PURE_API uint32_t
zix_ring_write_space(const ZixRing* ZIX_NONNULL ring);
-/// Write data to the ring
-ZIX_API
-uint32_t
+/**
+ Write data to the ring.
+
+ This writes a contiguous input buffer of bytes to the ring.
+
+ @param ring The ring to write data to.
+ @param src The buffer to read data from.
+ @param size The number of bytes to read from `src` and write to `ring`.
+
+ @return The number of bytes written, which is either `size` on success, or
+ zero on failure.
+*/
+ZIX_API uint32_t
zix_ring_write(ZixRing* ZIX_NONNULL ring,
const void* ZIX_NONNULL src,
uint32_t size);
@@ -154,8 +199,7 @@ zix_ring_write(ZixRing* ZIX_NONNULL ring,
@param ring The ring to write data to.
@return A new empty transaction.
*/
-ZIX_API
-ZixRingTransaction
+ZIX_API ZIX_NODISCARD ZixRingTransaction
zix_ring_begin_write(ZixRing* ZIX_NONNULL ring);
/**
@@ -176,8 +220,7 @@ zix_ring_begin_write(ZixRing* ZIX_NONNULL ring);
@param size Length of data to write in bytes.
@return #ZIX_STATUS_NO_MEM or #ZIX_STATUS_SUCCESS.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_ring_amend_write(ZixRing* ZIX_NONNULL ring,
ZixRingTransaction* ZIX_NONNULL tx,
const void* ZIX_NONNULL src,
@@ -196,8 +239,7 @@ zix_ring_amend_write(ZixRing* ZIX_NONNULL ring,
@param tx The active transaction, from zix_ring_begin_write().
@return #ZIX_STATUS_SUCCESS.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_ring_commit_write(ZixRing* ZIX_NONNULL ring,
const ZixRingTransaction* ZIX_NONNULL tx);
diff --git a/include/zix/sem.h b/include/zix/sem.h
index 8aa205e..49ab5f8 100644
--- a/include/zix/sem.h
+++ b/include/zix/sem.h
@@ -4,8 +4,8 @@
#ifndef ZIX_SEM_H
#define ZIX_SEM_H
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/attributes.h>
+#include <zix/status.h>
#ifdef __APPLE__
# include <mach/mach.h>
@@ -15,10 +15,10 @@
# include <semaphore.h>
#endif
-ZIX_BEGIN_DECLS
-
#include <stdint.h>
+ZIX_BEGIN_DECLS
+
/**
@defgroup zix_sem Semaphore
@ingroup zix_threading
@@ -30,14 +30,14 @@ ZIX_BEGIN_DECLS
This is an integer that is never negative, and has two main operations:
increment (post) and decrement (wait). If a decrement can't be performed
- (because the value is 0) the caller will be blocked until another thread posts
- and the operation can succeed.
+ (because the value is 0) the caller will be blocked until another thread
+ posts and the operation can succeed.
Semaphores can be created with any starting value, but typically this will
be 0 so the semaphore can be used as a simple signal where each post
corresponds to one wait.
- Semaphores are very efficient (much moreso than a mutex/cond pair). In
+ Semaphores are very efficient (compared to a mutex/cond pair). In
particular, at least on Linux, post is async-signal-safe, which means it
does not block and will not be interrupted. If you need to signal from
a realtime thread, this is the most appropriate primitive to use.
@@ -49,8 +49,7 @@ typedef struct ZixSemImpl ZixSem;
@return #ZIX_STATUS_SUCCESS, or an unlikely error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_sem_init(ZixSem* ZIX_NONNULL sem, unsigned initial);
/**
@@ -58,8 +57,7 @@ zix_sem_init(ZixSem* ZIX_NONNULL sem, unsigned initial);
@return #ZIX_STATUS_SUCCESS, or an error.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_sem_destroy(ZixSem* ZIX_NONNULL sem);
/**
@@ -71,8 +69,7 @@ zix_sem_destroy(ZixSem* ZIX_NONNULL sem);
if the maximum possible value would have been exceeded, or
#ZIX_STATUS_BAD_ARG if `sem` is invalid.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_sem_post(ZixSem* ZIX_NONNULL sem);
/**
@@ -83,8 +80,7 @@ zix_sem_post(ZixSem* ZIX_NONNULL sem);
@return #ZIX_STATUS_SUCCESS if `sem` was decremented, or #ZIX_STATUS_BAD_ARG
if `sem` is invalid.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_sem_wait(ZixSem* ZIX_NONNULL sem);
/**
@@ -94,8 +90,7 @@ zix_sem_wait(ZixSem* ZIX_NONNULL sem);
#ZIX_STATUS_UNAVAILABLE if it was already zero, or #ZIX_STATUS_BAD_ARG if
`sem` is invalid.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_sem_try_wait(ZixSem* ZIX_NONNULL sem);
/**
@@ -108,8 +103,7 @@ zix_sem_try_wait(ZixSem* ZIX_NONNULL sem);
the system does not support timed waits, or #ZIX_STATUS_BAD_ARG if `sem` is
invalid.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_sem_timed_wait(ZixSem* ZIX_NONNULL sem,
uint32_t seconds,
uint32_t nanoseconds);
diff --git a/include/zix/status.h b/include/zix/status.h
index 47aede8..d03160e 100644
--- a/include/zix/status.h
+++ b/include/zix/status.h
@@ -4,7 +4,7 @@
#ifndef ZIX_STATUS_H
#define ZIX_STATUS_H
-#include "zix/attributes.h"
+#include <zix/attributes.h>
ZIX_BEGIN_DECLS
@@ -38,8 +38,7 @@ typedef enum {
The returned string is always one sentence, with an uppercase first
character, and no trailing period.
*/
-ZIX_CONST_API
-const char*
+ZIX_CONST_API const char*
zix_strerror(ZixStatus status);
/**
diff --git a/include/zix/string_view.h b/include/zix/string_view.h
index f13f8d1..be15018 100644
--- a/include/zix/string_view.h
+++ b/include/zix/string_view.h
@@ -1,12 +1,13 @@
-// Copyright 2011-2023 David Robillard <d@drobilla.net>
+// Copyright 2011-2024 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 <zix/allocator.h>
+#include <zix/attributes.h>
+#include <stdbool.h>
#include <stddef.h>
#include <string.h>
@@ -39,9 +40,7 @@ typedef struct {
// clang-format on
/// Return a view of an empty string
-ZIX_ALWAYS_INLINE_FUNC
-ZIX_CONST_FUNC
-static inline ZixStringView
+ZIX_ALWAYS_INLINE_FUNC ZIX_CONST_FUNC static inline ZixStringView
zix_empty_string(void)
{
const ZixStringView view = {"", 0U};
@@ -61,9 +60,7 @@ zix_empty_string(void)
@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_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};
@@ -77,9 +74,7 @@ zix_substring(const char* const ZIX_NONNULL str, const size_t len)
@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_ALWAYS_INLINE_FUNC ZIX_PURE_FUNC static inline ZixStringView
// NOLINTNEXTLINE(clang-diagnostic-unused-function)
zix_string(const char* const ZIX_NULLABLE str)
{
@@ -89,11 +84,20 @@ zix_string(const char* const ZIX_NULLABLE str)
/**
Copy a string view into a newly allocated null-terminated string.
*/
-ZIX_API
-char* ZIX_ALLOCATED
+ZIX_MALLOC_API char* ZIX_ALLOCATED
zix_string_view_copy(ZixAllocator* ZIX_NULLABLE allocator, ZixStringView view);
/**
+ Return true if both string views refer to equal strings.
+
+ This may be significantly faster than a full string comparison, because it
+ has fast paths for when the operands have different lengths, or point to the
+ same string data.
+*/
+ZIX_PURE_API bool
+zix_string_view_equals(ZixStringView lhs, ZixStringView rhs);
+
+/**
@}
*/
diff --git a/include/zix/thread.h b/include/zix/thread.h
index 2493ed3..77a6bf5 100644
--- a/include/zix/thread.h
+++ b/include/zix/thread.h
@@ -4,8 +4,8 @@
#ifndef ZIX_THREAD_H
#define ZIX_THREAD_H
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/attributes.h>
+#include <zix/status.h>
#ifdef _WIN32
# include <windows.h>
@@ -62,8 +62,7 @@ typedef ZixThreadResult(ZIX_THREAD_FUNC* ZixThreadFunc)(void*);
@return #ZIX_STATUS_SUCCESS on success, or #ZIX_STATUS_ERROR.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_thread_create(ZixThread* thread,
size_t stack_size,
ZixThreadFunc function,
@@ -74,8 +73,7 @@ zix_thread_create(ZixThread* thread,
@return #ZIX_STATUS_SUCCESS on success, or #ZIX_STATUS_ERROR.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_thread_join(ZixThread thread);
/**
diff --git a/include/zix/tree.h b/include/zix/tree.h
index 0ad37f2..7a223a5 100644
--- a/include/zix/tree.h
+++ b/include/zix/tree.h
@@ -4,9 +4,9 @@
#ifndef ZIX_TREE_H
#define ZIX_TREE_H
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/status.h>
#include <stdbool.h>
#include <stddef.h>
@@ -20,7 +20,7 @@ ZIX_BEGIN_DECLS
*/
/**
- @defgroup zix_tree_setup Setup
+ @defgroup zix_tree_types Types
@{
*/
@@ -36,9 +36,14 @@ typedef int (*ZixTreeCompareFunc)(const void* ZIX_UNSPECIFIED a,
typedef void (*ZixTreeDestroyFunc)(void* ZIX_UNSPECIFIED ptr,
const void* ZIX_UNSPECIFIED user_data);
+/**
+ @}
+ @defgroup zix_tree_setup Setup
+ @{
+*/
+
/// Create a new (empty) tree
-ZIX_API
-ZixTree* ZIX_ALLOCATED
+ZIX_API ZIX_NODISCARD ZixTree* ZIX_ALLOCATED
zix_tree_new(ZixAllocator* ZIX_NULLABLE allocator,
bool allow_duplicates,
ZixTreeCompareFunc ZIX_NONNULL cmp,
@@ -47,13 +52,11 @@ zix_tree_new(ZixAllocator* ZIX_NULLABLE allocator,
const void* ZIX_NULLABLE destroy_user_data);
/// Free `t`
-ZIX_API
-void
+ZIX_API void
zix_tree_free(ZixTree* ZIX_NULLABLE t);
/// Return the number of elements in `t`
-ZIX_PURE_API
-size_t
+ZIX_PURE_API size_t
zix_tree_size(const ZixTree* ZIX_NONNULL t);
/**
@@ -66,48 +69,39 @@ zix_tree_size(const ZixTree* ZIX_NONNULL t);
typedef struct ZixTreeNodeImpl ZixTreeIter;
/// Return the data associated with the given tree item
-ZIX_PURE_API
-void* ZIX_UNSPECIFIED
+ZIX_PURE_API void* ZIX_UNSPECIFIED
zix_tree_get(const ZixTreeIter* ZIX_NULLABLE ti);
/// Return an iterator to the first (smallest) element in `t`
-ZIX_PURE_API
-ZixTreeIter* ZIX_NULLABLE
+ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE
zix_tree_begin(ZixTree* ZIX_NONNULL t);
/// Return an iterator the the element one past the last element in `t`
-ZIX_CONST_API
-ZixTreeIter* ZIX_NULLABLE
+ZIX_CONST_API ZixTreeIter* ZIX_NULLABLE
zix_tree_end(ZixTree* ZIX_NONNULL t);
/// Return true iff `i` is an iterator to the end of its tree
-ZIX_CONST_API
-bool
+ZIX_CONST_API bool
zix_tree_iter_is_end(const ZixTreeIter* ZIX_NULLABLE i);
/// Return an iterator to the last (largest) element in `t`
-ZIX_PURE_API
-ZixTreeIter* ZIX_NULLABLE
+ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE
zix_tree_rbegin(ZixTree* ZIX_NONNULL t);
/// Return an iterator the the element one before the first element in `t`
-ZIX_CONST_API
-ZixTreeIter* ZIX_NULLABLE
+ZIX_CONST_API ZixTreeIter* ZIX_NULLABLE
zix_tree_rend(ZixTree* ZIX_NONNULL t);
/// Return true iff `i` is an iterator to the reverse end of its tree
-ZIX_CONST_API
-bool
+ZIX_CONST_API bool
zix_tree_iter_is_rend(const ZixTreeIter* ZIX_NULLABLE i);
/// Return an iterator that points to the element one past `i`
-ZIX_PURE_API
-ZixTreeIter* ZIX_NULLABLE
+ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE
zix_tree_iter_next(ZixTreeIter* ZIX_NULLABLE i);
/// Return an iterator that points to the element one before `i`
-ZIX_PURE_API
-ZixTreeIter* ZIX_NULLABLE
+ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE
zix_tree_iter_prev(ZixTreeIter* ZIX_NULLABLE i);
/**
@@ -117,15 +111,13 @@ zix_tree_iter_prev(ZixTreeIter* ZIX_NULLABLE i);
*/
/// Insert the element `e` into `t` and point `ti` at the new element
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_tree_insert(ZixTree* ZIX_NONNULL t,
void* ZIX_UNSPECIFIED e,
ZixTreeIter* ZIX_NULLABLE* ZIX_NULLABLE ti);
/// Remove the item pointed at by `ti` from `t`
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_tree_remove(ZixTree* ZIX_NONNULL t, ZixTreeIter* ZIX_NONNULL ti);
/**
@@ -139,8 +131,7 @@ zix_tree_remove(ZixTree* ZIX_NONNULL t, ZixTreeIter* ZIX_NONNULL ti);
If no such item exists, `ti` is set to NULL.
*/
-ZIX_API
-ZixStatus
+ZIX_API ZixStatus
zix_tree_find(const ZixTree* ZIX_NONNULL t,
const void* ZIX_UNSPECIFIED e,
ZixTreeIter* ZIX_NULLABLE* ZIX_NONNULL ti);
diff --git a/include/zix/zix.h b/include/zix/zix.h
index ca72d35..ceaadc0 100644
--- a/include/zix/zix.h
+++ b/include/zix/zix.h
@@ -1,4 +1,4 @@
-// Copyright 2016-2022 David Robillard <d@drobilla.net>
+// Copyright 2016-2024 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#ifndef ZIX_ZIX_H
@@ -16,9 +16,9 @@
@{
*/
-#include "zix/attributes.h"
-#include "zix/status.h"
-#include "zix/string_view.h"
+#include <zix/attributes.h>
+#include <zix/status.h>
+#include <zix/string_view.h>
/**
@}
@@ -26,8 +26,8 @@
@{
*/
-#include "zix/allocator.h"
-#include "zix/bump_allocator.h"
+#include <zix/allocator.h>
+#include <zix/bump_allocator.h>
/**
@}
@@ -35,7 +35,7 @@
@{
*/
-#include "zix/digest.h"
+#include <zix/digest.h>
/**
@}
@@ -43,10 +43,10 @@
@{
*/
-#include "zix/btree.h"
-#include "zix/hash.h"
-#include "zix/ring.h"
-#include "zix/tree.h"
+#include <zix/btree.h>
+#include <zix/hash.h>
+#include <zix/ring.h>
+#include <zix/tree.h>
/**
@}
@@ -54,8 +54,8 @@
@{
*/
-#include "zix/sem.h"
-#include "zix/thread.h"
+#include <zix/sem.h>
+#include <zix/thread.h>
/**
@}
@@ -63,8 +63,16 @@
@{
*/
-#include "zix/filesystem.h"
-#include "zix/path.h"
+#include <zix/filesystem.h>
+#include <zix/path.h>
+
+/**
+ @}
+ @defgroup zix_environment Environment
+ @{
+*/
+
+#include <zix/environment.h>
/**
@}