Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Windows.h>
- #include <cstdint>
- #include "lua.hpp"
- #include <string>
- #include <variant>
- #define API_FUNC extern "C" __declspec( dllexport ) int
- using ErrMsg = std::string;
- static constexpr std::string_view _version = "v0.3";
- [[nodiscard]]
- static auto pushErrorMsg(lua_State* L, const std::string& msg)
- -> int
- {
- lua_pushboolean(L, false);
- lua_pushstring(L, msg.c_str());
- return 2;
- }
- [[nodiscard]]
- static auto luaStringToWideString(std::string utf8)
- -> std::wstring
- {
- const auto bytes = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0) - 1;
- std::wstring output(bytes, 0);
- const auto res = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &output[0], bytes);
- return output;
- }
- [[nodiscard]]
- static auto getFileHandleFromStringAtStackPos(
- lua_State* L, const uint16_t stack_pos, const bool read_only = true)
- -> std::variant<FILE*, ErrMsg>
- {
- if (abs(stack_pos) > lua_gettop(L)) return "Error: stack pos must be in range";
- if (!lua_isstring(L, stack_pos)) return "Error: stack pos must be a string";
- const auto path = std::string(lua_tostring(L, stack_pos));
- const auto& wpath = luaStringToWideString(path);
- uint32_t read_or_write_share = read_only ? FILE_SHARE_READ : FILE_SHARE_WRITE;
- uint32_t read_or_write_generic = read_only ? GENERIC_READ : GENERIC_ALL;
- const auto file = static_cast<FILE*>(
- CreateFileW(
- wpath.c_str(), read_or_write_generic, read_or_write_share, 0,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
- )
- );
- if (file) return file;
- return "Error: cannot open file '" + path + "'";
- }
- API_FUNC getVersion(lua_State* L)
- {
- lua_pushstring(L, std::string(_version).c_str());
- return 1;
- }
- API_FUNC getLastModified(lua_State* L)
- {
- if (!lua_isstring(L, 1)) return pushErrorMsg(L, "Error: function takes one filepath string");
- auto res = getFileHandleFromStringAtStackPos(L, 1);
- const auto file = std::get_if<FILE*>(&res);
- if (!file) return pushErrorMsg(L, std::get<ErrMsg>(res));
- FILETIME file_time;
- auto ok = GetFileTime(*file, nullptr, nullptr, &file_time);
- CloseHandle(*file);
- if (!ok) return pushErrorMsg(L, "Error: could not get file time.");
- lua_pushboolean(L, true);
- lua_pushnumber(L, static_cast<double>(file_time.dwHighDateTime));
- lua_pushnumber(L, static_cast<double>(file_time.dwLowDateTime));
- return 3;
- }
- API_FUNC compareFileTimesFromPaths(lua_State* L)
- {
- if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
- return pushErrorMsg(L, "Error: function takes two filepath strings");
- auto res = getFileHandleFromStringAtStackPos(L, 1);
- const auto file1 = std::get_if<FILE*>(&res);
- if (!file1) return pushErrorMsg(L, std::get<ErrMsg>(res));
- res = getFileHandleFromStringAtStackPos(L, 2);
- const auto file2 = std::get_if<FILE*>(&res);
- if (!file2) return pushErrorMsg(L, std::get<ErrMsg>(res));
- FILETIME file_time1;
- auto ok = GetFileTime(*file1, nullptr, &file_time1, nullptr);
- CloseHandle(*file1);
- FILETIME file_time2;
- ok = GetFileTime(*file2, nullptr, &file_time2, nullptr);
- CloseHandle(*file2);
- ok = CompareFileTime(&file_time1, &file_time2);
- lua_pushboolean(L, true);
- lua_pushnumber(L, ok);
- return 2;
- }
- API_FUNC copyFile(lua_State* L)
- {
- if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
- return pushErrorMsg(L, "Error: function takes two filepath strings");
- const auto& wpath1 = luaStringToWideString(lua_tostring(L, 1));
- const auto& wpath2 = luaStringToWideString(lua_tostring(L, 2));
- auto copy_succeeded = CopyFileW(wpath1.c_str(), wpath2.c_str(), false);
- if (!copy_succeeded) return pushErrorMsg(L, "Error: an unknown error occured copying the file.");
- lua_pushboolean(L, true);
- return 1;
- }
Add Comment
Please, Sign In to add comment