improve ipc msg

master
Сергей Маринкевич 2 months ago
parent 99ea8d1646
commit 0712460db0

@ -4,7 +4,7 @@
#include <string> #include <string>
// Примитивное IPCсообщение с API add<T>() / get<T>(). // Примитивное IPCсообщение с API add<T>() / get<T>().
// Под капотом пока текстовый формат, но снаружи интерфейс не завязан на std::string. // Под капотом пока текстовый формат с типовыми тегами, но снаружи интерфейс не завязан на std::string.
class IpcMessage { class IpcMessage {
public: public:
@ -28,22 +28,11 @@ public:
// Конструирование исходящего сообщения. // Конструирование исходящего сообщения.
template<typename T> template<typename T>
void add(const T& v) { void add(const T& v);
out_ << v << ' ';
raw_ = out_.str();
}
// Чтение входящего сообщения по частям. // Чтение входящего сообщения по частям.
template<typename T> template<typename T>
T get() { T get();
if (!in_initialized_) {
in_.str(raw_);
in_initialized_ = true;
}
T v{};
in_ >> v;
return v;
}
const std::string& raw() const { const std::string& raw() const {
return raw_; return raw_;
@ -58,5 +47,60 @@ private:
std::ostringstream out_; std::ostringstream out_;
std::istringstream in_; std::istringstream in_;
bool in_initialized_{false}; bool in_initialized_{false};
void ensureInput() {
if (!in_initialized_) {
in_.str(raw_);
in_initialized_ = true;
}
}
}; };
// ===== Специализации по типам =====
// int
template<>
inline void IpcMessage::add<int>(const int& v) {
out_ << 'i' << ' ' << v << ' ';
raw_ = out_.str();
}
template<>
inline int IpcMessage::get<int>() {
ensureInput();
char tag{};
in_ >> tag;
// в PoC просто доверяем, что тип совпадает
int v{};
in_ >> v;
return v;
}
// std::string
template<>
inline void IpcMessage::add<std::string>(const std::string& v) {
// формат: 's' <len> <bytes...>
out_ << 's' << ' ' << v.size() << ' ';
out_.write(v.data(), static_cast<std::streamsize>(v.size()));
out_ << ' ';
raw_ = out_.str();
}
template<>
inline std::string IpcMessage::get<std::string>() {
ensureInput();
char tag{};
in_ >> tag;
// ожидаем 's'
std::size_t len{};
in_ >> len;
// съесть одиночный пробел перед данными
in_.get();
std::string res(len, '\0');
in_.read(&res[0], static_cast<std::streamsize>(len));
// съесть завершающий пробел
in_.get();
return res;
}

@ -1,35 +0,0 @@
#include "RpcChannel.h"
#include <fcntl.h>
#include <unistd.h>
#include <string>
class RpcChannelFifo : public RpcChannel {
public:
RpcChannelFifo(const char* inPipe, const char* outPipe) {
fdOut = open(inPipe, O_WRONLY);
fdIn = open(outPipe, O_RDONLY);
}
void send(const std::string& data) override {
::write(fdOut, data.c_str(), data.size());
::write(fdOut, "\n", 1);
}
std::string receive() override {
char buf[4096];
int n = ::read(fdIn, buf, sizeof(buf) - 1);
if (n <= 0) {
return {};
}
buf[n] = 0;
return std::string(buf);
}
private:
int fdIn{};
int fdOut{};
};
Loading…
Cancel
Save