add io::directory_iterator
This commit is contained in:
parent
c3066eebd3
commit
347d76870a
@ -94,8 +94,7 @@ static void add_layouts(
|
||||
if (!io::is_directory(folder)) {
|
||||
return;
|
||||
}
|
||||
for (auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||
io::path file = folder / entry.path().filename().u8string();
|
||||
for (const auto& file : io::directory_iterator(folder)) {
|
||||
if (file.extension() != ".xml") continue;
|
||||
std::string name = prefix + ":" + file.stem();
|
||||
loader.add(
|
||||
|
||||
@ -50,8 +50,7 @@ static void detect_defs(
|
||||
if (!io::is_directory(folder)) {
|
||||
return;
|
||||
}
|
||||
for (const auto& entry : std::filesystem::directory_iterator(io::resolve(folder))) {
|
||||
io::path file = folder / entry.path().filename().u8string();
|
||||
for (const auto& file : io::directory_iterator(folder)) {
|
||||
std::string name = file.stem();
|
||||
if (name[0] == '_') {
|
||||
continue;
|
||||
@ -75,8 +74,7 @@ static void detect_defs_pairs(
|
||||
if (!io::is_directory(folder)) {
|
||||
return;
|
||||
}
|
||||
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||
io::path file = folder / entry.path().filename().u8string();
|
||||
for (const auto& file : io::directory_iterator(folder)) {
|
||||
std::string name = file.stem();
|
||||
if (name[0] == '_') {
|
||||
continue;
|
||||
@ -747,8 +745,7 @@ static inline void foreach_file(
|
||||
if (!io::is_directory(dir)) {
|
||||
return;
|
||||
}
|
||||
for (const auto& entry : fs::directory_iterator(io::resolve(dir))) {
|
||||
io::path path = dir / entry.path().filename().u8string();
|
||||
for (const auto& path : io::directory_iterator(dir)) {
|
||||
if (io::is_directory(path)) {
|
||||
continue;
|
||||
}
|
||||
@ -808,8 +805,7 @@ void ContentLoader::load() {
|
||||
// Load block materials
|
||||
io::path materialsDir = folder / "block_materials";
|
||||
if (io::is_directory(materialsDir)) {
|
||||
for (const auto& entry : fs::directory_iterator(io::resolve(materialsDir))) {
|
||||
io::path file = materialsDir / entry.path().filename().u8string();
|
||||
for (const auto& file : io::directory_iterator(materialsDir)) {
|
||||
auto [packid, full, filename] =
|
||||
create_unit_id(pack->id, file.stem());
|
||||
loadBlockMaterial(
|
||||
|
||||
@ -129,8 +129,7 @@ void ContentPack::scanFolder(
|
||||
if (!io::is_directory(folder)) {
|
||||
return;
|
||||
}
|
||||
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||
io::path packFolder = folder / entry.path().filename().u8string();
|
||||
for (const auto& packFolder : io::directory_iterator(folder)) {
|
||||
if (!io::is_directory(packFolder)) continue;
|
||||
if (!is_pack(packFolder)) continue;
|
||||
try {
|
||||
|
||||
@ -23,6 +23,7 @@ namespace io {
|
||||
virtual void mkdirs(std::string_view path) = 0;
|
||||
virtual bool remove(std::string_view path) = 0;
|
||||
virtual uint64_t removeAll(std::string_view path) = 0;
|
||||
virtual std::unique_ptr<PathsGenerator> list(std::string_view path) = 0;
|
||||
};
|
||||
|
||||
class SubDevice : public Device {
|
||||
@ -69,6 +70,10 @@ namespace io {
|
||||
uint64_t removeAll(std::string_view path) override {
|
||||
return parent->removeAll((root / path).pathPart());
|
||||
}
|
||||
|
||||
std::unique_ptr<PathsGenerator> list(std::string_view path) override {
|
||||
return parent->list((root / path).pathPart());
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<Device> parent;
|
||||
path root;
|
||||
|
||||
@ -4,9 +4,10 @@
|
||||
#include <filesystem>
|
||||
|
||||
using namespace io;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::filesystem::path StdfsDevice::resolve(std::string_view path) {
|
||||
return root / std::filesystem::u8path(path);
|
||||
fs::path StdfsDevice::resolve(std::string_view path) {
|
||||
return root / fs::u8path(path);
|
||||
}
|
||||
|
||||
void StdfsDevice::write(std::string_view path, const void* data, size_t size) {
|
||||
@ -29,35 +30,58 @@ void StdfsDevice::read(std::string_view path, void* data, size_t size) {
|
||||
|
||||
size_t StdfsDevice::size(std::string_view path) {
|
||||
auto resolved = resolve(path);
|
||||
return std::filesystem::file_size(resolved);
|
||||
return fs::file_size(resolved);
|
||||
}
|
||||
|
||||
bool StdfsDevice::exists(std::string_view path) {
|
||||
auto resolved = resolve(path);
|
||||
return std::filesystem::exists(resolved);
|
||||
return fs::exists(resolved);
|
||||
}
|
||||
|
||||
bool StdfsDevice::isdir(std::string_view path) {
|
||||
auto resolved = resolve(path);
|
||||
return std::filesystem::is_directory(resolved);
|
||||
return fs::is_directory(resolved);
|
||||
}
|
||||
|
||||
bool StdfsDevice::isfile(std::string_view path) {
|
||||
auto resolved = resolve(path);
|
||||
return std::filesystem::is_regular_file(resolved);
|
||||
return fs::is_regular_file(resolved);
|
||||
}
|
||||
|
||||
void StdfsDevice::mkdirs(std::string_view path) {
|
||||
auto resolved = resolve(path);
|
||||
std::filesystem::create_directories(resolved);
|
||||
fs::create_directories(resolved);
|
||||
}
|
||||
|
||||
bool StdfsDevice::remove(std::string_view path) {
|
||||
auto resolved = resolve(path);
|
||||
return std::filesystem::remove(resolved);
|
||||
return fs::remove(resolved);
|
||||
}
|
||||
|
||||
uint64_t StdfsDevice::removeAll(std::string_view path) {
|
||||
auto resolved = resolve(path);
|
||||
return std::filesystem::remove_all(resolved);
|
||||
return fs::remove_all(resolved);
|
||||
}
|
||||
|
||||
class StdfsPathsGenerator : public PathsGenerator {
|
||||
public:
|
||||
StdfsPathsGenerator(fs::path root) : root(std::move(root)) {
|
||||
it = fs::directory_iterator(this->root);
|
||||
}
|
||||
|
||||
bool next(io::path& path) override {
|
||||
if (it == fs::directory_iterator()) {
|
||||
return false;
|
||||
}
|
||||
path = it->path().filename().u8string();
|
||||
it++;
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
fs::path root;
|
||||
fs::directory_iterator it;
|
||||
};
|
||||
|
||||
std::unique_ptr<PathsGenerator> StdfsDevice::list(std::string_view path) {
|
||||
return std::make_unique<StdfsPathsGenerator>(root / fs::u8path(path));
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ namespace io {
|
||||
void mkdirs(std::string_view path) override;
|
||||
bool remove(std::string_view path) override;
|
||||
uint64_t removeAll(std::string_view path) override;
|
||||
std::unique_ptr<PathsGenerator> list(std::string_view path) override;
|
||||
private:
|
||||
std::filesystem::path root;
|
||||
};
|
||||
|
||||
@ -145,11 +145,10 @@ std::vector<io::path> EnginePaths::scanForWorlds() const {
|
||||
auto folder = getWorldsFolder();
|
||||
if (!io::is_directory(folder)) return folders;
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(io::resolve(folder))) {
|
||||
if (!entry.is_directory()) {
|
||||
for (const auto& worldFolder : io::directory_iterator(folder)) {
|
||||
if (!io::is_directory(worldFolder)) {
|
||||
continue;
|
||||
}
|
||||
io::path worldFolder = folder / entry.path().filename().u8string();
|
||||
auto worldFile = worldFolder / WorldFiles::WORLD_FILE;
|
||||
if (!io::is_regular_file(worldFile)) {
|
||||
continue;
|
||||
@ -271,9 +270,8 @@ std::vector<std::string> ResPaths::listdirRaw(const std::string& folderName) con
|
||||
auto& root = roots[i];
|
||||
auto folder = root.path / fs::u8path(folderName);
|
||||
if (!io::is_directory(folder)) continue;
|
||||
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||
auto name = entry.path().filename().u8string();
|
||||
entries.emplace_back(root.name + ":" + folderName + "/" + name);
|
||||
for (const auto& file : io::directory_iterator(folder)) {
|
||||
entries.emplace_back(root.name + ":" + folderName + "/" + file.name());
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
@ -287,8 +285,8 @@ std::vector<io::path> ResPaths::listdir(
|
||||
auto& root = roots[i];
|
||||
io::path folder = root.path / folderName;
|
||||
if (!io::is_directory(folder)) continue;
|
||||
for (const auto& entry : fs::directory_iterator(io::resolve(folder))) {
|
||||
entries.push_back(folder / entry.path().filename().u8string());
|
||||
for (const auto& entry : io::directory_iterator(folder)) {
|
||||
entries.push_back(folder / entry);
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
|
||||
@ -49,6 +49,12 @@ void io::create_subdevice(
|
||||
set_device(name, std::make_shared<io::SubDevice>(parentDevice, root.pathPart()));
|
||||
}
|
||||
|
||||
io::directory_iterator::directory_iterator(const io::path& folder)
|
||||
: folder(folder) {
|
||||
auto& device = io::require_device(folder.entryPoint());
|
||||
generator = device.list(folder.pathPart());
|
||||
}
|
||||
|
||||
io::rafile::rafile(const io::path& filename)
|
||||
: file(io::resolve(filename), std::ios::binary | std::ios::ate) {
|
||||
if (!file) {
|
||||
@ -171,7 +177,7 @@ std::vector<std::string> io::read_list(const io::path& filename) {
|
||||
}
|
||||
|
||||
bool io::is_regular_file(const io::path& file) {
|
||||
if (file.empty()) {
|
||||
if (file.emptyOrInvalid()) {
|
||||
return false;
|
||||
}
|
||||
auto device = io::get_device(file.entryPoint());
|
||||
@ -182,7 +188,7 @@ bool io::is_regular_file(const io::path& file) {
|
||||
}
|
||||
|
||||
bool io::is_directory(const io::path& file) {
|
||||
if (file.empty()) {
|
||||
if (file.emptyOrInvalid()) {
|
||||
return false;
|
||||
}
|
||||
auto device = io::get_device(file.entryPoint());
|
||||
@ -193,7 +199,7 @@ bool io::is_directory(const io::path& file) {
|
||||
}
|
||||
|
||||
bool io::exists(const io::path& file) {
|
||||
if (file.empty()) {
|
||||
if (file.emptyOrInvalid()) {
|
||||
return false;
|
||||
}
|
||||
auto device = io::get_device(file.entryPoint());
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <iterator>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -34,6 +35,75 @@ namespace io {
|
||||
size_t length() const;
|
||||
};
|
||||
|
||||
class directory_iterator_impl {
|
||||
public:
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = path;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = path*;
|
||||
using reference = path&;
|
||||
|
||||
directory_iterator_impl(
|
||||
PathsGenerator& generator, const path& folder, bool end = false
|
||||
)
|
||||
: generator(generator), folder(folder), isend(end) {
|
||||
if (!isend && this->generator.next(current)) {
|
||||
isend = false;
|
||||
current = folder / current;
|
||||
} else {
|
||||
isend = true;
|
||||
}
|
||||
}
|
||||
|
||||
reference operator*() {
|
||||
return current;
|
||||
}
|
||||
|
||||
pointer operator->() {
|
||||
return ¤t;
|
||||
}
|
||||
|
||||
directory_iterator_impl& operator++() {
|
||||
if (isend) {
|
||||
return *this;
|
||||
}
|
||||
if (generator.next(current)) {
|
||||
current = folder / current;
|
||||
} else {
|
||||
isend = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const directory_iterator_impl& other) const {
|
||||
return isend == other.isend;
|
||||
}
|
||||
|
||||
bool operator!=(const directory_iterator_impl& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
private:
|
||||
PathsGenerator& generator;
|
||||
path folder;
|
||||
path current;
|
||||
bool isend = false;
|
||||
};
|
||||
|
||||
class directory_iterator {
|
||||
std::unique_ptr<PathsGenerator> generator;
|
||||
path folder;
|
||||
public:
|
||||
directory_iterator(const path& folder);
|
||||
|
||||
directory_iterator_impl begin() {
|
||||
return directory_iterator_impl(*generator, folder);
|
||||
}
|
||||
|
||||
directory_iterator_impl end() {
|
||||
return directory_iterator_impl(*generator, "", true);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Write bytes array to the file without any extra data
|
||||
/// @param file target file
|
||||
/// @param data data bytes array
|
||||
@ -87,7 +157,11 @@ namespace io {
|
||||
|
||||
std::filesystem::path resolve(const io::path& file);
|
||||
|
||||
/// @brief Check if file is one of the supported data interchange formats
|
||||
bool is_data_file(const io::path& file);
|
||||
|
||||
/// @brief Check if file extension is one of the supported data interchange formats
|
||||
bool is_data_interchange_format(const std::string& ext);
|
||||
|
||||
dv::value read_object(const path& file);
|
||||
}
|
||||
|
||||
@ -127,6 +127,10 @@ namespace io {
|
||||
bool empty() const {
|
||||
return str.empty();
|
||||
}
|
||||
|
||||
bool emptyOrInvalid() const {
|
||||
return str.empty() || colonPos == std::string::npos;
|
||||
}
|
||||
private:
|
||||
/// @brief UTF-8 string contains entry_point:path or empty string
|
||||
std::string str;
|
||||
@ -135,4 +139,10 @@ namespace io {
|
||||
|
||||
void checkValid() const;
|
||||
};
|
||||
|
||||
class PathsGenerator {
|
||||
public:
|
||||
virtual ~PathsGenerator() = default;
|
||||
virtual bool next(path& dst) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@ -95,7 +95,8 @@ static int l_exists(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_isfile(lua::State* L) {
|
||||
io::path path = resolve_path_soft(lua::require_string(L, 1));
|
||||
const char* string =lua::require_string(L, 1);
|
||||
io::path path = resolve_path_soft(string);
|
||||
return lua::pushboolean(L, io::is_regular_file(path));
|
||||
}
|
||||
|
||||
@ -184,10 +185,8 @@ static int l_list(lua::State* L) {
|
||||
}
|
||||
lua::createtable(L, 0, 0);
|
||||
size_t index = 1;
|
||||
for (auto& entry : fs::directory_iterator(io::resolve(path))) {
|
||||
auto name = entry.path().filename().u8string();
|
||||
auto file = dirname + "/" + name;
|
||||
lua::pushstring(L, file);
|
||||
for (const auto& file : io::directory_iterator(path)) {
|
||||
lua::pushstring(L, file.string());
|
||||
lua::rawseti(L, index);
|
||||
index++;
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "data/dv.hpp"
|
||||
#include "lua_wrapper.hpp"
|
||||
#include "lua_custom_types.hpp"
|
||||
#include "lua_wrapper.hpp"
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
@ -68,7 +68,7 @@ namespace lua {
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<int n>
|
||||
template <int n>
|
||||
inline int pushvec_stack(lua::State* L, const glm::vec<n, float>& vec) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
pushnumber(L, vec[i]);
|
||||
@ -76,7 +76,7 @@ namespace lua {
|
||||
return n;
|
||||
}
|
||||
|
||||
template<int n>
|
||||
template <int n>
|
||||
inline int pushivec_stack(lua::State* L, const glm::vec<n, int>& vec) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
pushinteger(L, vec[i]);
|
||||
@ -108,10 +108,10 @@ namespace lua {
|
||||
|
||||
inline int pushquat(lua::State* L, glm::quat quat) {
|
||||
createtable(L, 4, 0);
|
||||
|
||||
|
||||
pushnumber(L, quat.w);
|
||||
rawseti(L, 1);
|
||||
|
||||
|
||||
pushnumber(L, quat.x);
|
||||
rawseti(L, 2);
|
||||
|
||||
@ -127,7 +127,7 @@ namespace lua {
|
||||
|
||||
pushnumber(L, quat.w);
|
||||
rawseti(L, 1);
|
||||
|
||||
|
||||
pushnumber(L, quat.x);
|
||||
rawseti(L, 2);
|
||||
|
||||
@ -287,8 +287,9 @@ namespace lua {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline std::enable_if_t<std::is_base_of_v<Userdata, T>>
|
||||
newusertype(lua::State* L) {
|
||||
inline std::enable_if_t<std::is_base_of_v<Userdata, T>> newusertype(
|
||||
lua::State* L
|
||||
) {
|
||||
const std::string& name = T::TYPENAME;
|
||||
usertypeNames[typeid(T)] = name;
|
||||
T::createMetatable(L);
|
||||
@ -386,7 +387,7 @@ namespace lua {
|
||||
rawgeti(L, 4);
|
||||
auto z = tonumber(L, -1);
|
||||
pop(L);
|
||||
|
||||
|
||||
pop(L);
|
||||
return glm::quat(x, y, z, w);
|
||||
}
|
||||
@ -445,8 +446,7 @@ namespace lua {
|
||||
|
||||
int pushvalue(lua::State*, const dv::value& value);
|
||||
|
||||
[[nodiscard]]
|
||||
dv::value tovalue(lua::State*, int idx);
|
||||
[[nodiscard]] dv::value tovalue(lua::State*, int idx);
|
||||
|
||||
inline bool getfield(lua::State* L, const std::string& name, int idx = -1) {
|
||||
lua_getfield(L, idx, name.c_str());
|
||||
@ -457,11 +457,13 @@ namespace lua {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int requirefield(lua::State* L, const std::string& name, int idx = -1) {
|
||||
inline int requirefield(
|
||||
lua::State* L, const std::string& name, int idx = -1
|
||||
) {
|
||||
if (getfield(L, name, idx)) {
|
||||
return 1;
|
||||
}
|
||||
throw std::runtime_error("object has no member '"+name+"'");
|
||||
throw std::runtime_error("object has no member '" + name + "'");
|
||||
}
|
||||
|
||||
inline bool hasfield(lua::State* L, const std::string& name, int idx = -1) {
|
||||
@ -637,7 +639,7 @@ namespace lua {
|
||||
}
|
||||
|
||||
inline const char* require_string_field(
|
||||
lua::State* L, const std::string& name, int idx=-1
|
||||
lua::State* L, const std::string& name, int idx = -1
|
||||
) {
|
||||
requirefield(L, name, idx);
|
||||
auto value = require_string(L, -1);
|
||||
@ -646,7 +648,7 @@ namespace lua {
|
||||
}
|
||||
|
||||
inline Integer require_integer_field(
|
||||
lua::State* L, const std::string& name, int idx=-1
|
||||
lua::State* L, const std::string& name, int idx = -1
|
||||
) {
|
||||
requirefield(L, name, idx);
|
||||
auto value = tointeger(L, -1);
|
||||
@ -655,7 +657,7 @@ namespace lua {
|
||||
}
|
||||
|
||||
inline Number require_number_field(
|
||||
lua::State* L, const std::string& name, int idx=-1
|
||||
lua::State* L, const std::string& name, int idx = -1
|
||||
) {
|
||||
requirefield(L, name, idx);
|
||||
auto value = tonumber(L, -1);
|
||||
@ -664,7 +666,7 @@ namespace lua {
|
||||
}
|
||||
|
||||
inline bool get_boolean_field(
|
||||
lua::State* L, const std::string& name, bool def, int idx=-1
|
||||
lua::State* L, const std::string& name, bool def, int idx = -1
|
||||
) {
|
||||
if (getfield(L, name, idx)) {
|
||||
bool value = toboolean(L, -1);
|
||||
@ -675,7 +677,7 @@ namespace lua {
|
||||
}
|
||||
|
||||
inline Integer get_integer_field(
|
||||
lua::State* L, const std::string& name, Integer def, int idx=-1
|
||||
lua::State* L, const std::string& name, Integer def, int idx = -1
|
||||
) {
|
||||
if (getfield(L, name, idx)) {
|
||||
auto value = tointeger(L, -1);
|
||||
@ -686,7 +688,7 @@ namespace lua {
|
||||
}
|
||||
|
||||
inline Number get_number_field(
|
||||
lua::State* L, const std::string& name, Number def, int idx=-1
|
||||
lua::State* L, const std::string& name, Number def, int idx = -1
|
||||
) {
|
||||
if (getfield(L, name, idx)) {
|
||||
auto value = tonumber(L, -1);
|
||||
@ -697,15 +699,20 @@ namespace lua {
|
||||
}
|
||||
|
||||
inline Integer get_integer_field(
|
||||
lua::State* L, const std::string& name,
|
||||
Integer def, Integer min, Integer max, int idx=-1
|
||||
lua::State* L,
|
||||
const std::string& name,
|
||||
Integer def,
|
||||
Integer min,
|
||||
Integer max,
|
||||
int idx = -1
|
||||
) {
|
||||
if (getfield(L, name, idx)) {
|
||||
auto value = tointeger(L, -1);
|
||||
if (value < min || value > max) {
|
||||
throw std::runtime_error(
|
||||
"value is out of range ["
|
||||
+std::to_string(min)+", "+std::to_string(max)+"]");
|
||||
"value is out of range [" + std::to_string(min) + ", " +
|
||||
std::to_string(max) + "]"
|
||||
);
|
||||
}
|
||||
pop(L);
|
||||
return value;
|
||||
|
||||
@ -42,14 +42,14 @@ void WorldConverter::addRegionsTasks(
|
||||
if (!io::is_directory(regionsFolder)) {
|
||||
return;
|
||||
}
|
||||
for (const auto& file : fs::directory_iterator(io::resolve(regionsFolder))) {
|
||||
for (const auto& file :io::directory_iterator(regionsFolder)) {
|
||||
int x, z;
|
||||
std::string name = file.path().stem().string();
|
||||
std::string name = file.stem();
|
||||
if (!WorldRegions::parseRegionFilename(name, x, z)) {
|
||||
logger.error() << "could not parse region name " << name;
|
||||
continue;
|
||||
}
|
||||
tasks.push(ConvertTask {taskType, file.path().u8string(), x, z, layerid});
|
||||
tasks.push(ConvertTask {taskType, file, x, z, layerid});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user