diff options
Diffstat (limited to 'src/uscxml')
23 files changed, 410 insertions, 340 deletions
diff --git a/src/uscxml/Common.h b/src/uscxml/Common.h index d1f42c7..abe4921 100644 --- a/src/uscxml/Common.h +++ b/src/uscxml/Common.h @@ -20,6 +20,8 @@ #ifndef COMMON_H_YZ3CIYP #define COMMON_H_YZ3CIYP +#define XERCESC_NS xercesc_3_1 + #ifndef _MSC_VER #define ELPP_STACKTRACE_ON_CRASH 1 #endif diff --git a/src/uscxml/debug/InterpreterIssue.h b/src/uscxml/debug/InterpreterIssue.h index 7eede09..983c1ad 100644 --- a/src/uscxml/debug/InterpreterIssue.h +++ b/src/uscxml/debug/InterpreterIssue.h @@ -21,7 +21,6 @@ #ifndef INTERPRETERISSUE_H_962CB305 #define INTERPRETERISSUE_H_962CB305 -#include "uscxml/config.h" #include "uscxml/Common.h" #include <list> diff --git a/src/uscxml/interpreter/BasicDelayedEventQueue.cpp b/src/uscxml/interpreter/BasicDelayedEventQueue.cpp new file mode 100644 index 0000000..3ad9ebd --- /dev/null +++ b/src/uscxml/interpreter/BasicDelayedEventQueue.cpp @@ -0,0 +1,171 @@ +/** + * @file + * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include "BasicDelayedEventQueue.h" +#include <event2/util.h> // for evutil_socket_t +#include <event2/thread.h> +#include <assert.h> + +#include "uscxml/interpreter/Logging.h" + +namespace uscxml { + +static void dummyCallback(evutil_socket_t fd, short what, void *arg) { + timeval tv; + tv.tv_sec = 365 * 24 * 3600; + tv.tv_usec = 0; + event *ev = *(event **)arg; + evtimer_add(ev, &tv); +} + +BasicDelayedEventQueue::BasicDelayedEventQueue(DelayedEventQueueCallbacks* callbacks) { + _callbacks = callbacks; +#ifndef _WIN32 + evthread_use_pthreads(); +#else + evthread_use_windows_threads(); +#endif + _eventLoop = event_base_new(); + + // see here: https://github.com/named-data/ndn.cxx/blob/master/scheduler/scheduler.cc + // and here: https://www.mail-archive.com/libevent-users@seul.org/msg01676.html + timeval tv; + tv.tv_sec = 365 * 24 * 3600; + tv.tv_usec = 0; + _dummyEvent = evtimer_new(_eventLoop, dummyCallback, &_dummyEvent); + evtimer_add(_dummyEvent, &tv); + + _thread = NULL; + _isStarted = false; + start(); +} + +BasicDelayedEventQueue::~BasicDelayedEventQueue() { + stop(); + evtimer_del(_dummyEvent); + event_free(_dummyEvent); + event_base_free(_eventLoop); +} + +std::shared_ptr<DelayedEventQueueImpl> BasicDelayedEventQueue::create(DelayedEventQueueCallbacks* callbacks) { + return std::shared_ptr<DelayedEventQueueImpl>(new BasicDelayedEventQueue(callbacks)); +} + +void BasicDelayedEventQueue::timerCallback(evutil_socket_t fd, short what, void *arg) { + struct callbackData *data = (struct callbackData*)arg; + std::lock_guard<std::recursive_mutex> lock(data->eventQueue->_mutex); + + if (data->eventQueue->_callbackData.find(data->eventUUID) == data->eventQueue->_callbackData.end()) + return; + + event_free(data->event); + data->eventQueue->_callbacks->eventReady(data->userData, data->eventUUID); + data->eventQueue->_callbackData.erase(data->eventUUID); +} + +void BasicDelayedEventQueue::enqueueDelayed(const Event& event, size_t delayMs, const std::string& eventUUID) { + std::lock_guard<std::recursive_mutex> lock(_mutex); + if(_callbackData.find(eventUUID) != _callbackData.end()) { + cancelDelayed(eventUUID); + } + + _callbackData[eventUUID].eventUUID = eventUUID; + _callbackData[eventUUID].userData = event; + _callbackData[eventUUID].eventQueue = this; + + struct timeval delay = {static_cast<int32_t>(delayMs / 1000), static_cast<int32_t>((delayMs % 1000) * 1000)}; + struct event* e = event_new(_eventLoop, -1, 0, timerCallback, &_callbackData[eventUUID]); + + _callbackData[eventUUID].event = e; + + event_add(e, &delay); +} + +void BasicDelayedEventQueue::cancelAllDelayed() { + std::lock_guard<std::recursive_mutex> lock(_mutex); + + while(_callbackData.size() > 0) { + std::pair<std::string, callbackData> item = *_callbackData.begin(); + Event data = item.second.userData; + event_del(item.second.event); + event_free(item.second.event); + _callbackData.erase(item.first); + } + +} + +void BasicDelayedEventQueue::cancelDelayed(const std::string& eventId) { + std::lock_guard<std::recursive_mutex> lock(_mutex); + + if(_callbackData.find(eventId) != _callbackData.end()) { + event_del(_callbackData[eventId].event); + event_free(_callbackData[eventId].event); + _callbackData.erase(eventId); + } +} + +void BasicDelayedEventQueue::run(void* instance) { + BasicDelayedEventQueue* INSTANCE = (BasicDelayedEventQueue*)instance; + int result; + while(INSTANCE->_isStarted) { + /** + * EVLOOP_NO_EXIT_ON_EMPTY was removed in libevent2.1 - we are + * using the event in the far future approach to get blocking + * behavior back (see comments in contructor) + */ + + // #ifndef EVLOOP_NO_EXIT_ON_EMPTY +// result = event_base_dispatch(INSTANCE->_eventLoop); + // #else + // TODO: this is polling when no events are enqueued + result = event_base_loop(INSTANCE->_eventLoop, EVLOOP_ONCE); +// assert(false); // NON-BLOCKING?! + //#endif + (void)result; + } +} + +void BasicDelayedEventQueue::start() { + if (_isStarted) { + return; + } + _isStarted = true; + _thread = new std::thread(BasicDelayedEventQueue::run, this); +} + +void BasicDelayedEventQueue::stop() { + if (_isStarted) { + _isStarted = false; + event_base_loopbreak(_eventLoop); + cancelAllDelayed(); + } + if (_thread) { + _thread->join(); + delete _thread; + _thread = NULL; + } +} + +void BasicDelayedEventQueue::reset() { + std::lock_guard<std::recursive_mutex> lock(_mutex); + cancelAllDelayed(); + _queue.clear(); +} + +} diff --git a/src/uscxml/interpreter/BasicDelayedEventQueue.h b/src/uscxml/interpreter/BasicDelayedEventQueue.h new file mode 100644 index 0000000..8666e9c --- /dev/null +++ b/src/uscxml/interpreter/BasicDelayedEventQueue.h @@ -0,0 +1,86 @@ +/** + * @file + * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef BASICDELAYEDEVENTQUEUE_H_49D837C4 +#define BASICDELAYEDEVENTQUEUE_H_49D837C4 + +#include "BasicEventQueue.h" +#include <string> +#include <map> +#include <list> +#include <thread> +#include <mutex> +#include <condition_variable> + +#include <event2/event.h> + +namespace uscxml { + +/** + * @ingroup eventqueue + * @ingroup impl + */ +class USCXML_API BasicDelayedEventQueue : public BasicEventQueue, public DelayedEventQueueImpl { +public: + BasicDelayedEventQueue(DelayedEventQueueCallbacks* callbacks); + virtual ~BasicDelayedEventQueue(); + virtual std::shared_ptr<DelayedEventQueueImpl> create(DelayedEventQueueCallbacks* callbacks); + virtual void enqueueDelayed(const Event& event, size_t delayMs, const std::string& eventUUID); + virtual void cancelDelayed(const std::string& eventId); + virtual void cancelAllDelayed(); + virtual Event dequeue(size_t blockMs) { + return BasicEventQueue::dequeue(blockMs); + } + virtual void enqueue(const Event& event) { + return BasicEventQueue::enqueue(event); + } + virtual void reset(); + +protected: + virtual std::shared_ptr<EventQueueImpl> create() { + ErrorEvent e("Cannot create a DelayedEventQueue without callbacks"); + throw e; + } + + struct callbackData { + Event userData; + std::string eventUUID; + bool persist; + struct event *event; + BasicDelayedEventQueue* eventQueue; + }; + + bool _isStarted; + std::thread* _thread; + + std::map<std::string, callbackData> _callbackData; + struct event_base* _eventLoop; + struct event* _dummyEvent; + + static void run(void* instance); + void start(); + void stop(); + + static void timerCallback(evutil_socket_t fd, short what, void *arg); + DelayedEventQueueCallbacks* _callbacks; +}; + +} + +#endif /* end of include guard: BASICDELAYEDEVENTQUEUE_H_49D837C4 */ diff --git a/src/uscxml/interpreter/BasicEventQueue.cpp b/src/uscxml/interpreter/BasicEventQueue.cpp index 287266d..3b51117 100644 --- a/src/uscxml/interpreter/BasicEventQueue.cpp +++ b/src/uscxml/interpreter/BasicEventQueue.cpp @@ -69,146 +69,4 @@ std::shared_ptr<EventQueueImpl> BasicEventQueue::create() { return std::shared_ptr<EventQueueImpl>(new BasicEventQueue()); } -static void dummyCallback(evutil_socket_t fd, short what, void *arg) { - timeval tv; - tv.tv_sec = 365 * 24 * 3600; - tv.tv_usec = 0; - event *ev = *(event **)arg; - evtimer_add(ev, &tv); -} - -BasicDelayedEventQueue::BasicDelayedEventQueue(DelayedEventQueueCallbacks* callbacks) { - _callbacks = callbacks; -#ifndef _WIN32 - evthread_use_pthreads(); -#else - evthread_use_windows_threads(); -#endif - _eventLoop = event_base_new(); - - // see here: https://github.com/named-data/ndn.cxx/blob/master/scheduler/scheduler.cc - // and here: https://www.mail-archive.com/libevent-users@seul.org/msg01676.html - timeval tv; - tv.tv_sec = 365 * 24 * 3600; - tv.tv_usec = 0; - _dummyEvent = evtimer_new(_eventLoop, dummyCallback, &_dummyEvent); - evtimer_add(_dummyEvent, &tv); - - _thread = NULL; - _isStarted = false; - start(); -} - -BasicDelayedEventQueue::~BasicDelayedEventQueue() { - stop(); - evtimer_del(_dummyEvent); - event_free(_dummyEvent); - event_base_free(_eventLoop); -} - -std::shared_ptr<DelayedEventQueueImpl> BasicDelayedEventQueue::create(DelayedEventQueueCallbacks* callbacks) { - return std::shared_ptr<DelayedEventQueueImpl>(new BasicDelayedEventQueue(callbacks)); -} - -void BasicDelayedEventQueue::timerCallback(evutil_socket_t fd, short what, void *arg) { - struct callbackData *data = (struct callbackData*)arg; - std::lock_guard<std::recursive_mutex> lock(data->eventQueue->_mutex); - - if (data->eventQueue->_callbackData.find(data->eventUUID) == data->eventQueue->_callbackData.end()) - return; - - event_free(data->event); - data->eventQueue->_callbacks->eventReady(data->userData, data->eventUUID); - data->eventQueue->_callbackData.erase(data->eventUUID); -} - -void BasicDelayedEventQueue::enqueueDelayed(const Event& event, size_t delayMs, const std::string& eventUUID) { - std::lock_guard<std::recursive_mutex> lock(_mutex); - if(_callbackData.find(eventUUID) != _callbackData.end()) { - cancelDelayed(eventUUID); - } - - _callbackData[eventUUID].eventUUID = eventUUID; - _callbackData[eventUUID].userData = event; - _callbackData[eventUUID].eventQueue = this; - - struct timeval delay = {static_cast<int32_t>(delayMs / 1000), static_cast<int32_t>((delayMs % 1000) * 1000)}; - struct event* e = event_new(_eventLoop, -1, 0, timerCallback, &_callbackData[eventUUID]); - - _callbackData[eventUUID].event = e; - - event_add(e, &delay); -} - -void BasicDelayedEventQueue::cancelAllDelayed() { - std::lock_guard<std::recursive_mutex> lock(_mutex); - - while(_callbackData.size() > 0) { - std::pair<std::string, callbackData> item = *_callbackData.begin(); - Event data = item.second.userData; - event_del(item.second.event); - event_free(item.second.event); - _callbackData.erase(item.first); - } - -} - -void BasicDelayedEventQueue::cancelDelayed(const std::string& eventId) { - std::lock_guard<std::recursive_mutex> lock(_mutex); - - if(_callbackData.find(eventId) != _callbackData.end()) { - event_del(_callbackData[eventId].event); - event_free(_callbackData[eventId].event); - _callbackData.erase(eventId); - } -} - -void BasicDelayedEventQueue::run(void* instance) { - BasicDelayedEventQueue* INSTANCE = (BasicDelayedEventQueue*)instance; - int result; - while(INSTANCE->_isStarted) { - /** - * EVLOOP_NO_EXIT_ON_EMPTY was removed in libevent2.1 - we are - * using the event in the far future approach to get blocking - * behavior back (see comments in contructor) - */ - - // #ifndef EVLOOP_NO_EXIT_ON_EMPTY -// result = event_base_dispatch(INSTANCE->_eventLoop); - // #else - // TODO: this is polling when no events are enqueued - result = event_base_loop(INSTANCE->_eventLoop, EVLOOP_ONCE); -// assert(false); // NON-BLOCKING?! - //#endif - (void)result; - } -} - -void BasicDelayedEventQueue::start() { - if (_isStarted) { - return; - } - _isStarted = true; - _thread = new std::thread(BasicDelayedEventQueue::run, this); -} - -void BasicDelayedEventQueue::stop() { - if (_isStarted) { - _isStarted = false; - event_base_loopbreak(_eventLoop); - cancelAllDelayed(); - } - if (_thread) { - _thread->join(); - delete _thread; - _thread = NULL; - } -} - -void BasicDelayedEventQueue::reset() { - std::lock_guard<std::recursive_mutex> lock(_mutex); - cancelAllDelayed(); - _queue.clear(); -} - } diff --git a/src/uscxml/interpreter/BasicEventQueue.h b/src/uscxml/interpreter/BasicEventQueue.h index 5911336..f9b6965 100644 --- a/src/uscxml/interpreter/BasicEventQueue.h +++ b/src/uscxml/interpreter/BasicEventQueue.h @@ -28,9 +28,6 @@ #include <mutex> #include <condition_variable> -#include <event2/event.h> - - namespace uscxml { /** @@ -52,55 +49,6 @@ protected: std::condition_variable_any _cond; }; -/** - * @ingroup eventqueue - * @ingroup impl - */ -class USCXML_API BasicDelayedEventQueue : public BasicEventQueue, public DelayedEventQueueImpl { -public: - BasicDelayedEventQueue(DelayedEventQueueCallbacks* callbacks); - virtual ~BasicDelayedEventQueue(); - virtual std::shared_ptr<DelayedEventQueueImpl> create(DelayedEventQueueCallbacks* callbacks); - virtual void enqueueDelayed(const Event& event, size_t delayMs, const std::string& eventUUID); - virtual void cancelDelayed(const std::string& eventId); - virtual void cancelAllDelayed(); - virtual Event dequeue(size_t blockMs) { - return BasicEventQueue::dequeue(blockMs); - } - virtual void enqueue(const Event& event) { - return BasicEventQueue::enqueue(event); - } - virtual void reset(); - -protected: - virtual std::shared_ptr<EventQueueImpl> create() { - ErrorEvent e("Cannot create a DelayedEventQueue without callbacks"); - throw e; - } - - struct callbackData { - Event userData; - std::string eventUUID; - bool persist; - struct event *event; - BasicDelayedEventQueue* eventQueue; - }; - - bool _isStarted; - std::thread* _thread; - - std::map<std::string, callbackData> _callbackData; - struct event_base* _eventLoop; - struct event* _dummyEvent; - - static void run(void* instance); - void start(); - void stop(); - - static void timerCallback(evutil_socket_t fd, short what, void *arg); - DelayedEventQueueCallbacks* _callbacks; -}; - } #endif /* end of include guard: BASICEVENTQUEUE_H_39DCC18B */ diff --git a/src/uscxml/interpreter/ContentExecutor.h b/src/uscxml/interpreter/ContentExecutor.h index e17d8dc..ae8ec64 100644 --- a/src/uscxml/interpreter/ContentExecutor.h +++ b/src/uscxml/interpreter/ContentExecutor.h @@ -21,7 +21,6 @@ #define CONTENTEXECUTOR_H_A2D592FA -#include "uscxml/config.h" #include "uscxml/Common.h" #include "uscxml/messages/Data.h" #include <string> diff --git a/src/uscxml/interpreter/ContentExecutorImpl.h b/src/uscxml/interpreter/ContentExecutorImpl.h index 2cf8566..c085756 100644 --- a/src/uscxml/interpreter/ContentExecutorImpl.h +++ b/src/uscxml/interpreter/ContentExecutorImpl.h @@ -22,15 +22,21 @@ #include "uscxml/Common.h" -#include "uscxml/util/DOM.h" #include "uscxml/messages/Event.h" #include "uscxml/interpreter/InterpreterMonitor.h" -#include <xercesc/dom/DOM.hpp> #include <string> +#include <set> + +namespace XERCESC_NS { + class DOMDocument; + class DOMNode; +} namespace uscxml { +class X; + /** * @ingroup execcontent * @ingroup callback diff --git a/src/uscxml/interpreter/EventQueueImpl.h b/src/uscxml/interpreter/EventQueueImpl.h index 4420c24..68c6d7c 100644 --- a/src/uscxml/interpreter/EventQueueImpl.h +++ b/src/uscxml/interpreter/EventQueueImpl.h @@ -29,8 +29,6 @@ #include <mutex> #include <condition_variable> -#include <event2/event.h> - namespace uscxml { diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp index 0f77285..85c77a8 100644 --- a/src/uscxml/interpreter/InterpreterImpl.cpp +++ b/src/uscxml/interpreter/InterpreterImpl.cpp @@ -23,6 +23,7 @@ #include "uscxml/Interpreter.h" #include "uscxml/interpreter/InterpreterImpl.h" // beware cyclic reference! #include "uscxml/interpreter/BasicEventQueue.h" +#include "uscxml/interpreter/BasicDelayedEventQueue.h" #include "uscxml/messages/Event.h" #include "uscxml/util/String.h" #include "uscxml/util/Predicates.h" diff --git a/src/uscxml/interpreter/InterpreterImpl.h b/src/uscxml/interpreter/InterpreterImpl.h index 9b784d3..ade2a91 100644 --- a/src/uscxml/interpreter/InterpreterImpl.h +++ b/src/uscxml/interpreter/InterpreterImpl.h @@ -35,7 +35,6 @@ #include "uscxml/interpreter/EventQueue.h" #include "uscxml/interpreter/EventQueueImpl.h" #include "uscxml/util/DOM.h" -#include <xercesc/dom/DOM.hpp> namespace uscxml { diff --git a/src/uscxml/interpreter/InterpreterMonitor.h b/src/uscxml/interpreter/InterpreterMonitor.h index 80065f7..a3c527d 100644 --- a/src/uscxml/interpreter/InterpreterMonitor.h +++ b/src/uscxml/interpreter/InterpreterMonitor.h @@ -20,7 +20,6 @@ #ifndef INTERPRETERMONITOR_H_D3F21429 #define INTERPRETERMONITOR_H_D3F21429 -#include "uscxml/config.h" #include "uscxml/Common.h" #include "uscxml/messages/Event.h" #include "uscxml/debug/InterpreterIssue.h" diff --git a/src/uscxml/interpreter/MicroStep.h b/src/uscxml/interpreter/MicroStep.h index 341be2e..9238fc8 100644 --- a/src/uscxml/interpreter/MicroStep.h +++ b/src/uscxml/interpreter/MicroStep.h @@ -25,11 +25,9 @@ #include <list> #include <string> -#include "uscxml/config.h" #include "uscxml/Common.h" #include "uscxml/interpreter/InterpreterState.h" -// #include <xercesc/dom/DOM.hpp> // forward declare namespace XERCESC_NS { diff --git a/src/uscxml/interpreter/MicroStepImpl.h b/src/uscxml/interpreter/MicroStepImpl.h index d831fdd..110dbd2 100644 --- a/src/uscxml/interpreter/MicroStepImpl.h +++ b/src/uscxml/interpreter/MicroStepImpl.h @@ -20,12 +20,9 @@ #ifndef MICROSTEPIMPL_H_98233709 #define MICROSTEPIMPL_H_98233709 -#include "uscxml/config.h" - #include <list> #include <set> #include <string> -#include <xercesc/dom/DOM.hpp> #include "uscxml/Common.h" #include "uscxml/Interpreter.h" diff --git a/src/uscxml/messages/Data.h b/src/uscxml/messages/Data.h index 899ede9..c863e41 100644 --- a/src/uscxml/messages/Data.h +++ b/src/uscxml/messages/Data.h @@ -24,7 +24,6 @@ #include <map> #include <memory> -#include "uscxml/config.h" #include "uscxml/Common.h" #include "uscxml/util/Convenience.h" #include "uscxml/messages/Blob.h" diff --git a/src/uscxml/plugins/DataModelImpl.h b/src/uscxml/plugins/DataModelImpl.h index e21be9a..444a9d4 100644 --- a/src/uscxml/plugins/DataModelImpl.h +++ b/src/uscxml/plugins/DataModelImpl.h @@ -20,12 +20,14 @@ #ifndef DATAMODELIMPL_H_5A33C087 #define DATAMODELIMPL_H_5A33C087 -#include "uscxml/config.h" #include "uscxml/Common.h" #include "uscxml/plugins/Invoker.h" #include "uscxml/plugins/IOProcessor.h" -#include <xercesc/dom/DOM.hpp> +namespace XERCESC_NS { + class DOMDocument; + class DOMNode; +} #include <list> #include <string> diff --git a/src/uscxml/plugins/ExecutableContent.h b/src/uscxml/plugins/ExecutableContent.h index 5fb2ac6..8ff9430 100644 --- a/src/uscxml/plugins/ExecutableContent.h +++ b/src/uscxml/plugins/ExecutableContent.h @@ -20,7 +20,6 @@ #ifndef EXECUTABLECONTENT_H_1E028A2D #define EXECUTABLECONTENT_H_1E028A2D -#include "uscxml/config.h" #include "uscxml/Common.h" #include <string> diff --git a/src/uscxml/plugins/ExecutableContentImpl.h b/src/uscxml/plugins/ExecutableContentImpl.h index d033d1e..5424717 100644 --- a/src/uscxml/plugins/ExecutableContentImpl.h +++ b/src/uscxml/plugins/ExecutableContentImpl.h @@ -20,14 +20,17 @@ #ifndef EXECUTABLECONTENTIMPL_H_CCE9F02D #define EXECUTABLECONTENTIMPL_H_CCE9F02D -#include "uscxml/config.h" #include "uscxml/Common.h" -#include <xercesc/dom/DOM.hpp> #include <string> #include <memory> #include <sstream> +namespace XERCESC_NS { + class DOMDocument; + class DOMNode; +} + namespace uscxml { class InterpreterImpl; diff --git a/src/uscxml/plugins/Invoker.h b/src/uscxml/plugins/Invoker.h index f5c55d5..54458f0 100644 --- a/src/uscxml/plugins/Invoker.h +++ b/src/uscxml/plugins/Invoker.h @@ -21,15 +21,14 @@ #define INVOKER_H_CAC11892 -#include "uscxml/config.h" #include "uscxml/Common.h" #include "uscxml/plugins/EventHandler.h" #include "uscxml/messages/Event.h" -#include <xercesc/dom/DOM.hpp> namespace XERCESC_NS { -class DOMDocument; -class DOMNode; + class DOMElement; + class DOMDocument; + class DOMNode; } namespace uscxml { diff --git a/src/uscxml/plugins/datamodel/CMakeLists.txt b/src/uscxml/plugins/datamodel/CMakeLists.txt index 6409a7a..e68fc8f 100644 --- a/src/uscxml/plugins/datamodel/CMakeLists.txt +++ b/src/uscxml/plugins/datamodel/CMakeLists.txt @@ -36,7 +36,7 @@ if (V8_FOUND) endif() -if (LUA51_FOUND) +if (LUA51_FOUND AND WITH_DM_LUA) set(USCXML_DATAMODELS "lua ${USCXML_DATAMODELS}") # Lua ecmascript datamodel file(GLOB LUA_DATAMODEL diff --git a/src/uscxml/util/DOM.h b/src/uscxml/util/DOM.h index e8094cf..2b133d8 100644 --- a/src/uscxml/util/DOM.h +++ b/src/uscxml/util/DOM.h @@ -24,25 +24,10 @@ #include <list> #include <iostream> -#include "uscxml/config.h" #include "uscxml/Common.h" #include <xercesc/util/XMLString.hpp> #include <xercesc/dom/DOM.hpp> - -/* -#define TAGNAME_CAST(elem) ((Arabica::DOM::Element<std::string>)elem).getTagName() -#define LOCALNAME_CAST(elem) ((Arabica::DOM::Element<std::string>)elem).getLocalName() -#define ATTR_CAST(elem, attr) ((Arabica::DOM::Element<std::string>)elem).getAttribute(attr) -#define ATTR_NODE_CAST(elem, attr) ((Arabica::DOM::Element<std::string>)elem).getAttributeNode(attr) -#define HAS_ATTR_CAST(elem, attr) ((Arabica::DOM::Element<std::string>)elem).hasAttribute(attr) - -#define TAGNAME(elem) elem.getTagName() -#define LOCALNAME(elem) elem.getLocalName() -#define ATTR(elem, attr) elem.getAttribute(attr) -#define ATTR_NODE(elem, attr) elem.getAttributeNode(attr) -*/ - #define HAS_ATTR(elem, attr) (elem)->hasAttribute(X(attr)) #define HAS_ATTR_CAST(elem, attr) HAS_ATTR(static_cast<const DOMElement*>(elem), attr) #define ATTR(elem, attr) std::string(X((elem)->getAttribute(X(attr)))) diff --git a/src/uscxml/util/URL.cpp b/src/uscxml/util/URL.cpp index 7978793..9329e7e 100644 --- a/src/uscxml/util/URL.cpp +++ b/src/uscxml/util/URL.cpp @@ -26,6 +26,9 @@ #include "uscxml/interpreter/Logging.h" #include "uscxml/config.h" +#include <curl/curl.h> +#include <uriparser/Uri.h> + #ifdef _WIN32 #include <direct.h> @@ -36,14 +39,17 @@ //#include <pwd.h> #endif +#define DOWNLOAD_IF_NECESSARY if (!_isDownloaded) { download(true); } +#define USCXML_URI_STRING(obj, field) std::string(obj.field.first, (obj.field.afterLast - obj.field.first)) + namespace uscxml { -void URLImpl::prepareException(ErrorEvent& exception, int errorCode, const std::string& origUri, UriParserStateA* parser) { + void URLImpl::prepareException(ErrorEvent& exception, int errorCode, const std::string& origUri, void* parser) { exception.data.compound["uri"].atom = origUri; - if (parser != NULL && parser->errorPos != NULL) { + if (parser != NULL && ((UriParserStateA*)parser)->errorPos != NULL) { const char* startPtr = origUri.c_str(); - while(startPtr != parser->errorPos && *startPtr != '\0') { + while(startPtr != ((UriParserStateA*)parser)->errorPos && *startPtr != '\0') { exception.data.compound["urk"].atom += " "; startPtr++; } @@ -82,16 +88,18 @@ void URLImpl::prepareException(ErrorEvent& exception, int errorCode, const std:: } URLImpl::URLImpl() : _handle(NULL), _requestType(GET), _isDownloaded(false), _hasFailed(false) { + _uri = malloc(sizeof(UriUriA)); } URLImpl::URLImpl(const std::string& url) : _orig(url), _handle(NULL), _requestType(GET), _isDownloaded(false), _hasFailed(false) { UriParserStateA state; - state.uri = &_uri; + _uri = malloc(sizeof(UriUriA)); + state.uri = (UriUriA*)_uri; int err = uriParseUriA(&state, _orig.c_str()); if (err != URI_SUCCESS) { UriParserStateA state2; - state2.uri = &_uri; + state2.uri = (UriUriA*)_uri; char* tmp = (char*)malloc(8 + 3 * _orig.size() + 1); uriWindowsFilenameToUriStringA(_orig.c_str(), tmp); @@ -102,7 +110,7 @@ URLImpl::URLImpl(const std::string& url) : _orig(url), _handle(NULL), _requestTy if (err != URI_SUCCESS) { UriParserStateA state2; - state2.uri = &_uri; + state2.uri = (UriUriA*)_uri; char* tmp = (char*)malloc(7 + 3 * _orig.size() + 1 ); uriUnixFilenameToUriStringA(_orig.c_str(), tmp); @@ -119,14 +127,17 @@ URLImpl::URLImpl(const std::string& url) : _orig(url), _handle(NULL), _requestTy } URLImpl::~URLImpl() { - uriFreeUriMembersA(&_uri); + uriFreeUriMembersA((UriUriA*)_uri); if (_handle != NULL) curl_easy_cleanup(_handle); + free(_uri); } URL URLImpl::resolve(URLImpl* relative, URLImpl* absolute) { std::shared_ptr<URLImpl> dest(new URLImpl()); - int err = uriAddBaseUriExA(&(dest->_uri), &(relative->_uri), &(absolute->_uri), URI_RESOLVE_IDENTICAL_SCHEME_COMPAT); + int err = uriAddBaseUriExA(((UriUriA*)dest->_uri), + ((UriUriA*)relative->_uri), + ((UriUriA*)absolute->_uri), URI_RESOLVE_IDENTICAL_SCHEME_COMPAT); if (err != URI_SUCCESS) { ErrorEvent exc("Cannot resolve " + (std::string)(*relative) + " with " + (std::string)(*absolute)); prepareException(exc, err, "", NULL); @@ -156,7 +167,9 @@ URL URLImpl::resolveWithCWD(URLImpl* relative) { URL URLImpl::refer(URLImpl* absoluteSource, URLImpl* absoluteBase) { std::shared_ptr<URLImpl> dest(new URLImpl()); - int err = uriRemoveBaseUriA(&(dest->_uri), &(absoluteSource->_uri), &(absoluteBase->_uri), URI_FALSE); + int err = uriRemoveBaseUriA(((UriUriA*)dest->_uri), + ((UriUriA*)absoluteSource->_uri), + ((UriUriA*)absoluteBase->_uri), URI_FALSE); if (err != URI_SUCCESS) { ErrorEvent exc("Cannot make a relative reference for " + (std::string)(*absoluteSource) + " with " + (std::string)(*absoluteBase)); prepareException(exc, err, "", NULL); @@ -168,7 +181,7 @@ URL URLImpl::refer(URLImpl* absoluteSource, URLImpl* absoluteBase) { } void URLImpl::normalize() { - int err = uriNormalizeSyntaxA(&_uri); + int err = uriNormalizeSyntaxA((UriUriA*)_uri); if (err != URI_SUCCESS) { ErrorEvent exc("Cannot normalize URL " + (std::string)*this); prepareException(exc, err, _orig, NULL); @@ -176,8 +189,33 @@ void URLImpl::normalize() { } } +bool URLImpl::isAbsolute() const { + // see https://sourceforge.net/p/uriparser/bugs/3/ + return ((UriUriA*)_uri)->absolutePath || ((((UriUriA*)_uri)->hostText.first != nullptr) && (((UriUriA*)_uri)->pathHead != nullptr)); +} + +std::string URLImpl::scheme() const { + return USCXML_URI_STRING((*(UriUriA*)_uri), scheme); +} + +std::string URLImpl::userInfo() const { + return USCXML_URI_STRING((*(UriUriA*)_uri), userInfo); +} + +std::string URLImpl::host() const { + return USCXML_URI_STRING((*(UriUriA*)_uri), hostText); +} + +std::string URLImpl::port() const { + return USCXML_URI_STRING((*(UriUriA*)_uri), portText); +} + +std::string URLImpl::fragment() const { + return USCXML_URI_STRING((*(UriUriA*)_uri), fragment); +} + std::string URLImpl::path() const { - UriPathSegmentA* firstSeg = _uri.pathHead; + UriPathSegmentA* firstSeg = ((UriUriA*)_uri)->pathHead; UriPathSegmentA* lastSeg = firstSeg; while(lastSeg->next) { lastSeg = lastSeg->next; @@ -186,12 +224,12 @@ std::string URLImpl::path() const { std::string path; // what a mess! - if (_uri.absolutePath || - (_uri.pathHead != NULL && - (_uri.hostText.first != NULL || - _uri.hostData.ip4 != NULL || - _uri.hostData.ip6 != NULL || - _uri.hostData.ipFuture.first != NULL))) { + if (((UriUriA*)_uri)->absolutePath || + (((UriUriA*)_uri)->pathHead != NULL && + (((UriUriA*)_uri)->hostText.first != NULL || + ((UriUriA*)_uri)->hostData.ip4 != NULL || + ((UriUriA*)_uri)->hostData.ip6 != NULL || + ((UriUriA*)_uri)->hostData.ipFuture.first != NULL))) { path += "/"; } path += std::string(firstSeg->text.first, lastSeg->text.afterLast - firstSeg->text.first); @@ -201,7 +239,7 @@ std::string URLImpl::path() const { std::list<std::string> URLImpl::pathComponents() const { std::list<std::string> pathList; - UriPathSegmentA* currSeg = _uri.pathHead; + UriPathSegmentA* currSeg = ((UriUriA*)_uri)->pathHead; while(currSeg != NULL) { pathList.push_back(USCXML_URI_STRING((*currSeg), text)); currSeg = currSeg->next; @@ -216,7 +254,7 @@ std::map<std::string, std::string> URLImpl::query() const { std::map<std::string, std::string> queryMap; int itemCount; - int err = uriDissectQueryMallocA(&queryList, &itemCount, _uri.query.first, _uri.query.afterLast); + int err = uriDissectQueryMallocA(&queryList, &itemCount, (*(UriUriA*)_uri).query.first, (*(UriUriA*)_uri).query.afterLast); if (err != URI_SUCCESS) { ErrorEvent exc("Cannot get query from URL " + (std::string)*this); prepareException(exc, err, _orig, NULL); @@ -327,10 +365,10 @@ void URLImpl::downloadCompleted() { } } -void URLImpl::downloadFailed(CURLcode errorCode) { +void URLImpl::downloadFailed(int errorCode) { std::lock_guard<std::recursive_mutex> lock(_mutex); - _error = curl_easy_strerror(errorCode); + _error = curl_easy_strerror((CURLcode)errorCode); _hasFailed = true; _isDownloaded = false; _condVar.notify_all(); @@ -342,6 +380,48 @@ void URLImpl::downloadFailed(CURLcode errorCode) { } } + +void URLImpl::addOutHeader(const std::string& key, const std::string& value) { + _outHeader[key] = value; +} +void URLImpl::setOutContent(const std::string& content) { + _outContent = content; + _requestType = URLRequestType::POST; +} +void URLImpl::setRequestType(URLRequestType requestType) { + _requestType = requestType; + +} + +const std::map<std::string, std::string> URLImpl::getInHeaderFields() { + DOWNLOAD_IF_NECESSARY + return _inHeaders; +} + +const std::string URLImpl::getInHeaderField(const std::string& key) { + DOWNLOAD_IF_NECESSARY + if (_inHeaders.find(key) != _inHeaders.end()) { + return _inHeaders[key]; + } + return ""; +} + +const std::string URLImpl::getStatusCode() const { + // DOWNLOAD_IF_NECESSARY + return _statusCode; +} + +const std::string URLImpl::getStatusMessage() const { + // DOWNLOAD_IF_NECESSARY + return _statusMsg; +} + +const std::string URLImpl::getInContent(bool forceReload) { + if (forceReload) + _isDownloaded = false; + DOWNLOAD_IF_NECESSARY + return _rawInContent.str(); +} const void URLImpl::download(bool blocking) { std::lock_guard<std::recursive_mutex> lock(_mutex); @@ -399,7 +479,7 @@ URLImpl::operator Data() const { URLImpl::operator std::string() const { int charsRequired = 0; - if (uriToStringCharsRequiredA(&_uri, &charsRequired) != URI_SUCCESS) { + if (uriToStringCharsRequiredA((UriUriA*)_uri, &charsRequired) != URI_SUCCESS) { throw ErrorEvent("Cannot recompose URL"); } charsRequired++; @@ -410,7 +490,7 @@ URLImpl::operator std::string() const { throw ErrorEvent("Malloc failed"); } - if (uriToStringA(uriString, &_uri, charsRequired, NULL) != URI_SUCCESS) { + if (uriToStringA(uriString, (UriUriA*)_uri, charsRequired, NULL) != URI_SUCCESS) { free(uriString); throw ErrorEvent("Cannot recompose URL"); } @@ -635,7 +715,7 @@ void URLFetcher::breakURL(URL& url) { instance->_handlesToURLs.erase(handle); } if (instance->_handlesToHeaders.find(handle) != instance->_handlesToHeaders.end()) { - curl_slist_free_all(instance->_handlesToHeaders[handle]); + curl_slist_free_all((struct curl_slist *)instance->_handlesToHeaders[handle]); instance->_handlesToHeaders.erase(handle); } } @@ -765,7 +845,7 @@ void URLFetcher::perform() { } _handlesToURLs.erase(msg->easy_handle); - curl_slist_free_all(_handlesToHeaders[msg->easy_handle]); + curl_slist_free_all((struct curl_slist *)_handlesToHeaders[msg->easy_handle]); _handlesToHeaders.erase(msg->easy_handle); } else { diff --git a/src/uscxml/util/URL.h b/src/uscxml/util/URL.h index f6da30d..a603c63 100644 --- a/src/uscxml/util/URL.h +++ b/src/uscxml/util/URL.h @@ -23,8 +23,6 @@ #include "uscxml/Common.h" #include "uscxml/messages/Event.h" -#define DOWNLOAD_IF_NECESSARY if (!_isDownloaded) { download(true); } - #include <string> #include <sstream> #include <map> @@ -32,10 +30,6 @@ #include <list> #include <thread> #include <condition_variable> -#include <curl/curl.h> -#include <uriparser/Uri.h> - -#define USCXML_URI_STRING(obj, field) std::string(obj.field.first, obj.field.afterLast - obj.field.first) namespace uscxml { @@ -60,31 +54,12 @@ public: URLImpl(const std::string& url); ~URLImpl(); - bool isAbsolute() const { - // see https://sourceforge.net/p/uriparser/bugs/3/ - return _uri.absolutePath || ((_uri.hostText.first != nullptr) && (_uri.pathHead != nullptr)); - } - - std::string scheme() const { - return USCXML_URI_STRING(_uri, scheme); - } - - std::string userInfo() const { - return USCXML_URI_STRING(_uri, userInfo); - } - - std::string host() const { - return USCXML_URI_STRING(_uri, hostText); - } - - std::string port() const { - return USCXML_URI_STRING(_uri, portText); - } - - std::string fragment() const { - return USCXML_URI_STRING(_uri, fragment); - } - + bool isAbsolute() const; + std::string scheme() const; + std::string userInfo() const; + std::string host() const; + std::string port() const; + std::string fragment() const; std::map<std::string, std::string> query() const; std::string path() const; std::list<std::string> pathComponents() const; @@ -103,48 +78,15 @@ public: } // downloading / uploading - void addOutHeader(const std::string& key, const std::string& value) { - _outHeader[key] = value; - } - void setOutContent(const std::string& content) { - _outContent = content; - _requestType = URLRequestType::POST; - } - void setRequestType(URLRequestType requestType) { - _requestType = requestType; - - } - - const std::map<std::string, std::string> getInHeaderFields() { - DOWNLOAD_IF_NECESSARY - return _inHeaders; - } - - const std::string getInHeaderField(const std::string& key) { - DOWNLOAD_IF_NECESSARY - if (_inHeaders.find(key) != _inHeaders.end()) { - return _inHeaders[key]; - } - return ""; - } - - const std::string getStatusCode() const { -// DOWNLOAD_IF_NECESSARY - return _statusCode; - } - - const std::string getStatusMessage() const { -// DOWNLOAD_IF_NECESSARY - return _statusMsg; - } - - const std::string getInContent(bool forceReload = false) { - if (forceReload) - _isDownloaded = false; - DOWNLOAD_IF_NECESSARY - return _rawInContent.str(); - } - + void addOutHeader(const std::string& key, const std::string& value); + void setOutContent(const std::string& content); + void setRequestType(URLRequestType requestType); + const std::map<std::string, std::string> getInHeaderFields(); + const std::string getInHeaderField(const std::string& key); + + const std::string getStatusCode() const; + const std::string getStatusMessage() const; + const std::string getInContent(bool forceReload = false); const void download(bool blocking = false); operator Data() const; @@ -152,20 +94,20 @@ public: protected: URLImpl(); - UriUriA _uri; + void* _uri = NULL; std::string _orig; - CURL* getCurlHandle(); + void* getCurlHandle(); static size_t writeHandler(void *ptr, size_t size, size_t nmemb, void *userdata); static size_t headerHandler(void *ptr, size_t size, size_t nmemb, void *userdata); void downloadStarted(); void downloadCompleted(); - void downloadFailed(CURLcode errorCode); + void downloadFailed(int errorCode); - static void prepareException(ErrorEvent& exception, int errorCode, const std::string& origUri, UriParserStateA* parser); + static void prepareException(ErrorEvent& exception, int errorCode, const std::string& origUri, void* parser); - CURL* _handle = NULL; + void* _handle = NULL; std::stringstream _rawInContent; std::stringstream _rawInHeader; std::map<std::string, std::string> _inHeaders; @@ -324,10 +266,10 @@ protected: std::recursive_mutex _mutex; bool _isStarted; - std::map<CURL*, URL> _handlesToURLs; - std::map<CURL*, curl_slist*> _handlesToHeaders; - CURLM* _multiHandle; - char* _envProxy; + std::map<void*, URL> _handlesToURLs; + std::map<void*, void*> _handlesToHeaders; + void* _multiHandle = NULL; + char* _envProxy = NULL; }; } |