inital commit (message v3)
This commit is contained in:
commit
b08d2bf366
31
CMakeLists.txt
Normal file
31
CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||||
|
|
||||||
|
project(solanaceae)
|
||||||
|
|
||||||
|
add_library(solanaceae_message3
|
||||||
|
./solanaceae/message3/file.hpp
|
||||||
|
./solanaceae/message3/file_r_mem.hpp
|
||||||
|
./solanaceae/message3/file_r_file.hpp
|
||||||
|
./solanaceae/message3/file_w_file.hpp
|
||||||
|
./solanaceae/message3/file_rw_file.hpp
|
||||||
|
|
||||||
|
./solanaceae/message3/components.hpp
|
||||||
|
./solanaceae/message3/components_id.inl
|
||||||
|
|
||||||
|
./solanaceae/message3/message_model3.hpp
|
||||||
|
|
||||||
|
./solanaceae/message3/registry_message_model.hpp
|
||||||
|
./solanaceae/message3/registry_message_model.cpp
|
||||||
|
|
||||||
|
./solanaceae/message3/message_time_sort.hpp
|
||||||
|
./solanaceae/message3/message_time_sort.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(solanaceae_message3 PUBLIC .)
|
||||||
|
target_compile_features(solanaceae_message3 PUBLIC cxx_std_17)
|
||||||
|
target_link_libraries(solanaceae_message3 PUBLIC
|
||||||
|
solanaceae_util
|
||||||
|
solanaceae_contact
|
||||||
|
EnTT::EnTT
|
||||||
|
)
|
||||||
|
|
24
LICENSE
Normal file
24
LICENSE
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
The Code is under the following License, if not stated otherwise:
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Erik Scholz
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
`plant !`
|
||||||
|
|
||||||
|
provides `message` functionallity for solanaceae code.
|
||||||
|
|
||||||
|
relies on [EnTT](https://github.com/skypjack/entt)
|
||||||
|
|
120
solanaceae/message3/components.hpp
Normal file
120
solanaceae/message3/components.hpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <solanaceae/contact/contact_model3.hpp>
|
||||||
|
|
||||||
|
//fwd
|
||||||
|
struct FileI;
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Message::Components {
|
||||||
|
|
||||||
|
struct ContactFrom {
|
||||||
|
Contact3 c;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContactTo {
|
||||||
|
Contact3 c;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Timestamp {
|
||||||
|
uint64_t ts {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimestampProcessed {
|
||||||
|
uint64_t ts {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimestampWritten {
|
||||||
|
uint64_t ts {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MessageText {
|
||||||
|
std::string text;
|
||||||
|
MessageText(const std::string_view& view) : text(view) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TagMessageIsAction {};
|
||||||
|
|
||||||
|
namespace Transfer {
|
||||||
|
|
||||||
|
//struct TransferState {
|
||||||
|
//enum State {
|
||||||
|
//running,
|
||||||
|
//paused,
|
||||||
|
//finished,
|
||||||
|
//failed,
|
||||||
|
//} state = paused;
|
||||||
|
//};
|
||||||
|
struct TagHaveAll {};
|
||||||
|
|
||||||
|
struct BytesSent {
|
||||||
|
uint64_t total {0u};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BytesReceived {
|
||||||
|
uint64_t total {0u};
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: rename to stream?
|
||||||
|
using File = std::unique_ptr<FileI>;
|
||||||
|
|
||||||
|
struct TagReceiving {};
|
||||||
|
struct TagSending {};
|
||||||
|
// TODO: add both?
|
||||||
|
|
||||||
|
// convert to enum?
|
||||||
|
// TODO: local/remote
|
||||||
|
// TODO: invert?
|
||||||
|
struct TagPaused {};
|
||||||
|
|
||||||
|
struct StateCanceled {
|
||||||
|
enum Reason {
|
||||||
|
disconnected,
|
||||||
|
remote_canceld,
|
||||||
|
local_canceld,
|
||||||
|
} reason = disconnected;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct FileID {
|
||||||
|
// persistent ID
|
||||||
|
// sometimes called file_id or hash
|
||||||
|
ToxKey id;
|
||||||
|
// TODO: variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileKind {
|
||||||
|
// TODO: use tox file kind
|
||||||
|
uint64_t kind {0};
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct FileInfo {
|
||||||
|
struct FileDirEntry {
|
||||||
|
std::string file_name; // full path relative to base
|
||||||
|
uint64_t file_size {0};
|
||||||
|
};
|
||||||
|
std::vector<FileDirEntry> file_list;
|
||||||
|
uint64_t total_size {0};
|
||||||
|
};
|
||||||
|
|
||||||
|
// describes the files locally
|
||||||
|
// filename might be different to non local FileInfo
|
||||||
|
// order is the same
|
||||||
|
struct FileInfoLocal {
|
||||||
|
std::vector<std::string> file_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: rename to start? or set or ...
|
||||||
|
struct ActionAccept {
|
||||||
|
std::string save_to_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Transfer
|
||||||
|
|
||||||
|
} // Message::Components
|
||||||
|
|
||||||
|
#include "./components_id.inl"
|
||||||
|
|
36
solanaceae/message3/components_id.inl
Normal file
36
solanaceae/message3/components_id.inl
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "./components.hpp"
|
||||||
|
|
||||||
|
#include <entt/core/type_info.hpp>
|
||||||
|
|
||||||
|
// TODO: move more central
|
||||||
|
#define DEFINE_COMP_ID(x) \
|
||||||
|
template<> \
|
||||||
|
constexpr entt::id_type entt::type_hash<x>::value() noexcept { \
|
||||||
|
using namespace entt::literals; \
|
||||||
|
return #x##_hs; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// cross compile(r) stable ids
|
||||||
|
|
||||||
|
DEFINE_COMP_ID(Message::Components::ContactFrom)
|
||||||
|
DEFINE_COMP_ID(Message::Components::ContactTo)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Timestamp)
|
||||||
|
DEFINE_COMP_ID(Message::Components::TimestampProcessed)
|
||||||
|
DEFINE_COMP_ID(Message::Components::TimestampWritten)
|
||||||
|
DEFINE_COMP_ID(Message::Components::MessageText)
|
||||||
|
DEFINE_COMP_ID(Message::Components::TagMessageIsAction)
|
||||||
|
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::TagHaveAll)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::BytesSent)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::BytesReceived)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::File)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::TagReceiving)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::TagSending)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::TagPaused)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::StateCanceled)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::FileInfo)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::FileInfoLocal)
|
||||||
|
DEFINE_COMP_ID(Message::Components::Transfer::ActionAccept)
|
||||||
|
|
||||||
|
#undef DEFINE_COMP_ID
|
||||||
|
|
20
solanaceae/message3/file.hpp
Normal file
20
solanaceae/message3/file.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct FileI {
|
||||||
|
uint64_t _file_size {0};
|
||||||
|
// TODO: remove?
|
||||||
|
uint64_t _bytes_read {0};
|
||||||
|
uint64_t _bytes_written {0};
|
||||||
|
|
||||||
|
virtual ~FileI(void) {}
|
||||||
|
|
||||||
|
virtual bool isGood(void) = 0;
|
||||||
|
|
||||||
|
// TODO: move to owning/nonowning pointers
|
||||||
|
virtual std::vector<uint8_t> read(uint64_t pos, uint32_t size) = 0;
|
||||||
|
virtual bool write(uint64_t pos, const std::vector<uint8_t>& data) = 0;
|
||||||
|
};
|
||||||
|
|
53
solanaceae/message3/file_r_file.hpp
Normal file
53
solanaceae/message3/file_r_file.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./file.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
struct FileRFile : public FileI {
|
||||||
|
std::ifstream _file;
|
||||||
|
|
||||||
|
FileRFile(std::string_view file_path) : _file(static_cast<std::string>(file_path), std::ios::binary) {
|
||||||
|
if (!_file.is_open()) {
|
||||||
|
return; // TODO: error
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out size
|
||||||
|
_file.seekg(0, _file.end);
|
||||||
|
_file_size = _file.tellg();
|
||||||
|
_file.seekg(0, _file.beg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//FileRFile(std::ifstream&& other_file) : _file(std::move(other_file)) {}
|
||||||
|
//FileRFile(std::ifstream&& other_file, size_t file_size) : _file(std::move(other_file)), _file_size(file_size) {}
|
||||||
|
|
||||||
|
virtual ~FileRFile(void) {}
|
||||||
|
|
||||||
|
bool isGood(void) override {
|
||||||
|
return _file.is_open() && _file.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> read(uint64_t pos, uint32_t size) override {
|
||||||
|
if (_file_size > 0 && pos >= _file_size) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: error check
|
||||||
|
_file.seekg(pos);
|
||||||
|
|
||||||
|
// TODO: optimize
|
||||||
|
std::vector<uint8_t> chunk;
|
||||||
|
int read_char;
|
||||||
|
for (size_t i = 0; i < size && (_file_size == 0 || i+pos < _file_size) && (read_char = _file.get()) != std::ifstream::traits_type::eof(); i++) {
|
||||||
|
chunk.push_back(read_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bytes_read += chunk.size();
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read only
|
||||||
|
bool write(uint64_t, const std::vector<uint8_t>&) override { return false; }
|
||||||
|
};
|
||||||
|
|
38
solanaceae/message3/file_r_mem.hpp
Normal file
38
solanaceae/message3/file_r_mem.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./file.hpp"
|
||||||
|
|
||||||
|
struct FileRMem : public FileI {
|
||||||
|
std::vector<uint8_t> _data;
|
||||||
|
|
||||||
|
FileRMem(void) = delete;
|
||||||
|
FileRMem(const std::vector<uint8_t>& data) : _data(data) {
|
||||||
|
_file_size = _data.size();
|
||||||
|
}
|
||||||
|
virtual ~FileRMem(void) {}
|
||||||
|
|
||||||
|
bool isGood(void) override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> read(uint64_t pos, uint32_t size) override {
|
||||||
|
if (_file_size > 0 && pos >= _data.size()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: optimize
|
||||||
|
std::vector<uint8_t> chunk;
|
||||||
|
for (size_t i = 0; i < size && i+pos < _data.size(); i++) {
|
||||||
|
chunk.push_back(_data[pos+i]);
|
||||||
|
}
|
||||||
|
//chunk.insert(chunk.begin(), _data.cbegin()+pos, _data.cbegin()+pos+size);
|
||||||
|
|
||||||
|
_bytes_read += chunk.size();
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read only
|
||||||
|
bool write(uint64_t, const std::vector<uint8_t>&) override { return false; }
|
||||||
|
};
|
||||||
|
|
60
solanaceae/message3/file_rw_file.hpp
Normal file
60
solanaceae/message3/file_rw_file.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./file.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
struct FileRWFile : public FileI {
|
||||||
|
std::fstream _file;
|
||||||
|
|
||||||
|
//FileWFile(std::string_view file_path, uint64_t file_size) : _file(static_cast<std::string>(file_path), std::ios::binary) {
|
||||||
|
//_file_size = file_size;
|
||||||
|
|
||||||
|
//if (!_file.is_open()) {
|
||||||
|
//return; // TODO: error
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
virtual ~FileRWFile(void) {}
|
||||||
|
|
||||||
|
bool isGood(void) override {
|
||||||
|
return _file.is_open() && _file.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> read(uint64_t pos, uint32_t size) override {
|
||||||
|
if (pos >= _file_size) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: error check
|
||||||
|
_file.seekg(pos);
|
||||||
|
|
||||||
|
// TODO: optimize
|
||||||
|
std::vector<uint8_t> chunk;
|
||||||
|
int read_char;
|
||||||
|
for (size_t i = 0; i < size && (_file_size == 0 || i+pos < _file_size) && (read_char = _file.get()) != std::ifstream::traits_type::eof(); i++) {
|
||||||
|
chunk.push_back(read_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bytes_read += chunk.size();
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool write(uint64_t pos, const std::vector<uint8_t>& data) override {
|
||||||
|
if (pos >= _file_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if out-of-order, seek
|
||||||
|
if (_file.tellp() != int64_t(pos)) {
|
||||||
|
// TODO: error check
|
||||||
|
_file.seekp(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
_file.write(reinterpret_cast<const char*>(data.data()), data.size());
|
||||||
|
|
||||||
|
return _file.good();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
46
solanaceae/message3/file_w_file.hpp
Normal file
46
solanaceae/message3/file_w_file.hpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./file.hpp"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
struct FileWFile : public FileI {
|
||||||
|
std::ofstream _file;
|
||||||
|
|
||||||
|
FileWFile(std::string_view file_path, uint64_t file_size) : _file(static_cast<std::string>(file_path), std::ios::binary) {
|
||||||
|
_file_size = file_size;
|
||||||
|
|
||||||
|
if (!_file.is_open()) {
|
||||||
|
return; // TODO: error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~FileWFile(void) {}
|
||||||
|
|
||||||
|
bool isGood(void) override {
|
||||||
|
return _file.is_open() && _file.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
// write only
|
||||||
|
std::vector<uint8_t> read(uint64_t, uint32_t) override { return {}; }
|
||||||
|
|
||||||
|
bool write(uint64_t pos, const std::vector<uint8_t>& data) override {
|
||||||
|
if (_file_size > 0 && pos >= _file_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if out-of-order, seek
|
||||||
|
if (_file.tellp() != int64_t(pos)) {
|
||||||
|
// TODO: error check
|
||||||
|
_file.seekp(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
_file.write(reinterpret_cast<const char*>(data.data()), data.size());
|
||||||
|
|
||||||
|
_bytes_written += data.size();
|
||||||
|
|
||||||
|
return _file.good();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
27
solanaceae/message3/message_model3.hpp
Normal file
27
solanaceae/message3/message_model3.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <solanaceae/contact/contact_model3.hpp>
|
||||||
|
|
||||||
|
//#include "./file.hpp"
|
||||||
|
|
||||||
|
// TODO: move, rename, do something?, change in favor of tox?
|
||||||
|
//enum class FileKind : uint32_t {
|
||||||
|
//file = 0u,
|
||||||
|
//avatar = 1u,
|
||||||
|
//};
|
||||||
|
|
||||||
|
// interface to send messages
|
||||||
|
struct MessageModel3I {
|
||||||
|
virtual ~MessageModel3I(void) {}
|
||||||
|
|
||||||
|
// return true if a handler was found for the contact
|
||||||
|
|
||||||
|
virtual bool sendText(const Contact3 c, std::string_view message, bool action = false) { (void)c,(void)message,(void)action; return false; }
|
||||||
|
|
||||||
|
//virtual bool sendFile(const Contact& c, std::string_view file_name, std::unique_ptr<FileI> file) { (void)c,(void)message,(void)action; return false; }
|
||||||
|
virtual bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) { (void)c,(void)file_name,(void)file_path; return false; }
|
||||||
|
|
||||||
|
|
||||||
|
//virtual bool sendFileMem(const Contact& c, std::string_view file_name, const std::vector<uint8_t>& file) = 0;
|
||||||
|
};
|
||||||
|
|
29
solanaceae/message3/message_time_sort.cpp
Normal file
29
solanaceae/message3/message_time_sort.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "./message_time_sort.hpp"
|
||||||
|
|
||||||
|
#include <solanaceae/registry_message_model/components.hpp>
|
||||||
|
|
||||||
|
MessageTimeSort::MessageTimeSort(RegistryMessageModel& rmm) : _rmm(rmm) {
|
||||||
|
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
|
||||||
|
_rmm.subscribe(this, RegistryMessageModel_Event::message_updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageTimeSort::iterate(void) {
|
||||||
|
// TODO: maybe only every x for updated
|
||||||
|
for (auto* reg : _to_sort) {
|
||||||
|
reg->sort<Message::Components::Timestamp>([](const auto& lhs, const auto& rhs) -> bool {
|
||||||
|
return lhs.ts < rhs.ts;
|
||||||
|
}, entt::insertion_sort{});
|
||||||
|
}
|
||||||
|
_to_sort.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageTimeSort::onEvent(const Message::Events::MessageConstruct& e) {
|
||||||
|
_to_sort.emplace(e.e.registry());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageTimeSort::onEvent(const Message::Events::MessageUpdated& e) {
|
||||||
|
_to_sort.emplace(e.e.registry());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
23
solanaceae/message3/message_time_sort.hpp
Normal file
23
solanaceae/message3/message_time_sort.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./registry_message_model.hpp"
|
||||||
|
|
||||||
|
#include <entt/container/dense_set.hpp>
|
||||||
|
|
||||||
|
class MessageTimeSort : public RegistryMessageModelEventI {
|
||||||
|
RegistryMessageModel& _rmm;
|
||||||
|
|
||||||
|
// TODO: use contact instead
|
||||||
|
entt::dense_set<Message3Registry*> _to_sort;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MessageTimeSort(RegistryMessageModel& rmm);
|
||||||
|
|
||||||
|
// do the sorting
|
||||||
|
void iterate(void);
|
||||||
|
|
||||||
|
protected: // mm
|
||||||
|
bool onEvent(const Message::Events::MessageConstruct& e) override;
|
||||||
|
bool onEvent(const Message::Events::MessageUpdated& e) override;
|
||||||
|
};
|
||||||
|
|
131
solanaceae/message3/registry_message_model.cpp
Normal file
131
solanaceae/message3/registry_message_model.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include "./registry_message_model.hpp"
|
||||||
|
|
||||||
|
#include <solanaceae/contact/components.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Message3Registry* RegistryMessageModel::get(Contact3 c) {
|
||||||
|
if (_cr.valid(c) && !_cr.all_of<Contact::Components::TagBig>(c)) {
|
||||||
|
// TODO: loop upwards
|
||||||
|
if (!_cr.all_of<Contact::Components::Parent>(c)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
c = _cr.get<Contact::Components::Parent>(c).parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_cr.valid(c)) {
|
||||||
|
// TODO: throw error
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto it = _contact_messages.find(c);
|
||||||
|
if (it != _contact_messages.end()) {
|
||||||
|
return it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& reg_sh = _contact_messages[c] = std::make_unique<Message3Registry>();
|
||||||
|
return reg_sh.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Message3Registry* RegistryMessageModel::get(Contact3 c) const {
|
||||||
|
if (_cr.valid(c) && !_cr.all_of<Contact::Components::TagBig>(c)) {
|
||||||
|
// TODO: loop upwards
|
||||||
|
if (!_cr.all_of<Contact::Components::Parent>(c)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
c = _cr.get<Contact::Components::Parent>(c).parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_cr.valid(c)) {
|
||||||
|
// TODO: throw error
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto it = _contact_messages.find(c);
|
||||||
|
if (it != _contact_messages.cend()) {
|
||||||
|
return it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistryMessageModel::throwEventConstruct(Message3Registry& reg, Message3 e) {
|
||||||
|
std::cout << "RMM debug: event construct " << entt::to_integral(e) << "\n";
|
||||||
|
dispatch(
|
||||||
|
RegistryMessageModel_Event::message_construct,
|
||||||
|
Message::Events::MessageConstruct{
|
||||||
|
Message3Handle{reg, e}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistryMessageModel::throwEventUpdate(Message3Registry& reg, Message3 e) {
|
||||||
|
// the update while update lock is hacky
|
||||||
|
_update_queue.push_back({reg, e});
|
||||||
|
if (!_update_in_progess) {
|
||||||
|
_update_in_progess = true;
|
||||||
|
for (size_t i = 0; i < _update_queue.size(); i++) {
|
||||||
|
std::cout << "RMM debug: event update " << entt::to_integral(e) << "\n";
|
||||||
|
dispatch(
|
||||||
|
RegistryMessageModel_Event::message_updated,
|
||||||
|
Message::Events::MessageUpdated{
|
||||||
|
_update_queue.at(i)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_update_queue.clear();
|
||||||
|
_update_in_progess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistryMessageModel::throwEventDestroy(Message3Registry& reg, Message3 e) {
|
||||||
|
std::cout << "RMM debug: event destroy " << entt::to_integral(e) << "\n";
|
||||||
|
dispatch(
|
||||||
|
RegistryMessageModel_Event::message_destroy,
|
||||||
|
Message::Events::MessageDestory{
|
||||||
|
Message3Handle{reg, e}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistryMessageModel::throwEventConstruct(const Contact3 c, Message3 e) {
|
||||||
|
if (auto* reg_ptr = get(c); reg_ptr) {
|
||||||
|
throwEventConstruct(*reg_ptr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistryMessageModel::throwEventUpdate(const Contact3 c, Message3 e) {
|
||||||
|
if (auto* reg_ptr = get(c); reg_ptr) {
|
||||||
|
throwEventUpdate(*reg_ptr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegistryMessageModel::throwEventDestroy(const Contact3 c, Message3 e) {
|
||||||
|
if (auto* reg_ptr = get(c); reg_ptr) {
|
||||||
|
throwEventDestroy(*reg_ptr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegistryMessageModel::sendText(const Contact3 c, std::string_view message, bool action) {
|
||||||
|
std::cout << "RMM debug: event send text\n";
|
||||||
|
|
||||||
|
// manual, bc its not an "event"
|
||||||
|
for (auto* zei : _subscribers.at(size_t(RegistryMessageModel_Event::send_text))) {
|
||||||
|
if (zei->sendText(c, message, action)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegistryMessageModel::sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) {
|
||||||
|
std::cout << "RMM debug: event send file path\n";
|
||||||
|
|
||||||
|
// manual, bc its not an "event"
|
||||||
|
for (auto* zei : _subscribers.at(size_t(RegistryMessageModel_Event::send_file_path))) {
|
||||||
|
if (zei->sendFilePath(c, file_name, file_path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
100
solanaceae/message3/registry_message_model.hpp
Normal file
100
solanaceae/message3/registry_message_model.hpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <solanaceae/util/event_provider.hpp>
|
||||||
|
|
||||||
|
#include "./message_model3.hpp"
|
||||||
|
|
||||||
|
#include <entt/entity/registry.hpp>
|
||||||
|
#include <entt/entity/handle.hpp>
|
||||||
|
#include <entt/container/dense_map.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
// strong typing
|
||||||
|
enum class Message3 : uint32_t {};
|
||||||
|
using Message3Registry = entt::basic_registry<Message3>;
|
||||||
|
using Message3Handle = entt::basic_handle<Message3Registry>;
|
||||||
|
|
||||||
|
namespace Message::Events {
|
||||||
|
|
||||||
|
struct MessageConstruct {
|
||||||
|
const Message3Handle e;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MessageUpdated {
|
||||||
|
const Message3Handle e;
|
||||||
|
// hint?
|
||||||
|
// like component list?
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MessageDestory {
|
||||||
|
const Message3Handle e;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Events
|
||||||
|
|
||||||
|
enum class RegistryMessageModel_Event : uint32_t {
|
||||||
|
message_construct,
|
||||||
|
message_updated,
|
||||||
|
message_destroy,
|
||||||
|
|
||||||
|
send_text,
|
||||||
|
send_file_path,
|
||||||
|
|
||||||
|
MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2 in 1
|
||||||
|
struct RegistryMessageModelEventI : public MessageModel3I {
|
||||||
|
using enumType = RegistryMessageModel_Event;
|
||||||
|
|
||||||
|
virtual ~RegistryMessageModelEventI(void) {}
|
||||||
|
|
||||||
|
virtual bool onEvent(const Message::Events::MessageConstruct&) { return false; }
|
||||||
|
virtual bool onEvent(const Message::Events::MessageUpdated&) { return false; }
|
||||||
|
virtual bool onEvent(const Message::Events::MessageDestory&) { return false; }
|
||||||
|
|
||||||
|
// mm3
|
||||||
|
// send text
|
||||||
|
// send file path
|
||||||
|
};
|
||||||
|
using RegistryMessageModelEventProviderI = EventProviderI<RegistryMessageModelEventI>;
|
||||||
|
|
||||||
|
class RegistryMessageModel : public RegistryMessageModelEventProviderI, public MessageModel3I {
|
||||||
|
protected:
|
||||||
|
Contact3Registry& _cr;
|
||||||
|
|
||||||
|
entt::dense_map<Contact3, std::unique_ptr<Message3Registry>> _contact_messages;
|
||||||
|
|
||||||
|
bool _update_in_progess {false};
|
||||||
|
std::vector<Message3Handle> _update_queue {};
|
||||||
|
|
||||||
|
public:
|
||||||
|
RegistryMessageModel(Contact3Registry& cr) : _cr(cr) {}
|
||||||
|
virtual ~RegistryMessageModel(void) {}
|
||||||
|
|
||||||
|
// TODO: iterate?
|
||||||
|
|
||||||
|
public:
|
||||||
|
Message3Registry* get(Contact3 c);
|
||||||
|
Message3Registry* get(Contact3 c) const;
|
||||||
|
|
||||||
|
public: // dispatcher
|
||||||
|
// !!! remember to manually throw these externally
|
||||||
|
void throwEventConstruct(Message3Registry& reg, Message3 e);
|
||||||
|
void throwEventUpdate(Message3Registry& reg, Message3 e);
|
||||||
|
void throwEventDestroy(Message3Registry& reg, Message3 e);
|
||||||
|
|
||||||
|
void throwEventConstruct(Message3Handle h) { throwEventConstruct(*h.registry(), h.entity()); }
|
||||||
|
void throwEventUpdate(Message3Handle h) { throwEventUpdate(*h.registry(), h.entity()); }
|
||||||
|
void throwEventDestroy(Message3Handle h) { throwEventDestroy(*h.registry(), h.entity()); }
|
||||||
|
|
||||||
|
void throwEventConstruct(const Contact3 c, Message3 e);
|
||||||
|
void throwEventUpdate(const Contact3 c, Message3 e);
|
||||||
|
void throwEventDestroy(const Contact3 c, Message3 e);
|
||||||
|
|
||||||
|
public: // mm3
|
||||||
|
bool sendText(const Contact3 c, std::string_view message, bool action = false) override;
|
||||||
|
bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) override;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user