Browse Source

Add `XDG_DATA_DIRS` to MPQ search paths

Fixes #5304
pull/5312/head
Gleb Mazovetskiy 4 years ago
parent
commit
9feb3139e2
  1. 18
      Source/init.cpp
  2. 98
      Source/utils/str_split.hpp

18
Source/init.cpp

@ -23,6 +23,7 @@
#include "utils/language.h"
#include "utils/log.hpp"
#include "utils/paths.h"
#include "utils/str_split.hpp"
#include "utils/ui_fwd.h"
#include "utils/utf8.hpp"
@ -93,8 +94,21 @@ std::vector<std::string> GetMPQSearchPaths()
paths.pop_back();
#if defined(__unix__) && !defined(__ANDROID__)
paths.emplace_back("/usr/share/diasurgical/devilutionx/");
paths.emplace_back("/usr/local/share/diasurgical/devilutionx/");
// `XDG_DATA_HOME` is usually the root path of `paths::PrefPath()`, so we only
// add `XDG_DATA_DIRS`.
const char *xdgDataDirs = std::getenv("XDG_DATA_DIRS");
if (xdgDataDirs != nullptr) {
for (const string_view path : SplitByChar(xdgDataDirs, ':')) {
std::string fullPath(path);
if (!path.empty() && path.back() != '/')
fullPath += '/';
fullPath.append("diasurgical/devilutionx/");
paths.push_back(std::move(fullPath));
}
} else {
paths.emplace_back("/usr/local/share/diasurgical/devilutionx/");
paths.emplace_back("/usr/share/diasurgical/devilutionx/");
}
#elif defined(NXDK)
paths.emplace_back("D:\\");
#elif (defined(_WIN64) || defined(_WIN32)) && !defined(__UWP__) && !defined(NXDK)

98
Source/utils/str_split.hpp

@ -0,0 +1,98 @@
#pragma once
#include <iterator>
#include <type_traits>
#include "utils/stdcompat/string_view.hpp"
namespace devilution {
class SplitByCharIterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = string_view;
using reference = std::add_lvalue_reference<value_type>::type;
using pointer = std::add_pointer<value_type>::type;
static SplitByCharIterator begin(string_view text, char split_by) // NOLINT(readability-identifier-naming)
{
return SplitByCharIterator(split_by, text, text.substr(0, text.find(split_by)));
}
static SplitByCharIterator end(string_view text, char split_by) // NOLINT(readability-identifier-naming)
{
return SplitByCharIterator(split_by, text, text.substr(text.size()));
}
[[nodiscard]] string_view operator*() const
{
return slice_;
}
[[nodiscard]] const string_view *operator->() const
{
return &slice_;
}
SplitByCharIterator &operator++()
{
slice_ = text_.substr(slice_.data() - text_.data() + slice_.size());
if (!slice_.empty())
slice_.remove_prefix(1); // skip the split_by char
slice_ = slice_.substr(0, slice_.find(split_by_));
return *this;
}
SplitByCharIterator operator++(int)
{
auto copy = *this;
++(*this);
return copy;
}
bool operator==(const SplitByCharIterator &rhs) const
{
return slice_.data() == rhs.slice_.data();
}
bool operator!=(const SplitByCharIterator &rhs) const
{
return !(*this == rhs);
}
private:
SplitByCharIterator(char split_by, string_view text, string_view slice)
: split_by_(split_by)
, text_(text)
, slice_(slice)
{
}
const char split_by_;
const string_view text_;
string_view slice_;
};
class SplitByChar {
public:
explicit SplitByChar(string_view text, char split_by)
: text_(text)
, split_by_(split_by)
{
}
[[nodiscard]] SplitByCharIterator begin() const // NOLINT(readability-identifier-naming)
{
return SplitByCharIterator::begin(text_, split_by_);
}
[[nodiscard]] SplitByCharIterator end() const // NOLINT(readability-identifier-naming)
{
return SplitByCharIterator::end(text_, split_by_);
}
private:
const string_view text_;
const char split_by_;
};
} // namespace devilution
Loading…
Cancel
Save