#pragma once #include #include // Примитивное IPC‑сообщение с API add() / get(). // Под капотом пока текстовый формат с типовыми тегами, но снаружи интерфейс не завязан на std::string. class IpcMessage { public: IpcMessage() = default; explicit IpcMessage(const std::string& raw) : raw_(raw) {} IpcMessage(const IpcMessage& other) : raw_(other.raw_) {} IpcMessage& operator=(const IpcMessage& other) { if (this != &other) { raw_ = other.raw_; in_.clear(); in_initialized_ = false; out_.str(std::string{}); } return *this; } // Конструирование исходящего сообщения. template void add(const T& v); // Чтение входящего сообщения по частям. template T get(); const std::string& raw() const { return raw_; } bool empty() const { return raw_.empty(); } private: std::string raw_; std::ostringstream out_; std::istringstream in_; bool in_initialized_{false}; void ensureInput() { if (!in_initialized_) { in_.str(raw_); in_initialized_ = true; } } }; // ===== Специализации по типам ===== // int template<> inline void IpcMessage::add(const int& v) { out_ << 'i' << ' ' << v << ' '; raw_ = out_.str(); } template<> inline int IpcMessage::get() { ensureInput(); char tag{}; in_ >> tag; // в PoC просто доверяем, что тип совпадает int v{}; in_ >> v; return v; } // std::string template<> inline void IpcMessage::add(const std::string& v) { // формат: 's' out_ << 's' << ' ' << v.size() << ' '; out_.write(v.data(), static_cast(v.size())); out_ << ' '; raw_ = out_.str(); } template<> inline std::string IpcMessage::get() { 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(len)); // съесть завершающий пробел in_.get(); return res; }