#ifndef __JEEP__JFUNCTIONADAPTOR__ #define __JEEP__JFUNCTIONADAPTOR__ #include #include #include #include #include "JLang/JException.hh" #include "JLang/JSharedCounter.hh" /** * \author mdejong */ namespace JEEP {} namespace JPP { using namespace JEEP; } namespace JEEP { using JLANG::JSharedCounter; using JLANG::JFileOpenException; using JLANG::JFileReadException; using JLANG::JParseError; /** * Auxiliary base class for function adaptor. * * Note that the dynamic load library internally maintains link counts for the file handles. */ template struct JFunctionAdaptorHelper : JSharedCounter { /** * Separation character between library file name and function name. */ static const char SEPARATOR = ':'; /** * Virtual destructor. */ virtual ~JFunctionAdaptorHelper() { reset(); } /** * Check validity of function. * * \return true if valid function; else false */ bool is_valid() const { return (function != NULL); } /** * Reset function adaptor helper. */ void reset() { if (detach()) { close(); } function = NULL; } /** * Set function. * * \param pf pointer to function */ void set(__pF__ pf) { close(); function = pf; } /** * Get function with given name according to specific protocol. * * \param symbol function name */ void get(const char* symbol) { function = NULL; if (handle != NULL) { dlerror(); // reset errors function = (__pF__) dlsym(handle, symbol); const char* error = dlerror(); if (error != NULL) { THROW(JFileReadException, error); } } else { THROW(JFileReadException, "Invalid handle."); } } /** * Check if shared library file is open. * * \return true if open; else false */ bool is_open() const { return (handle != NULL); } /** * Open file. * * \param file_name file name */ void open(const char* file_name) { reset(); handle = dlopen(file_name, RTLD_LOCAL | RTLD_LAZY); if (!handle) { THROW(JFileOpenException, dlerror()); } initialise(); } /** * Close file. * * Note that the file should remain open as long as the library function is used. */ void close() { if (handle != NULL) { dlclose(handle); dlclose(handle); } handle = NULL; } /** * Load function from shared library. * * \param file_name file name * \param symbol function name */ void load(const std::string& file_name, const std::string& symbol) { open(file_name.c_str()); get(symbol.c_str()); } /** * Load function from shared library. * * The input buffer should consist of \SEPARATOR\. * * \param buffer input */ void load(const std::string& buffer) { using namespace std; const string::size_type pos = buffer.rfind(SEPARATOR); if (pos != string::npos) { load(buffer.substr(0,pos).c_str(), buffer.substr(pos+1).c_str()); } else { THROW(JParseError, "Missing separator " << SEPARATOR << " in " << buffer); } } /** * Read function adaptor helper from input stream. * * \param in input stream * \param object function adaptor helper * \return input stream */ friend std::istream& operator>>(std::istream& in, JFunctionAdaptorHelper& object) { object.reset(); std::string buffer; if (in >> buffer) { object.load(buffer); } return in; } /** * Write function adaptor helper to output stream. * * \param out output stream * \param object function adaptor helper * \return output stream */ friend std::ostream& operator<<(std::ostream& out, const JFunctionAdaptorHelper& object) { return out; } protected: /** * Default constructor. */ JFunctionAdaptorHelper() : handle (NULL), function(NULL) {} /** * Constructor. * * \param pf pointer to function */ JFunctionAdaptorHelper(__pF__ pf) : handle (NULL), function(pf) {} /** * Constructor. * * \param file_name file name * \param symbol function name */ JFunctionAdaptorHelper(const std::string& file_name, const std::string& symbol) : handle (NULL), function(NULL) { this->load(file_name, symbol); } /** * Copy constructor. * * \param helper helper */ JFunctionAdaptorHelper(const JFunctionAdaptorHelper& helper) : handle (helper.handle), function(helper.function) { if (is_open()) { attach(helper); } } void* handle; __pF__ function; }; /** * Function adaptor. */ template struct JFunctionAdaptor; /** * Function adaptor for function with one argument. */ template struct JFunctionAdaptor : public JFunctionAdaptorHelper { /** * Type definition of method. */ typedef JReturn_t (*pF)(JFirst_t); /** * Default constructor. */ JFunctionAdaptor() : JFunctionAdaptorHelper() {} /** * Constructor. * * \param pf pointer to function */ JFunctionAdaptor(pF pf) : JFunctionAdaptorHelper(pf) {} /** * Constructor. * * \param file_name file name * \param symbol function name */ JFunctionAdaptor(const std::string& file_name, const std::string& symbol) : JFunctionAdaptorHelper(file_name, symbol) {} /** * Function operation. * * \param first first argument * \return return value */ JReturn_t operator()(JFirst_t first) const { return this->function(first); } }; /** * Function adaptor for function with two arguments. */ template struct JFunctionAdaptor : public JFunctionAdaptorHelper { /** * Type definition of method. */ typedef JReturn_t (*pF)(JFirst_t, JSecond_t); /** * Default constructor. */ JFunctionAdaptor() : JFunctionAdaptorHelper() {} /** * Constructor. * * \param pf pointer to function */ JFunctionAdaptor(pF pf) : JFunctionAdaptorHelper(pf) {} /** * Constructor. * * \param file_name file name * \param symbol function name */ JFunctionAdaptor(const std::string& file_name, const std::string& symbol) : JFunctionAdaptorHelper(file_name, symbol) {} /** * Function operation. * * \param first first argument * \param second second argument * \return return value */ JReturn_t operator()(JFirst_t first, JSecond_t second) const { return this->function(first, second); } }; } #endif