Skip to content

Commit

Permalink
Improve filesystem functions
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Dec 13, 2023
1 parent 12c7f3e commit b85b83b
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 45 deletions.
17 changes: 11 additions & 6 deletions modules/foundation/inc/tactile/foundation/io/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ using FilePath = std::filesystem::path;
using DirectoryIterator = std::filesystem::directory_iterator;
using RecursiveDirectoryIterator = std::filesystem::recursive_directory_iterator;

namespace fs {
/**
* \brief Returns the file path to the persistent storage directory associated with the app.
*
* \return a directory path.
*/
[[nodiscard]]
TACTILE_FOUNDATION_API auto get_persistent_storage_directory() -> FilePath;

/**
* \brief Converts a path to a string that is guaranteed to use forward slash characters.
Expand All @@ -28,7 +34,7 @@ namespace fs {
* \return a file path string with forward slashes.
*/
[[nodiscard]]
TACTILE_FOUNDATION_API auto use_forward_slashes(const FilePath& path) -> String;
TACTILE_FOUNDATION_API auto normalize_path(const FilePath& path) -> String;

/**
* \brief Converts file paths to use a '~' prefix (if possible).
Expand All @@ -38,7 +44,8 @@ TACTILE_FOUNDATION_API auto use_forward_slashes(const FilePath& path) -> String;
* \return a string with a shortened user directory prefix; or nothing if not applicable.
*/
[[nodiscard]]
TACTILE_FOUNDATION_API auto use_short_home_prefix(const FilePath& path) -> Maybe<String>;
TACTILE_FOUNDATION_API auto shorten_home_directory_prefix(const FilePath& path)
-> Maybe<String>;

/**
* \brief Indicates whether a file path starts with the home directory.
Expand All @@ -48,9 +55,7 @@ TACTILE_FOUNDATION_API auto use_short_home_prefix(const FilePath& path) -> Maybe
* \return true if the path features the home directory prefix; false otherwise.
*/
[[nodiscard]]
TACTILE_FOUNDATION_API auto has_home_prefix(const FilePath& path) -> bool;

} // namespace fs
TACTILE_FOUNDATION_API auto has_home_directory_prefix(const FilePath& path) -> bool;

