Skip to content

Commit

Permalink
Merge pull request #13 from Nauja/dev
Browse files Browse the repository at this point in the history
Add fs_rsplit, fs_basename and fs_dirname
  • Loading branch information
Nauja committed Feb 10, 2023
2 parents 916717f + 61d0311 commit ae9855d
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")

set(LIBFS_VERSION_MAJOR 0)
set(LIBFS_VERSION_MINOR 2)
set(LIBFS_VERSION_PATCH 2)
set(LIBFS_VERSION_PATCH 3)
set(LIBFS_VERSION "${LIBFS_VERSION_MAJOR}.${LIBFS_VERSION_MINOR}.${LIBFS_VERSION_PATCH}")

#find_package(Git)
Expand Down
10 changes: 10 additions & 0 deletions docs/api/functions/fs_basename.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. -*- coding: utf-8 -*-
.. _fs_basename:

fs_basename
-----------

.. contents::
:local:

.. doxygenfunction:: fs_basename
10 changes: 10 additions & 0 deletions docs/api/functions/fs_dirname.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. -*- coding: utf-8 -*-
.. _fs_dirname:

fs_dirname
----------

.. contents::
:local:

.. doxygenfunction:: fs_dirname
10 changes: 10 additions & 0 deletions docs/api/functions/fs_rsplit.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. -*- coding: utf-8 -*-
.. _fs_rsplit:

fs_rsplit
---------

.. contents::
:local:

.. doxygenfunction:: fs_rsplit
5 changes: 5 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
Changelog
=========

v0.2.3 (Feb 10, 2023)
---------------------

* Add fs_rsplit, fs_basename and fs_dirname

v0.2.2 (Jan 24, 2023)
---------------------

Expand Down
45 changes: 45 additions & 0 deletions fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,51 @@ fs_init_hooks(fs_hooks *hooks)
#define _LIBFS_MALLOC fs_global_hooks.malloc_fn
#define _LIBFS_FREE fs_global_hooks.free_fn

#if HAVE_STRING_H
LIBFS_PUBLIC(const char *)
fs_rsplit(const char *path)
{
char *c1;
char *c2;

c1 = strrchr(path, '/');
if (!c1)
{
return strrchr(path, '\\');
}

c2 = strrchr(c1, '\\');
return c2 ? c2 : c1;
}
#endif

#if HAVE_STDIO_H && HAVE_STRING_H
LIBFS_PUBLIC(size_t)
fs_dirname(const char *path, char *buf, size_t size)
{
const char *c = fs_rsplit(path);
if (!c)
{
snprintf(buf, size, "%s", "");
return 0;
}

return snprintf(buf, size, "%.*s", (int)(((size_t)c) - ((size_t)path)), path);
}

LIBFS_PUBLIC(const char *)
fs_basename(const char *path)
{
const char *c = fs_rsplit(path);
if (!c)
{
return path;
}

return c + 1;
}
#endif

#if HAVE_WINDOWS_H
LIBFS_PUBLIC(char *)
fs_absolute(const char *path, char *buf, size_t size)
Expand Down
45 changes: 44 additions & 1 deletion fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern "C"
/** Minor version of libfs. */
#define LIBFS_VERSION_MINOR 2
/** Patch version of libfs. */
#define LIBFS_VERSION_PATCH 2
#define LIBFS_VERSION_PATCH 3

/* Define to 1 if you have the <dirent.h> header file. */
#ifndef HAVE_DIRENT_H
Expand Down Expand Up @@ -234,6 +234,49 @@ extern "C"
LIBFS_PUBLIC(char *)
fs_absolute(const char *path, char *buf, size_t size);

/**
* Gets a pointer to the rightmost path separator.
*
* @code{.c}
* const char* c = fs_rsplit("./path/to/foo.txt");
* @endcode
*
* @param[in] path Some null-terminated path
* @return A pointer to the rightmost separator.
*/
LIBFS_PUBLIC(const char*)
fs_rsplit(const char* path);

/**
* Gets the directory name of path.
*
* @code{.c}
* char dirname[256];
* fs_dirname("./foo.txt", dirname, 256);
* @endcode
*
* @param[in] path Some null-terminated path
* @param[out] buf Buffer for storing the result path
* @param[in] size Buffer size
* @return The number of bytes that would have been written if
* buf was large enough (excluding the null-terminating character).
*/
LIBFS_PUBLIC(size_t)
fs_dirname(const char* path, char *buf, size_t size);

/**
* Gets the base name of path.
*
* @code{.c}
* const char* basename = fs_basename("./foo.txt");
* @endcode
*
* @param[in] path Some null-terminated path
* @return A pointer to the base name.
*/
LIBFS_PUBLIC(const char*)
fs_basename(const char* path);

