EVOLUTION-MANAGER
Edit File: rinsideserver.h
/* * Copyright (c) 2014 Christian Authmann */ #pragma once #include "common/typeid.h" #include "common/binarystream.h" #include "common/constants.h" #include "rinside_callbacks.h" #include <stdexcept> #include <map> #include <functional> class CppFunctionForRInsideServer; class RInsideServer { public: RInsideServer(BinaryStream &stream, RInside &R, RInsideCallbacks &Rcallbacks); ~RInsideServer(); void run(); private: SEXP sexp_from_stream(); void sexp_to_stream(SEXP, int32_t type, bool include_reply = false); BinaryStream stream; RInside &R; RInsideCallbacks &Rcallbacks; bool can_send_reply; void sendReply(char reply) { if (!can_send_reply) throw std::runtime_error("Cannot send a reply at this time, exiting"); can_send_reply = false; stream.write(reply); } void allowSendReply() { if (can_send_reply) throw std::runtime_error("allowSendReply() called twice, exiting"); can_send_reply = true; } static std::map<int32_t, std::function<SEXP(BinaryStream &)> > registry_sexp_from_stream; static std::map<int32_t, std::function<void(RInsideServer &, SEXP, bool)> > registry_sexp_to_stream; public: static void registerDefaultTypes(); template <typename T> static void registerType() { int32_t type = TYPEID<T>(); if (registry_sexp_from_stream.count(type) > 0 || registry_sexp_to_stream.count(type) > 0) throw std::runtime_error("registerType(): type already registered"); registry_sexp_from_stream[type] = [] (BinaryStream &stream) -> SEXP { T value = stream.read<T>(); return Rcpp::wrap<T>(value); }; registry_sexp_to_stream[type] = [type] (RInsideServer &server, SEXP sexp, bool include_reply) -> void { T value = Rcpp::as<T>(sexp); /* * The reply should be sent after type conversion. If type conversion throws an exception, * the server cannot reply with REPLY_ERROR after another reply has been sent. */ if (include_reply) server.sendReply(RIS_REPLY_VALUE); server.stream.write(type); server.stream.write(value); }; } friend class CppFunctionForRInsideServer; };