Skip to content

Commit

Permalink
Use templates instead of inline functions
Browse files Browse the repository at this point in the history
  • Loading branch information
RauliL committed Sep 7, 2024
1 parent c5b9ada commit 9e96a19
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/.vscode
/build
/doxygen
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2021, peelo.net
Copyright (c) 2021-2024, peelo.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
70 changes: 42 additions & 28 deletions include/peelo/xdg.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, peelo.net
* Copyright (c) 2021-2024, peelo.net
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -40,31 +40,37 @@ namespace peelo::xdg
{
namespace internal
{
inline std::vector<std::filesystem::path>
get_multiple_dirs(const char* env_variable_name)
{
#if defined(_WIN32)
static const char separator = ';';
static constexpr char path_separator = ';';
#else
static const char separator = ':';
static constexpr char path_separator = ':';
#endif
std::vector<std::filesystem::path> result;

if (const auto env_variable = std::getenv(env_variable_name))
template<class T = std::filesystem::path>
std::vector<T>
get_multiple_dirs(const char* env_variable_name)
{
std::vector<T> result;

if (auto begin = std::getenv(env_variable_name))
{
const std::string s = env_variable;
std::string::size_type start = 0;
std::string::size_type end = s.find(separator);
auto end = begin;

while (end != std::string::npos)
for (; *end; ++end)
{
result.push_back(s.substr(start, end - start));
start = end + 1;
end = s.find(separator, start);
if (*end != path_separator)
{
continue;
}
else if (end - begin > 0)
{
result.emplace_back(std::string(begin, end - begin));
}
begin = end + 1;
}
if (end - start > 0)
if (end - begin > 0)
{
result.push_back(s.substr(start, end - start));
result.emplace_back(std::string(begin, end - begin));
}
}

Expand All @@ -75,7 +81,8 @@ namespace peelo::xdg
/**
* Returns path to users home directory, if it can be determined.
*/
inline std::optional<std::filesystem::path>
template<class T = std::filesystem::path>
std::optional<T>
home_dir()
{
const auto home = std::getenv("HOME");
Expand Down Expand Up @@ -115,7 +122,8 @@ namespace peelo::xdg
/**
* Returns path to XDG data directory, if it can be determined.
*/
inline std::optional<std::filesystem::path>
template<class T = std::filesystem::path>
std::optional<T>
data_dir()
{
if (const auto env_variable = std::getenv("XDG_DATA_HOME"))
Expand All @@ -134,16 +142,17 @@ namespace peelo::xdg
* Returns all XDG data directories in users preferred order, or empty vector
* if they cannot be determined.
*/
inline std::vector<std::filesystem::path>
template<class T = std::filesystem::path>
std::vector<T>
all_data_dirs()
{
auto result = internal::get_multiple_dirs("XDG_DATA_DIRS");

#if !defined(_WIN32)
if (result.empty())
{
result.push_back("/usr/local/share");
result.push_back("/usr/share");
result.emplace_back("/usr/local/share");
result.emplace_back("/usr/share");
}
#endif

Expand All @@ -153,7 +162,8 @@ namespace peelo::xdg
/**
* Returns path to XDG configuration directory, if it can be determined.
*/
inline std::optional<std::filesystem::path>
template<class T = std::filesystem::path>
std::optional<T>
config_dir()
{
if (const auto env_variable = std::getenv("XDG_CONFIG_HOME"))
Expand All @@ -172,15 +182,16 @@ namespace peelo::xdg
* Returns all XDG configuration directories in users preferred order, or
* empty vector if they cannot be determined.
*/
inline std::vector<std::filesystem::path>
template<class T = std::filesystem::path>
std::vector<T>
all_config_dirs()
{
auto result = internal::get_multiple_dirs("XDG_CONFIG_DIRS");

#if !defined(_WIN32)
if (result.empty())
{
result.push_back("/etc/xdg");
result.emplace_back("/etc/xdg");
}
#endif

Expand All @@ -190,7 +201,8 @@ namespace peelo::xdg
/**
* Returns path to XDG state directory, if it can be determined.
*/
inline std::optional<std::filesystem::path>
template<class T = std::filesystem::path>
std::optional<T>
state_dir()
{
if (const auto env_variable = std::getenv("XDG_STATE_HOME"))
Expand All @@ -208,7 +220,8 @@ namespace peelo::xdg
/**
* Returns path to XDG cache directory, if it can be determined.
*/
inline std::optional<std::filesystem::path>
template<class T = std::filesystem::path>
std::optional<T>
cache_dir()
{
if (const auto env_variable = std::getenv("XDG_CACHE_HOME"))
Expand All @@ -226,7 +239,8 @@ namespace peelo::xdg
/**
* Returns path to XDG runtime directory, if it can be determined.
*/
inline std::optional<std::filesystem::path>
template<class T = std::filesystem::path>
std::optional<T>
runtime_dir()
{
if (const auto env_variable = std::getenv("XDG_RUNTIME_DIR"))
Expand Down
27 changes: 14 additions & 13 deletions test/test_multiple_paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@

#include <peelo/xdg.hpp>

#if defined(_WIN32)
static const char separator = ';';
#else
static const char separator = ':';
#endif

using callback_type = std::function<std::vector<std::filesystem::path>()>;

static void test_callback(
static void
test_callback(
const callback_type& callback,
const char* env_variable_name
)
{
using peelo::xdg::internal::path_separator;

unsetenv(env_variable_name);
setenv(
env_variable_name,
(std::string("/xdg") + separator + "/xdg/xdg").c_str(),
(
std::string("/xdg") +
path_separator +
path_separator +
"/xdg/xdg"
).c_str(),
1
);

Expand All @@ -31,12 +33,11 @@ static void test_callback(
assert(result[1] == std::filesystem::path("/xdg/xdg"));
}

int main()
int
main()
{
using namespace peelo::xdg;

test_callback(all_data_dirs, "XDG_DATA_DIRS");
test_callback(all_config_dirs, "XDG_CONFIG_DIRS");

return EXIT_SUCCESS;
test_callback(all_data_dirs<std::filesystem::path>, "XDG_DATA_DIRS");
test_callback(all_config_dirs<std::filesystem::path>, "XDG_CONFIG_DIRS");
}
45 changes: 33 additions & 12 deletions test/test_single_paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ using std::optional;

using callback_type = std::function<std::optional<std::filesystem::path>()>;

static void test_with_env_variable(
static void
test_with_env_variable(
const callback_type& callback,
const char* env_variable_name
)
Expand All @@ -24,7 +25,8 @@ static void test_with_env_variable(
assert(*result == path("xdg") / "test");
}

static void test_without_env_variable(
static void
test_without_env_variable(
const callback_type& callback,
const char* env_variable_name,
const optional<path>& expected_result
Expand All @@ -44,7 +46,8 @@ static void test_without_env_variable(
}
}

static void test_callback(
static void
test_callback(
const callback_type& callback,
const char* env_variable_name,
const optional<path>& expected_result_without_env_var = nullopt
Expand All @@ -58,16 +61,34 @@ static void test_callback(
);
}

int main()
int
main()
{
const path base = "xdg";
using namespace peelo::xdg;
const path base = "xdg";

test_callback(data_dir, "XDG_DATA_HOME", base / ".local" / "share");
test_callback(config_dir, "XDG_CONFIG_HOME", base / ".config");
test_callback(state_dir, "XDG_STATE_HOME", base / ".local" / "state");
test_callback(cache_dir, "XDG_CACHE_HOME", base / ".cache");
test_callback(runtime_dir, "XDG_RUNTIME_DIR");

return EXIT_SUCCESS;
test_callback(
data_dir<std::filesystem::path>,
"XDG_DATA_HOME",
base / ".local" / "share"
);
test_callback(
config_dir<std::filesystem::path>,
"XDG_CONFIG_HOME",
base / ".config"
);
test_callback(
state_dir<std::filesystem::path>,
"XDG_STATE_HOME",
base / ".local" / "state"
);
test_callback(
cache_dir<std::filesystem::path>,
"XDG_CACHE_HOME",
base / ".cache"
);
test_callback(
runtime_dir<std::filesystem::path>,
"XDG_RUNTIME_DIR"
);
}

0 comments on commit 9e96a19

Please sign in to comment.