Skip to content

Commit

Permalink
Merge pull request #174 from gon6109/filesystem
Browse files Browse the repository at this point in the history
Filesystem
  • Loading branch information
durswd committed Dec 1, 2019
2 parents c542fef + d5e3962 commit dbf5aa2
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 78 deletions.
21 changes: 21 additions & 0 deletions core/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ set(core_files
Common/Resources.h
Common/Resources.cpp
Common/StringHelper.h
Platform/FileSystem.h
Window/Window.h
Window/Window.cpp
Input/ButtonState.h
Expand Down Expand Up @@ -91,6 +92,26 @@ set(core_files
Sound/Sound.cpp
)

if(WIN32)

list(APPEND core_files
Platform/FileSystemWin.cpp
)

elseif(APPLE)

list(APPEND core_files
Platform/FileSystemMac.cpp
)

else()

list(APPEND core_files
Platform/FileSystemLinux.cpp
)

endif()

# specify project filters
foreach(FILE ${core_files})
# Get the directory of the source file
Expand Down
56 changes: 8 additions & 48 deletions core/src/Common/ResourceContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,8 @@
#include <mutex>
#include <string>

#if defined(_WIN32) || defined(__APPLE__)
#include <filesystem>
namespace fs = std::filesystem;
#else

#if __GNUC__ >= 8
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif

#endif

#include "../Common/Resource.h"

#if defined(_WIN32) || defined(__APPLE__)
#include <filesystem>
namespace fs = std::filesystem;
#else

#if __GNUC__ >= 8
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif

#endif
#include "../Platform/FileSystem.h"
#include "Resource.h"

namespace altseed {
class ResourceContainer {
Expand All @@ -46,7 +17,7 @@ class ResourceContainer {
private:
Resource* m_resourcePtr;
std::u16string m_path;
fs::file_time_type m_modifiedTime;
int32_t m_modifiedTime;

public:
ResourceInfomation(Resource* resource, std::u16string path) {
Expand All @@ -59,9 +30,9 @@ class ResourceContainer {

const std::u16string& GetPath() { return m_path; }

const fs::file_time_type GetModifiedTime() { return m_modifiedTime; }
const int32_t GetModifiedTime() { return m_modifiedTime; }

bool Reload(fs::file_time_type time) {
bool Reload(int32_t time) {
m_modifiedTime = time;
return m_resourcePtr->Reload();
}
Expand Down Expand Up @@ -117,20 +88,9 @@ class ResourceContainer {
}
}

static fs::file_time_type GetModifiedTime(const std::u16string path) {
fs::path p(path);
std::error_code ec;
auto ftime = fs::last_write_time(p, ec);
#ifndef _WIN32
if (ec.value() != 0) {
#ifndef _WIN32

// TODO: log failure to get time
return fs::file_time_type::min();
#endif
}
#endif
return ftime;
static int32_t GetModifiedTime(const std::u16string path) {
auto time = FileSystem::GetLastWriteTime(path);
return time;
}
};

Expand Down
129 changes: 129 additions & 0 deletions core/src/Common/StringHelper.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <array>
#include <codecvt>
#include <locale>

Expand All @@ -19,4 +20,132 @@ static std::string utf16_to_utf8(const std::u16string& s) {
#endif
}

static bool IsU8LaterByte(char ch) { return 0x80 <= uint8_t(ch) && uint8_t(ch) < 0xC0; }

static int GetU8ByteCount(char ch) {
if (0 <= uint8_t(ch) && uint8_t(ch) < 0x80) {
return 1;
}
if (0xC2 <= uint8_t(ch) && uint8_t(ch) < 0xE0) {
return 2;
}
if (0xE0 <= uint8_t(ch) && uint8_t(ch) < 0xF0) {
return 3;
}
if (0xF0 <= uint8_t(ch) && uint8_t(ch) < 0xF8) {
return 4;
}
return 0;
}

static bool ConvChU8ToU32(const std::array<char, 4>& u8Ch, char32_t& u32Ch) {
int numBytes = GetU8ByteCount(u8Ch[0]);
if (numBytes == 0) {
return false;
}
switch (numBytes) {
case 1:
u32Ch = char32_t(uint8_t(u8Ch[0]));
break;
case 2:
if (!IsU8LaterByte(u8Ch[1])) {
return false;
}
if ((uint8_t(u8Ch[0]) & 0x1E) == 0) {
return false;
}

u32Ch = char32_t(u8Ch[0] & 0x1F) << 6;
u32Ch |= char32_t(u8Ch[1] & 0x3F);
break;
case 3:
if (!IsU8LaterByte(u8Ch[1]) || !IsU8LaterByte(u8Ch[2])) {
return false;
}
if ((uint8_t(u8Ch[0]) & 0x0F) == 0 && (uint8_t(u8Ch[1]) & 0x20) == 0) {
return false;
}

u32Ch = char32_t(u8Ch[0] & 0x0F) << 12;
u32Ch |= char32_t(u8Ch[1] & 0x3F) << 6;
u32Ch |= char32_t(u8Ch[2] & 0x3F);
break;
case 4:
if (!IsU8LaterByte(u8Ch[1]) || !IsU8LaterByte(u8Ch[2]) || !IsU8LaterByte(u8Ch[3])) {
return false;
}
if ((uint8_t(u8Ch[0]) & 0x07) == 0 && (uint8_t(u8Ch[1]) & 0x30) == 0) {
return false;
}

u32Ch = char32_t(u8Ch[0] & 0x07) << 18;
u32Ch |= char32_t(u8Ch[1] & 0x3F) << 12;
u32Ch |= char32_t(u8Ch[2] & 0x3F) << 6;
u32Ch |= char32_t(u8Ch[3] & 0x3F);
break;
default:
return false;
}

return true;
}

static bool ConvChU32ToU16(const char32_t u32Ch, std::array<char16_t, 2>& u16Ch) {
if (u32Ch > 0x10FFFF) {
return false;
}

if (u32Ch < 0x10000) {
u16Ch[0] = char16_t(u32Ch);
u16Ch[1] = 0;
} else {
u16Ch[0] = char16_t((u32Ch - 0x10000) / 0x400 + 0xD800);
u16Ch[1] = char16_t((u32Ch - 0x10000) % 0x400 + 0xDC00);
}

return true;
}

static bool ConvChU8ToU16(const std::array<char, 4>& u8Ch, std::array<char16_t, 2>& u16Ch) {
char32_t u32Ch;
if (!ConvChU8ToU32(u8Ch, u32Ch)) {
return false;
}
if (!ConvChU32ToU16(u32Ch, u16Ch)) {
return false;
}
return true;
}

static std::u16string utf8_to_utf16(const std::string& u8Str) {
std::u16string u16Str;
for (auto u8It = u8Str.begin(); u8It != u8Str.end(); ++u8It) {
auto numBytes = GetU8ByteCount((*u8It));
if (numBytes == 0) {
return std::u16string();
}

std::array<char, 4> u8Ch;
u8Ch[0] = (*u8It);
for (int i = 1; i < numBytes; i++) {
++u8It;
if (u8It == u8Str.end()) {
return std::u16string();
}
u8Ch[i] = (*u8It);
}

std::array<char16_t, 2> u16Ch;
if (!ConvChU8ToU16(u8Ch, u16Ch)) {
return std::u16string();
}

u16Str.push_back(u16Ch[0]);
if (u16Ch[1] != 0) {
u16Str.push_back(u16Ch[1]);
}
}
return u16Str;
}

} // namespace altseed
52 changes: 22 additions & 30 deletions core/src/IO/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,9 @@
#include <fstream>
#include <stack>
#include "../Common/StringHelper.h"
#include "../Platform/FileSystem.h"
#include "PackFileReader.h"

#if defined(_WIN32) || defined(__APPLE__)
#include <filesystem>
namespace fs = std::filesystem;
#else

#if __GNUC__ >= 8
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif

#endif

namespace altseed {

std::shared_ptr<File> File::instance = nullptr;
Expand Down Expand Up @@ -63,7 +49,7 @@ StaticFile* File::CreateStaticFile(const char16_t* path) {
reader = new PackFileReader(zipFile, path, stat);
break;
}
} else if (fs::is_regular_file((*i)->GetPath() + path)) {
} else if (FileSystem::GetIsFile((*i)->GetPath() + path)) {
reader = new BaseFileReader(path);
}
}
Expand Down Expand Up @@ -100,7 +86,7 @@ StreamFile* File::CreateStreamFile(const char16_t* path) {
reader = new PackFileReader(zipFile, path, (*i)->GetPackFile()->GetIsUsePassword() ? stat : nullptr);
break;
}
} else if (fs::is_regular_file((*i)->GetPath() + path)) {
} else if (FileSystem::GetIsFile((*i)->GetPath() + path)) {
reader = new BaseFileReader(path);
}
}
Expand All @@ -115,14 +101,14 @@ StreamFile* File::CreateStreamFile(const char16_t* path) {
}

bool File::AddRootDirectory(const char16_t* path) {
if (!fs::is_directory(path)) return false;
if (!FileSystem::GetIsDirectory(path)) return false;
std::lock_guard<std::mutex> lock(m_rootMtx);
m_roots.push_back(std::make_shared<FileRoot>(path));
return true;
}

bool File::AddRootPackageWithPassword(const char16_t* path, const char16_t* password) {
if (!fs::is_regular_file(path)) return false;
if (!FileSystem::GetIsFile(path)) return false;

int error;
zip_t* zip_ = zip_open(utf16_to_utf8(path).c_str(), ZIP_RDONLY, &error);
Expand All @@ -139,7 +125,7 @@ bool File::AddRootPackageWithPassword(const char16_t* path, const char16_t* pass
}

bool File::AddRootPackage(const char16_t* path) {
if (!fs::is_regular_file(path)) return false;
if (!FileSystem::GetIsFile(path)) return false;

int error;
zip_t* zip_ = zip_open(utf16_to_utf8(path).c_str(), ZIP_RDONLY, &error);
Expand All @@ -162,15 +148,15 @@ bool File::Exists(const char16_t* path) const {
for (auto i = m_roots.rbegin(), e = m_roots.rend(); i != e; ++i) {
if ((*i)->IsPack()) {
if ((*i)->GetPackFile()->Exists(path)) return true;
} else if (fs::is_regular_file((*i)->GetPath() + path))
} else if (FileSystem::GetIsFile((*i)->GetPath() + path))
return true;
}

return false;
}

bool File::Pack(const char16_t* srcPath, const char16_t* dstPath) const {
if (!fs::is_directory(srcPath)) return false;
if (!FileSystem::GetIsDirectory(srcPath)) return false;

int error;
zip_t* zip_ = zip_open(utf16_to_utf8(dstPath).c_str(), ZIP_TRUNCATE | ZIP_CREATE, &error);
Expand All @@ -182,7 +168,7 @@ bool File::Pack(const char16_t* srcPath, const char16_t* dstPath) const {
}

bool File::Pack(const char16_t* srcPath, const char16_t* dstPath, const char16_t* password) const {
if (!fs::is_directory(srcPath)) return false;
if (!FileSystem::GetIsDirectory(srcPath)) return false;

int error;
zip_t* zip_ = zip_open(utf16_to_utf8(dstPath).c_str(), ZIP_TRUNCATE | ZIP_CREATE, &error);
Expand All @@ -208,18 +194,24 @@ bool File::MakePackage(zip_t* zipPtr, const std::u16string& path, bool isEncrypt
current = children.top();
children.pop();

for (const fs::directory_entry& i : fs::directory_iterator(current)) {
std::u16string zipPath = i.path().generic_u16string();
std::vector<std::u16string> paths;
FileSystem::GetChildPaths(current, paths);
for (auto& i : paths) {
std::u16string zipPath = i;
zipPath.erase(0, path.size());

if (fs::is_directory(i)) {
if (FileSystem::GetIsDirectory(i)) {
if (zip_dir_add(zipPtr, utf16_to_utf8(zipPath).c_str(), ZIP_FL_ENC_UTF_8) == -1) return false;
children.push(i.path().generic_u16string());
} else if (fs::is_regular_file(i)) {
std::ifstream file(i.path(), std::ios::binary);
children.push(i);
} else if (FileSystem::GetIsFile(i)) {
#if _WIN32
std::ifstream file((wchar_t*)i.c_str(), std::ios::binary);
#else
std::ifstream file(utf16_to_utf8(i).c_str(), std::ios::binary);
#endif
if (!file.is_open()) return false;

int size = fs::file_size(i.path());
int size = FileSystem::GetFileSize(i);

// libzip requires malloced buffer (not new)
char* buffer = static_cast<char*>(malloc(size));
Expand Down

0 comments on commit dbf5aa2

Please sign in to comment.