summaryrefslogtreecommitdiffstats
path: root/include/zix
diff options
context:
space:
mode:
Diffstat (limited to 'include/zix')
-rw-r--r--include/zix/function_types.h2
-rw-r--r--include/zix/path.h246
-rw-r--r--include/zix/zix.h8
3 files changed, 255 insertions, 1 deletions
diff --git a/include/zix/function_types.h b/include/zix/function_types.h
index e2a8958..d0c7193 100644
--- a/include/zix/function_types.h
+++ b/include/zix/function_types.h
@@ -12,7 +12,7 @@ ZIX_BEGIN_DECLS
/**
@defgroup zix_function_types Function Types
- @ingroup zix
+ @ingroup zix_utilities
@{
*/
diff --git a/include/zix/path.h b/include/zix/path.h
new file mode 100644
index 0000000..5d3bd60
--- /dev/null
+++ b/include/zix/path.h
@@ -0,0 +1,246 @@
+// Copyright 2007-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#ifndef ZIX_PATH_H
+#define ZIX_PATH_H
+
+#include "zix/allocator.h"
+#include "zix/attributes.h"
+#include "zix/string_view.h"
+
+#include <stdbool.h>
+
+/// A pure API function on Windows, a constant stub everywhere else
+#ifdef _WIN32
+# define ZIX_PURE_WIN_API ZIX_PURE_API
+#else
+# define ZIX_PURE_WIN_API ZIX_CONST_API
+#endif
+
+ZIX_BEGIN_DECLS
+
+/**
+ @defgroup zix_path Path
+ @ingroup zix_file_system
+
+ Functions for interpreting and manipulating paths. These functions are
+ purely lexical and do not access any filesystem.
+
+ @{
+*/
+
+/**
+ @defgroup zix_path_concatenation Concatenation
+ @{
+*/
+
+/// Join path `a` and path `b` with a single directory separator between them
+ZIX_API
+char* ZIX_ALLOCATED
+zix_path_join(ZixAllocator* ZIX_NULLABLE allocator,
+ const char* ZIX_NULLABLE a,
+ const char* ZIX_NULLABLE b);
+
+/**
+ @}
+ @defgroup zix_path_lexical Lexical Transformations
+ @{
+*/
+
+/**
+ Return `path` with preferred directory separators.
+
+ The returned path will be a copy of `path` with any directory separators
+ converted to the preferred separator (backslash on Windows, slash everywhere
+ else).
+*/
+ZIX_API
+char* ZIX_ALLOCATED
+zix_path_preferred(ZixAllocator* ZIX_NULLABLE allocator,
+ const char* ZIX_NONNULL path);
+
+/**
+ Return `path` converted to normal form.
+
+ 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).
+
+ Note that this function doesn't access the filesystem, so won't do anything
+ like case normalization or symbolic link dereferencing.
+*/
+ZIX_API
+char* ZIX_ALLOCATED
+zix_path_lexically_normal(ZixAllocator* ZIX_NULLABLE allocator,
+ const char* ZIX_NONNULL path);
+
+/**
+ Return `path` relative to `base` if possible.
+
+ If `path` is not within `base`, a copy is returned. Otherwise, an
+ equivalent path relative to `base` is returned (which may contain
+ up-references).
+*/
+ZIX_API
+char* ZIX_ALLOCATED
+zix_path_lexically_relative(ZixAllocator* ZIX_NULLABLE allocator,
+ const char* ZIX_NONNULL path,
+ const char* ZIX_NONNULL base);
+
+/**
+ @}
+ @defgroup zix_path_decomposition Decomposition
+ @{
+*/
+
+/// Return the root name of `path` like "C:", or null
+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_path_root_directory(const char* ZIX_NONNULL path);
+
+/**
+ Return the root path of `path`, or null.
+
+ The universal root path (in normal form) is "/". Root paths are their own
+ roots, but note that the path returned by this function may be partially
+ normalized. For example, "/" is the root of "/", "//", "/.", and "/..".
+
+ On Windows, the root may additionally be an absolute drive root like "C:\",
+ a relative drive root like "C:", or a network root like "//Host/".
+
+ @return The newly allocated root path of `path`, or null if it has no root
+ or allocation failed.
+*/
+ZIX_PURE_API
+ZixStringView
+zix_path_root_path(const char* ZIX_NONNULL path);
+
+/**
+ Return the relative path component of path without the root directory.
+
+ If the path has no relative path (because it is empty or a root path), this
+ returns null.
+*/
+ZIX_PURE_API
+ZixStringView
+zix_path_relative_path(const char* ZIX_NONNULL path);
+
+/**
+ Return the path to the directory that contains `path`.
+
+ The parent of a root path is itself, but note that the path returned by this
+ function may be partially normalized. For example, "/" is the parent of
+ "/", "//", "/.", and "/..".
+
+ If `path` has a trailing separator, it is treated like an empty filename in
+ a directory. For example, the parent of "/a/" is "/a".
+
+ If `path` is relative, then this returns either a relative path to the
+ parent if possible, or null. For example, the parent of "a/b" is "a".
+
+ @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_path_parent_path(const char* ZIX_NONNULL path);
+
+/**
+ Return the filename component of `path` without any directories.
+
+ The filename is the name after the last directory separator. If the path
+ has no filename, this returns null.
+*/
+ZIX_PURE_API
+ZixStringView
+zix_path_filename(const char* ZIX_NONNULL path);
+
+/**
+ Return the stem of the filename component of `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_path_stem(const char* ZIX_NONNULL path);
+
+/**
+ Return the extension of the filename component of `path`.
+
+ The "extension" is everything past the last "." in the filename, if "." is
+ not the first character.
+*/
+ZIX_PURE_API
+ZixStringView
+zix_path_extension(const char* ZIX_NONNULL path);
+
+/**
+ @}
+ @defgroup zix_path_queries Queries
+ @{
+*/
+
+/// Return true if `path` has a root path like "/" or "C:\"
+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_path_has_root_name(const char* ZIX_NULLABLE path);
+
+/// Return true if `path` has a root directory like "/" or "\"
+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_path_has_relative_path(const char* ZIX_NULLABLE path);
+
+/// Return true if `path` has a parent path like "dir/"
+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_path_has_filename(const char* ZIX_NULLABLE path);
+
+/// Return true if `path` has a stem like "file"
+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_path_has_extension(const char* ZIX_NULLABLE path);
+
+/// Return true if `path` is an absolute path
+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_path_is_relative(const char* ZIX_NULLABLE path);
+
+/**
+ @}
+ @}
+*/
+
+ZIX_END_DECLS
+
+#endif /* ZIX_PATH_H */
diff --git a/include/zix/zix.h b/include/zix/zix.h
index 223d1dc..a91b6f8 100644
--- a/include/zix/zix.h
+++ b/include/zix/zix.h
@@ -54,6 +54,14 @@
/**
@}
+ @defgroup zix_file_system File System
+ @{
+*/
+
+#include "zix/path.h"
+
+/**
+ @}
@}
*/