Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FilesystemPathParents #1292

Merged
merged 2 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions NAS2D/FilesystemPathParents.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "FilesystemPathParents.h"

#include <algorithm>


namespace
{
std::size_t parentCount(const NAS2D::FilesystemPath& path)
{
std::size_t count = 1;
for (auto lastPath = path, nextPath = path.parent(); lastPath != nextPath;)
{
++count;
lastPath = nextPath;
nextPath = nextPath.parent();
}
return count;
}
}


namespace NAS2D
{
static_assert(std::forward_iterator<FilesystemPathParents::Iterator>);


FilesystemPathParents::FilesystemPathParents(const FilesystemPath& folder) :
FilesystemPathParents(folder, parentCount(folder))
{
}


FilesystemPathParents::FilesystemPathParents(const FilesystemPath& folder, std::size_t maxLevels) :
mPath{folder},
mMaxLevels{std::min(maxLevels, parentCount(folder))}
{
}


std::size_t FilesystemPathParents::size() const
{
return mMaxLevels;
}


FilesystemPathParents::Iterator FilesystemPathParents::begin() const
{
return {mPath, mMaxLevels};
}


FilesystemPathParents::Iterator FilesystemPathParents::end() const
{
return {};
}


FilesystemPathParents::Iterator::Iterator() :
FilesystemPathParents::Iterator::Iterator("", 0)
{
}


FilesystemPathParents::Iterator::Iterator(const FilesystemPath& folder, std::size_t levelsRemaining) :
mPath{folder},
mLevelsRemaining{levelsRemaining}
{
}


bool FilesystemPathParents::Iterator::operator==(const Iterator& other) const
{
return mLevelsRemaining == other.mLevelsRemaining && (mLevelsRemaining == 0 || mPath == other.mPath);
}


FilesystemPathParents::Iterator& FilesystemPathParents::Iterator::operator++()
{
if (mLevelsRemaining > 0)
{
mPath = mPath.parent();
--mLevelsRemaining;
}
return *this;
}


FilesystemPathParents::Iterator FilesystemPathParents::Iterator::operator++(int)
{
auto temp = *this;
++*this;
return temp;
}


const FilesystemPath& FilesystemPathParents::Iterator::operator*() const
{
return mPath;
}
}
48 changes: 48 additions & 0 deletions NAS2D/FilesystemPathParents.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once

#include "FilesystemPath.h"


namespace NAS2D
{
class FilesystemPathParents
{
public:
class Iterator;

FilesystemPathParents(const FilesystemPath& folder);
FilesystemPathParents(const FilesystemPath& folder, std::size_t maxLevels);

std::size_t size() const;

Iterator begin() const;
Iterator end() const;

private:
FilesystemPath mPath;
std::size_t mMaxLevels;


public:
class Iterator
{
public:
using value_type = FilesystemPath;
using difference_type = std::ptrdiff_t;

Iterator();
Iterator(const FilesystemPath& folder, std::size_t levelsRemaining);

bool operator==(const Iterator& other) const;

Iterator& operator++();
Iterator operator++(int);

const FilesystemPath& operator*() const;

private:
FilesystemPath mPath;
std::size_t mLevelsRemaining;
};
};
}
2 changes: 2 additions & 0 deletions NAS2D/NAS2D.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
<ClCompile Include="EventHandler.cpp" />
<ClCompile Include="Filesystem.cpp" />
<ClCompile Include="FilesystemPath.cpp" />
<ClCompile Include="FilesystemPathParents.cpp" />
<ClCompile Include="FpsCounter.cpp" />
<ClCompile Include="Game.cpp" />
<ClCompile Include="ParserHelper.cpp" />
Expand Down Expand Up @@ -214,6 +215,7 @@
<ClInclude Include="EventHandler.h" />
<ClInclude Include="Filesystem.h" />
<ClInclude Include="FilesystemPath.h" />
<ClInclude Include="FilesystemPathParents.h" />
<ClInclude Include="FpsCounter.h" />
<ClInclude Include="Game.h" />
<ClInclude Include="Math\Angle.h" />
Expand Down
6 changes: 6 additions & 0 deletions NAS2D/NAS2D.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
<ClCompile Include="FilesystemPath.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FilesystemPathParents.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FpsCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
Expand Down Expand Up @@ -236,6 +239,9 @@
<ClInclude Include="FilesystemPath.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FilesystemPathParents.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FpsCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand Down
45 changes: 45 additions & 0 deletions test/FilesystemPathParents.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "NAS2D/FilesystemPathParents.h"

#include <gtest/gtest.h>
#include <gmock/gmock.h>


TEST(FilesystemPathParents, sizeRelativeTrailingSlash) {
EXPECT_EQ(1u, NAS2D::FilesystemPathParents{""}.size());
EXPECT_EQ(2u, NAS2D::FilesystemPathParents{"a/"}.size());
EXPECT_EQ(3u, NAS2D::FilesystemPathParents{"a/b/"}.size());
EXPECT_EQ(4u, NAS2D::FilesystemPathParents{"a/b/c/"}.size());
}

TEST(FilesystemPathParents, sizeRelativeNoTrailingSlash) {
EXPECT_EQ(1u, NAS2D::FilesystemPathParents{""}.size());
EXPECT_EQ(2u, NAS2D::FilesystemPathParents{"a"}.size());
EXPECT_EQ(3u, NAS2D::FilesystemPathParents{"a/b"}.size());
EXPECT_EQ(4u, NAS2D::FilesystemPathParents{"a/b/c"}.size());
}

TEST(FilesystemPathParents, sizeAbsoluteTrailingSlash) {
EXPECT_EQ(1u, NAS2D::FilesystemPathParents{"/"}.size());
EXPECT_EQ(2u, NAS2D::FilesystemPathParents{"/a/"}.size());
EXPECT_EQ(3u, NAS2D::FilesystemPathParents{"/a/b/"}.size());
EXPECT_EQ(4u, NAS2D::FilesystemPathParents{"/a/b/c/"}.size());
}

TEST(FilesystemPathParents, sizeAbsoluteNoTrailingSlash) {
EXPECT_EQ(1u, NAS2D::FilesystemPathParents{"/"}.size());
EXPECT_EQ(2u, NAS2D::FilesystemPathParents{"/a"}.size());
EXPECT_EQ(3u, NAS2D::FilesystemPathParents{"/a/b"}.size());
EXPECT_EQ(4u, NAS2D::FilesystemPathParents{"/a/b/c"}.size());
}

TEST(FilesystemPathParents, iterationValuesRelative) {
const auto parentPaths = NAS2D::FilesystemPathParents("a/b/c/");
const auto paths = std::vector(parentPaths.begin(), parentPaths.end());
ASSERT_THAT(paths, testing::ElementsAre("a/b/c/", "a/b/", "a/", ""));
}

TEST(FilesystemPathParents, iterationValuesAbsolute) {
const auto parentPaths = NAS2D::FilesystemPathParents("/a/b/c/");
const auto paths = std::vector(parentPaths.begin(), parentPaths.end());
ASSERT_THAT(paths, testing::ElementsAre("/a/b/c/", "/a/b/", "/a/", "/"));
}
1 change: 1 addition & 0 deletions test/test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
<ClCompile Include="Dictionary.test.cpp" />
<ClCompile Include="Filesystem.test.cpp" />
<ClCompile Include="FilesystemPath.test.cpp" />
<ClCompile Include="FilesystemPathParents.test.cpp" />
<ClCompile Include="ParserHelper.test.cpp" />
<ClCompile Include="StringFrom.test.cpp" />
<ClCompile Include="StringFromTo.test.cpp" />
Expand Down