namespace fs_literals {

Expand Down
39 changes: 27 additions & 12 deletions modules/foundation/src/tactile/foundation/io/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@

#include <algorithm> // replace

#include <SDL2/SDL.h>

#include "tactile/foundation/debug/exception.hpp"
#include "tactile/foundation/log/logger.hpp"
#include "tactile/foundation/platform/environment.hpp"
#include "tactile/foundation/prelude.hpp"

namespace tactile::fs {
namespace tactile {
namespace {

[[nodiscard]] auto _get_home_prefix() -> const NativeString&
[[nodiscard]] auto _get_user_home_directory() -> const NativeString&
{
// On Unix platforms, HOME is something like '/Users/username'
// On Windows, USERPROFILE is something like 'C:\Users\username'
Expand All @@ -21,29 +25,40 @@ namespace {

} // namespace

auto use_forward_slashes(const FilePath& path) -> String
auto get_persistent_storage_directory() -> FilePath
{
if (const auto* path = SDL_GetPrefPath("albin-johansson", "tactile")) {
return FilePath {path};
}

TACTILE_LOG_ERROR("Could not determine persistent storage directory: {}",
SDL_GetError());
throw Exception {"Could not determine persistent storage directory"};
}

auto normalize_path(const FilePath& path) -> String
{
auto str = path.string();
std::replace(str.begin(), str.end(), '\\', '/');
return str;
}

auto use_short_home_prefix(const FilePath& path) -> Maybe<String>
auto shorten_home_directory_prefix(const FilePath& path) -> Maybe<String>
{
if (has_home_prefix(path)) {
const auto& prefix = _get_home_prefix();
return '~' + path.string().substr(prefix.size());
if (has_home_directory_prefix(path)) {
const auto& home_dir = _get_user_home_directory();
return '~' + path.string().substr(home_dir.size());
}
else {
return kNone;
return kNothing;
}
}

auto has_home_prefix(const FilePath& path) -> bool
auto has_home_directory_prefix(const FilePath& path) -> bool
{
const auto& prefix = _get_home_prefix();
const auto& home_dir = _get_user_home_directory();
const NativeStringView view {path.c_str()};
return view.starts_with(prefix);
return view.starts_with(home_dir);
}

} // namespace tactile::fs
} // namespace tactile
59 changes: 33 additions & 26 deletions modules/foundation/test/io/filesystem_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,49 @@ TEST(Filesystem, PathLiteralOperator)
EXPECT_EQ("x/y/z"_path, FilePath {"x/y/z"});
}

/// \tests tactile::fs::use_forward_slashes
TEST(Filesystem, UseForwardSlashes)
/// \tests tactile::get_persistent_storage_directory
TEST(Filesystem, GetPersistentStorageDirectory)
{
EXPECT_EQ(fs::use_forward_slashes(R"(~/a/b)"), "~/a/b");
EXPECT_EQ(fs::use_forward_slashes(R"(C:\a\b\c.txt)"), "C:/a/b/c.txt");
EXPECT_NO_THROW((void) get_persistent_storage_directory());
}

/// \tests tactile::fs::use_short_home_prefix
TEST(Filesystem, UseShortHomePrefix)

/// \tests tactile::normalize_path
TEST(Filesystem, NormalizePath)
{
EXPECT_EQ(normalize_path(R"(~/a/b)"), "~/a/b");
EXPECT_EQ(normalize_path(R"(C:\a\b\c.txt)"), "C:/a/b/c.txt");
}

/// \tests tactile::shorten_home_directory_prefix
TEST(Filesystem, ShortenHomeDirectoryPrefix)
{
const FilePath home = get_env(kIsWindows ? "USERPROFILE" : "HOME").value();

EXPECT_EQ(fs::use_short_home_prefix(home), "~");
EXPECT_EQ(fs::use_short_home_prefix(home.string() + "/foo/"), "~/foo/");
EXPECT_EQ(fs::use_short_home_prefix(home.string() + "/foo/bar.txt"), "~/foo/bar.txt");
EXPECT_EQ(fs::use_short_home_prefix(home.string() + '/'), "~/");
EXPECT_EQ(shorten_home_directory_prefix(home), "~");
EXPECT_EQ(shorten_home_directory_prefix(home.string() + "/foo/"), "~/foo/");
EXPECT_EQ(shorten_home_directory_prefix(home.string() + "/foo/bar.txt"), "~/foo/bar.txt");
EXPECT_EQ(shorten_home_directory_prefix(home.string() + '/'), "~/");

EXPECT_FALSE(fs::use_short_home_prefix("/a/b").has_value());
EXPECT_FALSE(fs::use_short_home_prefix("a/b/c").has_value());
EXPECT_FALSE(fs::use_short_home_prefix("file.txt").has_value());
EXPECT_FALSE(shorten_home_directory_prefix("/a/b").has_value());
EXPECT_FALSE(shorten_home_directory_prefix("a/b/c").has_value());
EXPECT_FALSE(shorten_home_directory_prefix("file.txt").has_value());
}

/// \tests tactile::fs::has_home_prefix
TEST(Filesystem, HasHomePrefix)
/// \tests tactile::has_home_directory_prefix
TEST(Filesystem, HasHomeDirectoryPrefix)
{
const FilePath home = get_env(kIsWindows ? "USERPROFILE" : "HOME").value();

EXPECT_FALSE(fs::has_home_prefix(""));
EXPECT_FALSE(fs::has_home_prefix("abc.xyz"));
EXPECT_FALSE(fs::has_home_prefix("a/b.c"));
EXPECT_FALSE(fs::has_home_prefix("a/b/c"));
EXPECT_FALSE(fs::has_home_prefix("/a/b"));

EXPECT_TRUE(fs::has_home_prefix(home));
EXPECT_TRUE(fs::has_home_prefix(home / "a"));
EXPECT_TRUE(fs::has_home_prefix(home / "a.b"));
EXPECT_TRUE(fs::has_home_prefix(home / "a" / "b.c"));
EXPECT_TRUE(fs::has_home_prefix(home.string() + "/"));
EXPECT_FALSE(has_home_directory_prefix(""));
EXPECT_FALSE(has_home_directory_prefix("abc.xyz"));
EXPECT_FALSE(has_home_directory_prefix("a/b.c"));
EXPECT_FALSE(has_home_directory_prefix("a/b/c"));
EXPECT_FALSE(has_home_directory_prefix("/a/b"));

EXPECT_TRUE(has_home_directory_prefix(home));
EXPECT_TRUE(has_home_directory_prefix(home / "a"));
EXPECT_TRUE(has_home_directory_prefix(home / "a.b"));
EXPECT_TRUE(has_home_directory_prefix(home / "a" / "b.c"));
EXPECT_TRUE(has_home_directory_prefix(home.string() + "/"));
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ auto _add_common_tileset_attributes(const ir::Tileset& tileset,
tileset_json["tilecount"] = tileset.tile_count;

const auto image_path = std::filesystem::relative(tileset.image_path, options.base_dir);
tileset_json["image"] = fs::use_forward_slashes(tileset.image_path);
tileset_json["image"] = normalize_path(tileset.image_path);
tileset_json["imagewidth"] = tileset.image_width;
tileset_json["imageheight"] = tileset.image_height;

Expand Down

0 comments on commit b85b83b

Please sign in to comment.