diff --git a/Core/ClientSML/src/sml_ClientEvents.h b/Core/ClientSML/src/sml_ClientEvents.h index 93822a709d..1fcc324660 100644 --- a/Core/ClientSML/src/sml_ClientEvents.h +++ b/Core/ClientSML/src/sml_ClientEvents.h @@ -100,13 +100,16 @@ namespace sml typedef char const *(*RhsEventHandler)(smlRhsEventId id, void* pUserData, Agent* pAgent, char const* pFunctionName, char const* pArgument, int *buffSize, char *buff) ; + typedef std::string(*RhsEventHandlerManaged)(smlRhsEventId id, void* pUserData, Agent* pAgent, + char const* pFunctionName, char const* pArgument) ; // Handler for a generic "client message". The content is determined by the client sending this data. // The message is sent as a simple string and the response is also a string. The string can contain data that is intended to be parsed, // such as a simple series of integers up to a complete XML message. // SEE MAINTAINER NOTE ABOVE! typedef char const *(*ClientMessageHandler)(smlRhsEventId id, void* pUserData, Agent* pAgent, char const* pFunctionName, char const* pArgument, int *buffSize, char *buff) ; - + typedef std::string(*ClientMessageHandlerManaged)(smlRhsEventId id, void* pUserData, Agent* pAgent, + char const* pClientName, char const* pMessage) ; // We'll store a handler function together with a generic pointer to data of the user's choosing // (which is then passed back into the handler when the event occurs). // We also include a callback "id" which is a unique way to refer to this callback--used during unregistering. diff --git a/Core/ClientSML/src/sml_ClientKernel.cpp b/Core/ClientSML/src/sml_ClientKernel.cpp index a2c79a22f0..17116f02f9 100644 --- a/Core/ClientSML/src/sml_ClientKernel.cpp +++ b/Core/ClientSML/src/sml_ClientKernel.cpp @@ -2189,6 +2189,42 @@ int Kernel::AddRhsFunction(char const* pRhsFunctionName, RhsEventHandler handler return InternalAddRhsFunction(id, pRhsFunctionName, handler, pUserData, addToBack) ; } +int Kernel::AddRhsFunctionManaged(char const* pRhsFunctionName, RhsEventHandlerManaged handler, void* pUserData, bool addToBack) +{ + auto newHandler = [&handler]( + smlRhsEventId id, + void* pUserData, + Agent* pAgent, + char const* pFunctionName, + char const* pArgument, + int *bufSize, + char *buf) -> char * { + static std::string prevResult; + // Previous call could not return the full result and cached it in prevResult instead. + // Return the cached result and clear the cache. + if ( !prevResult.empty() ) + { + strncpy( buf, prevResult.c_str(), *bufSize ); + prevResult = ""; + return buf; + } + + std::string resultStr = handler(id, pUserData, pAgent, pFunctionName, pArgument); + // Result won't fit in the buffer. Return NULL and set buffSize to the required size. + // Soar will then re-call this handler and get the cached result. + if ( resultStr.length() + 1 > *bufSize ) + { + *bufSize = resultStr.length() + 1; + prevResult = resultStr; + return NULL; + } + + strcpy( buf, resultStr.c_str() ); + return buf; + }; + return AddRhsFunction(pRhsFunctionName, newHandler, pUserData, addToBack); +} + /************************************************************* * @brief Unregister for a particular RHS function *************************************************************/ diff --git a/Core/ClientSML/src/sml_ClientKernel.h b/Core/ClientSML/src/sml_ClientKernel.h index 90eb0bdc82..c288f06800 100644 --- a/Core/ClientSML/src/sml_ClientKernel.h +++ b/Core/ClientSML/src/sml_ClientKernel.h @@ -781,6 +781,7 @@ namespace sml * @returns Unique ID for this callback. Required when unregistering this callback. *************************************************************/ int AddRhsFunction(char const* pRhsFunctionName, RhsEventHandler handler, void* pUserData, bool addToBack = true) ; + int AddRhsFunctionManaged(char const* pRhsFunctionName, RhsEventHandlerManaged handler, void* pUserData, bool addToBack = true) ; /************************************************************* * @brief Unregister for a particular rhs function callback