nf7/file/system_native_file.cc

177 lines
5.0 KiB
C++

#include <chrono>
#include <functional>
#include <future>
#include <memory>
#include <mutex>
#include <string>
#include <string_view>
#include <typeinfo>
#include <utility>
#include <vector>
#include <imgui.h>
#include <imgui_stdlib.h>
#include <yas/serialize.hpp>
#include <yas/types/std/chrono.hpp>
#include <yas/types/std/string.hpp>
#include "nf7.hh"
#include "common/async_buffer.hh"
#include "common/async_buffer_adaptor.hh"
#include "common/dir_item.hh"
#include "common/generic_context.hh"
#include "common/generic_type_info.hh"
#include "common/gui_window.hh"
#include "common/native_file.hh"
#include "common/ptr_selector.hh"
#include "common/queue.hh"
#include "common/yas_std_filesystem.hh"
namespace nf7 {
namespace {
class NativeFile final : public File,
public nf7::DirItem {
public:
static inline const GenericTypeInfo<NativeFile> kType = {
"System/NativeFile", {"nf7::AsyncBuffer", "nf7::DirItem"}};
static void UpdateTypeTooltip() noexcept {
ImGui::TextUnformatted("Reads/Writes a file placed on native filesystem.");
ImGui::Bullet(); ImGui::TextUnformatted("implements nf7::AsyncBuffer");
ImGui::Bullet(); ImGui::TextUnformatted("basepath is environment native path");
}
NativeFile(Env& env, const std::filesystem::path& path = "", std::string_view mode = "") noexcept :
File(kType, env), DirItem(DirItem::kMenu | DirItem::kTooltip),
npath_(path), mode_(mode) {
}
NativeFile(Env& env, Deserializer& ar) : NativeFile(env) {
ar(npath_, mode_, lastmod_);
}
void Serialize(Serializer& ar) const noexcept override {
ar(npath_, mode_, lastmod_);
}
std::unique_ptr<File> Clone(Env& env) const noexcept override {
return std::make_unique<NativeFile>(env, npath_, mode_);
}
void Update() noexcept override;
void UpdateMenu() noexcept override;
void UpdateTooltip() noexcept override;
void Handle(const Event& ev) noexcept override {
switch (ev.type) {
case Event::kAdd:
Reset();
return;
case Event::kRemove:
buf_ = nullptr;
return;
default:
return;
}
}
File::Interface* interface(const std::type_info& t) noexcept override {
return InterfaceSelector<nf7::AsyncBuffer, nf7::DirItem>(t).Select(this, buf_.get());
}
private:
std::shared_ptr<nf7::AsyncBufferAdaptor> buf_;
const char* popup_ = nullptr;
// persistent params
std::filesystem::path npath_;
std::string mode_;
std::filesystem::file_time_type lastmod_;
void Reset() noexcept {
bool exlock = false;
nf7::Buffer::Flags flags = 0;
for (auto c : mode_) {
if (c == 'x') exlock = true;
flags |=
c == 'r'? nf7::Buffer::kRead:
c == 'w'? nf7::Buffer::kWrite: 0;
}
auto buf = std::make_shared<
nf7::NativeFile>(*this, env().npath()/npath_, flags, exlock);
buf_ = std::make_shared<nf7::AsyncBufferAdaptor>(buf, buf);
}
};
void NativeFile::Update() noexcept {
// file update check
try {
const auto lastmod = std::filesystem::last_write_time(env().npath()/npath_);
if (std::exchange(lastmod_, lastmod) < lastmod) {
Touch();
}
} catch (std::filesystem::filesystem_error&) {
}
if (const auto popup = std::exchange(popup_, nullptr)) {
ImGui::OpenPopup(popup);
}
if (ImGui::BeginPopup("ConfigPopup")) {
static std::string path;
static bool flag_exlock;
static bool flag_readable;
static bool flag_writeable;
ImGui::TextUnformatted("System/NativeFile: config");
if (ImGui::IsWindowAppearing()) {
path = npath_.generic_string();
flag_exlock = mode_.find('x') != std::string::npos;
flag_readable = mode_.find('r') != std::string::npos;
flag_writeable = mode_.find('w') != std::string::npos;
}
ImGui::InputText("path", &path);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"path to the native file system (base: '%s')",
env().npath().generic_string().c_str());
}
ImGui::Checkbox("exclusive lock", &flag_exlock);
ImGui::Checkbox("readable", &flag_readable);
ImGui::Checkbox("writeable", &flag_writeable);
if (ImGui::Button("ok")) {
ImGui::CloseCurrentPopup();
npath_ = path;
mode_ = "";
if (flag_exlock) mode_ += 'x';
if (flag_readable) mode_ += 'r';
if (flag_writeable) mode_ += 'w';
auto ctx = std::make_shared<nf7::GenericContext>(*this, "resetting native file handle");
env().ExecMain(ctx, [this]() { Reset(); Touch(); });
}
if (!std::filesystem::exists(env().npath()/path)) {
ImGui::Bullet(); ImGui::TextUnformatted("target file seems to be missing...");
}
ImGui::EndPopup();
}
}
void NativeFile::UpdateMenu() noexcept {
if (ImGui::MenuItem("config")) {
popup_ = "ConfigPopup";
}
}
void NativeFile::UpdateTooltip() noexcept {
ImGui::Text("basepath: %s", env().npath().generic_string().c_str());
ImGui::Text("path : %s", npath_.generic_string().c_str());
ImGui::Text("mode : %s", mode_.c_str());
}
}
} // namespace nf7