/**
* Copies files or directories.
*
Expand Down
43 changes: 43 additions & 0 deletions fs.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,49 @@ extern "C"
LIBFS_PUBLIC(char *)
fs_absolute(const char *path, char *buf, size_t size);

/**
* Gets a pointer to the rightmost path separator.
*
* @code{.c}
* const char* c = fs_rsplit("./path/to/foo.txt");
* @endcode
*
* @param[in] path Some null-terminated path
* @return A pointer to the rightmost separator.
*/
LIBFS_PUBLIC(const char*)
fs_rsplit(const char* path);

/**
* Gets the directory name of path.
*
* @code{.c}
* char dirname[256];
* fs_dirname("./foo.txt", dirname, 256);
* @endcode
*
* @param[in] path Some null-terminated path
* @param[out] buf Buffer for storing the result path
* @param[in] size Buffer size
* @return The number of bytes that would have been written if
* buf was large enough (excluding the null-terminating character).
*/
LIBFS_PUBLIC(size_t)
fs_dirname(const char* path, char *buf, size_t size);

/**
* Gets the base name of path.
*
* @code{.c}
* const char* basename = fs_basename("./foo.txt");
* @endcode
*
* @param[in] path Some null-terminated path
* @return A pointer to the base name.
*/
LIBFS_PUBLIC(const char*)
fs_basename(const char* path);

/**
* Copies files or directories.
*
Expand Down
74 changes: 74 additions & 0 deletions tests/test_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@
typedef struct fs_file_iterator fs_file_iterator;
typedef struct fs_directory_iterator fs_directory_iterator;

static void test_rsplit_root(void **state)
{
assert_null(fs_rsplit("foo.txt"));
}

static void test_rsplit_forwardslash(void **state)
{
assert_string_equal(fs_rsplit("/path\\to/foo.txt"), "/foo.txt");
}

static void test_rsplit_backslash(void **state)
{
assert_string_equal(fs_rsplit("/path/to\\foo.txt"), "\\foo.txt");
}

static void test_absolute(void **state)
{
char cwd[256];
Expand All @@ -25,6 +40,54 @@ static void test_absolute(void **state)
assert_string_equal(cwd, buf);
}

static void test_dirname_root_file(void **state)
{
char buf[LIBFS_MAX_PATH];
fs_dirname("foo.txt", buf, LIBFS_MAX_PATH);
assert_string_equal(buf, "");
}

static void test_dirname_dot(void **state)
{
char buf[LIBFS_MAX_PATH];
fs_dirname(".", buf, LIBFS_MAX_PATH);
assert_string_equal(buf, "");
}

static void test_dirname_file(void **state)
{
char buf[LIBFS_MAX_PATH];
fs_dirname("/path/to\\bar.txt", buf, LIBFS_MAX_PATH);
assert_string_equal(buf, "/path/to");
}

static void test_dirname_empty(void **state)
{
char buf[LIBFS_MAX_PATH];
fs_dirname("/foo/bar/", buf, LIBFS_MAX_PATH);
assert_string_equal(buf, "/foo/bar");
}

static void test_basename_root_file(void **state)
{
assert_string_equal(fs_basename("foo.txt"), "foo.txt");
}

static void test_basename_dot(void **state)
{
assert_string_equal(fs_basename("."), ".");
}

static void test_basename_file(void **state)
{
assert_string_equal(fs_basename("/path/to\\bar.txt"), "bar.txt");
}

static void test_basename_empty(void **state)
{
assert_string_equal(fs_basename("/foo/bar/"), "");
}

static void test_get_cwd(void **state)
{
char cwd[LIBFS_MAX_PATH];
Expand Down Expand Up @@ -271,7 +334,18 @@ static void test_hooks(void **state)
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_rsplit_root),
cmocka_unit_test(test_rsplit_forwardslash),
cmocka_unit_test(test_rsplit_backslash),
cmocka_unit_test(test_absolute),
cmocka_unit_test(test_dirname_root_file),
cmocka_unit_test(test_dirname_dot),
cmocka_unit_test(test_dirname_file),
cmocka_unit_test(test_dirname_empty),
cmocka_unit_test(test_basename_root_file),
cmocka_unit_test(test_basename_dot),
cmocka_unit_test(test_basename_file),
cmocka_unit_test(test_basename_empty),
cmocka_unit_test(test_get_cwd),
cmocka_unit_test(test_path_join),
cmocka_unit_test(test_exists),
Expand Down

0 comments on commit ae9855d

Please sign in to comment.