Compare commits
2 Commits
e6556c6f90
...
cbd4efb0f9
Author | SHA1 | Date | |
---|---|---|---|
cbd4efb0f9 | |||
d0be5f7739 |
@ -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
129
source/mijin/types/path.hpp
Normal 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)
|
@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <charconv>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
Loading…
x
Reference in New Issue
Block a user