kinect/codes/Azure-Kinect-Sensor-SDK/tools/k4aviewer/platform/windows/filesystem17.cpp

237 lines
4.7 KiB
C++
Raw Normal View History

2024-03-06 18:05:53 +00:00
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Associated header
//
#include "filesystem17.h"
// System headers
//
// Library headers
//
#define NOMINMAX
#include "Windows.h"
#include <locale>
#include <codecvt>
#include "PathCch.h"
#include "Shlwapi.h"
// Project headers
//
#include "k4aviewerutil.h"
using namespace std17::filesystem;
struct std17::filesystem::directory_iterator_impl
{
directory_iterator_impl(const path &p)
{
end = false;
path searchPath = p;
searchPath.append("*");
hFindFile = FindFirstFile(searchPath.c_str(), &findData);
if (hFindFile == INVALID_HANDLE_VALUE)
{
end = true;
return;
}
// FindFirstFile/FindNextFile return the '.' and '..' special directories,
// but std::filesystem omits them, so we want to mimic that behavior
//
while (!end && (!strcmp(".", findData.cFileName) || !strcmp("..", findData.cFileName)))
{
advance();
}
}
directory_iterator_impl &advance()
{
end = !FindNextFile(hFindFile, &findData);
return *this;
}
~directory_iterator_impl()
{
if (hFindFile)
{
FindClose(hFindFile);
}
}
WIN32_FIND_DATAA findData{};
HANDLE hFindFile = nullptr;
bool end = false;
};
path::path(const char *p)
{
m_path = p;
}
path &path::append(const char *p)
{
if (m_path.size() != 0 && m_path[m_path.size() - 1] != '\\')
{
m_path += "\\";
}
m_path += p;
return *this;
}
path &path::concat(const char *p)
{
m_path += p;
return *this;
}
const char *path::c_str() const
{
return m_path.c_str();
}
std::string path::string() const
{
return m_path;
}
bool path::exists(const path &path)
{
const DWORD attributes = GetFileAttributes(path.c_str());
return attributes != INVALID_FILE_ATTRIBUTES;
}
bool path::is_directory(const path &path)
{
const DWORD attributes = GetFileAttributes(path.c_str());
return attributes != INVALID_FILE_ATTRIBUTES && attributes & FILE_ATTRIBUTE_DIRECTORY;
}
path path::filename() const
{
std::string filename = m_path;
PathStripPath(&filename[0]);
return path(filename.c_str());
}
path path::extension() const
{
std::string filenameStr = filename().string();
size_t lastPeriod = filenameStr.rfind('.');
if (lastPeriod == std::string::npos || lastPeriod == 0 || filenameStr == "..")
{
return path("");
}
return path(filenameStr.substr(lastPeriod).c_str());
}
path path::parent_path() const
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wsParentPath = converter.from_bytes(m_path);
PathCchRemoveFileSpec(&wsParentPath[0], wsParentPath.size());
std::string resultPath = converter.to_bytes(wsParentPath);
return path(resultPath.c_str());
}
bool directory_entry::exists() const
{
return path::exists(m_path);
}
bool directory_entry::is_directory() const
{
return path::is_directory(m_path);
}
path std17::filesystem::current_path()
{
const DWORD size = GetCurrentDirectory(0, nullptr);
std::string pathStr;
pathStr.resize(size);
GetCurrentDirectory(size, &pathStr[0]);
return path(pathStr.c_str());
}
directory_iterator::directory_iterator() : m_impl(nullptr) {}
directory_iterator::directory_iterator(const path &p) : m_impl(std::make_shared<directory_iterator_impl>(p))
{
if (m_impl->end)
{
m_impl.reset();
return;
}
m_directory = p;
update_entry_path();
}
directory_iterator directory_iterator::end(const directory_iterator &)
{
return directory_iterator();
}
directory_iterator &directory_iterator::operator++()
{
if (m_impl)
{
m_impl->advance();
}
if (m_impl->end)
{
m_impl.reset();
}
else
{
update_entry_path();
}
return *this;
}
bool directory_iterator::operator!=(const directory_iterator &other)
{
// This is not strictly true, but we only need operator!= to support iterator loops
// (i.e. they only need to return equal if they're both the end iterator)
//
return !(m_impl == nullptr && other.m_impl == nullptr);
}
const directory_entry &directory_iterator::operator*() const
{
if (!m_impl)
{
// then they're trying to deference an invalid iterator - segfault
//
directory_entry *e = nullptr;
return *e;
}
return m_current;
}
const directory_entry *directory_iterator::operator->() const
{
if (!m_impl)
{
return nullptr;
}
return &m_current;
}
void directory_iterator::update_entry_path()
{
m_current.m_path = m_directory;
m_current.m_path.append(m_impl->findData.cFileName);
}