Compare commits

..

2 Commits

3 changed files with 132 additions and 2 deletions

View File

@ -779,7 +779,7 @@ void TaskHandle::cancel() const MIJIN_NOEXCEPT
}
}
Optional<std::source_location> TaskHandle::getLocation() const noexcept
Optional<std::source_location> TaskHandle::getLocation() const MIJIN_NOEXCEPT
{
if (std::shared_ptr<TaskSharedState> state = state_.lock())
{
@ -825,7 +825,7 @@ FuturePtr<TResult> TaskLoop<TAllocator>::addTaskImpl(TaskBase<TResult, TAllocato
// add tasks to a seperate vector first as we might be running another task right now
TAllocator<WrappedTask<TaskBase<TResult, TAllocator>>> allocator(allocator_);
addStoredTask(StoredTask(wrapTask(std::move(allocator), std::move(task)), std::move(setFuture), std::move(future)));
addStoredTask(StoredTask(wrapTask(std::move(allocator), std::move(task)), std::move(setFuture), future));
return future;
}

129
source/mijin/types/path.hpp Normal file
View File

@ -0,0 +1,129 @@
#pragma once
#if !defined(MIJIN_TYPES_PATH_HPP_INCLUDED)
#define MIJIN_TYPES_PATH_HPP_INCLUDED 1
#include "../internal/common.hpp"
#include <string>
#include <type_traits>
namespace mijin
{
template<typename TChar = char, TChar separator = TChar('/'), typename TTraits = std::char_traits<TChar>, template<typename> typename TAllocator = MIJIN_DEFAULT_ALLOCATOR>
class BasePath
{
public:
using string_t = std::basic_string<TChar, TTraits, TAllocator<char>>;
using size_type = string_t::size_type;
using difference_type = string_t::difference_type;
private:
string_t storage_;
public:
BasePath() = default;
BasePath(const BasePath&) = default;
BasePath(BasePath&&) = default;
BasePath(string_t string) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible<string_t>()) : storage_(std::move(string)) {
simplify();
}
BasePath& operator=(const BasePath&) = default;
BasePath& operator=(BasePath&&) = default;
auto operator<=>(const BasePath&) const noexcept = default;
[[nodiscard]]
const string_t& string() const MIJIN_NOEXCEPT
{
return storage_;
}
private:
void simplify() MIJIN_NOEXCEPT;
};
using Path = BasePath<char>;
using WPath = BasePath<wchar_t>;
template<typename TChar, TChar separator, typename TTraits, template<typename> typename TAllocator>
void BasePath<TChar, separator, TTraits, TAllocator>::simplify() MIJIN_NOEXCEPT
{
// step 1: remove double slashes
difference_type moveBy = 0;
for (auto it = std::next(storage_.begin()); it < storage_.end(); ++it)
{
const bool doubleSlash = (*it == separator && *std::prev(it) == separator); // check this before moving the current character, as that might create a double slash itself
if (moveBy > 0) {
*std::prev(it, moveBy) = *it;
}
if (doubleSlash) {
++moveBy;
}
}
// step 1.5: remove trailing slash (but only if it's not the only remaining char)
if (moveBy < static_cast<difference_type>(storage_.size() - 1) && storage_[storage_.size() - moveBy - 1] == separator) {
++moveBy;
}
storage_.resize(storage_.size() - moveBy);
// step 2: get rid of any "/.." together with the preceeding segment
moveBy = 0;
for (auto it = std::next(storage_.begin(), 2); it < storage_.end(); ++it)
{
if (moveBy > 0)
{
*std::prev(it, moveBy) = *it;
}
if (*std::prev(it, moveBy) == TChar('.') && *std::prev(it, moveBy + 1) == TChar('.') && *std::prev(it, moveBy + 2) == separator
&& (std::next(it) == storage_.end() || *std::next(it) == separator))
{
if (std::prev(it, moveBy + 2) == storage_.begin())
{
// leading "/.." -> just remove it
moveBy += 3;
continue;
}
// find the start of the preceeding segment
for (auto itStart = std::prev(it, moveBy + 3);; --itStart)
{
if (*std::prev(itStart) == separator || std::prev(itStart) == storage_.begin())
{
// /path/with/../double/dot
// itStart --A A
// it -------------|
// remove everything from itStart to it + two slashes
moveBy += std::distance(itStart, std::prev(it, moveBy)) + 2; // skip it all
break;
}
}
}
}
storage_.resize(storage_.size() - moveBy);
// step 3: eliminate any segments that are just "."
moveBy = 0;
if (storage_.size() == 1) {
return; // just stop it here
}
for (auto it = storage_.begin(); it < storage_.end(); ++it)
{
const bool atStart = (it == storage_.begin());
const bool atEnd = (std::next(it) == storage_.end());
const bool emptyEle = (*it == TChar('.') // char is a dot
&& (atStart || *std::prev(it, moveBy + 1) == separator) // previous is a slash or doesn't exist
&& (atEnd || *std::next(it) == separator)); // next is a slash or doesn't exist
if (moveBy > 0) {
*std::prev(it, moveBy) = *it;
}
if (emptyEle) {
moveBy += 2;
if (!atEnd) {
++it; // skip the next one
}
}
}
storage_.resize(storage_.size() - moveBy);
}
} // namespace shiken
#endif // !defined(MIJIN_TYPES_PATH_HPP_INCLUDED)

View File

@ -7,6 +7,7 @@
#include <algorithm>
#include <array>
#include <charconv>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iterator>