random ai stuff
This commit is contained in:
89
telldus-core/common/CMakeLists.txt
Normal file
89
telldus-core/common/CMakeLists.txt
Normal file
@@ -0,0 +1,89 @@
|
||||
IF(COMMAND cmake_policy)
|
||||
CMAKE_POLICY(SET CMP0003 NEW)
|
||||
ENDIF(COMMAND cmake_policy)
|
||||
|
||||
######## Non configurable options ########
|
||||
SET( telldus-common_SRCS
|
||||
Event.cpp
|
||||
Message.cpp
|
||||
Mutex.cpp
|
||||
Strings.cpp
|
||||
Thread.cpp
|
||||
)
|
||||
|
||||
SET( telldus-common_HDRS
|
||||
common.h
|
||||
Event.h
|
||||
EventHandler.h
|
||||
Message.h
|
||||
Mutex.h
|
||||
Socket.h
|
||||
Strings.h
|
||||
Thread.h
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} )
|
||||
|
||||
######## Configurable options for the platform ########
|
||||
|
||||
|
||||
######## Platforms-specific, non configurable ########
|
||||
|
||||
IF (APPLE)
|
||||
#### Mac OS X ####
|
||||
FIND_LIBRARY(ICONV_LIBRARY iconv)
|
||||
ADD_DEFINITIONS( -D_MACOSX )
|
||||
LIST(APPEND telldus-common_SRCS
|
||||
Event_unix.cpp
|
||||
EventHandler_unix.cpp
|
||||
Socket_unix.cpp
|
||||
stdlibc_workaround.cpp #Remove this when we drop support for 10.5
|
||||
)
|
||||
LIST(APPEND telldus-common_LIBRARIES
|
||||
${ICONV_LIBRARY}
|
||||
)
|
||||
ELSEIF (WIN32)
|
||||
#### Windows ####
|
||||
ADD_DEFINITIONS( -DUNICODE )
|
||||
ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No
|
||||
ADD_DEFINITIONS( -D_WINDOWS )
|
||||
LIST(APPEND telldus-common_SRCS
|
||||
Event_win.cpp
|
||||
EventHandler_win.cpp
|
||||
Socket_win.cpp
|
||||
)
|
||||
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
#### FreeBSD ####
|
||||
FIND_LIBRARY(ICONV_LIBRARY iconv)
|
||||
ADD_DEFINITIONS( -D_FREEBSD )
|
||||
LIST(APPEND telldus-common_SRCS
|
||||
Event_unix.cpp
|
||||
EventHandler_unix.cpp
|
||||
Socket_unix.cpp
|
||||
)
|
||||
LIST(APPEND telldus-common_LIBRARIES
|
||||
${ICONV_LIBRARY}
|
||||
)
|
||||
ELSE (APPLE)
|
||||
#### Linux ####
|
||||
ADD_DEFINITIONS( -D_LINUX )
|
||||
LIST(APPEND telldus-common_SRCS
|
||||
Event_unix.cpp
|
||||
EventHandler_unix.cpp
|
||||
Socket_unix.cpp
|
||||
)
|
||||
ENDIF (APPLE)
|
||||
|
||||
|
||||
######## Configuring ########
|
||||
|
||||
ADD_LIBRARY(TelldusCommon STATIC
|
||||
${telldus-common_SRCS}
|
||||
${telldus-common_HDRS}
|
||||
)
|
||||
|
||||
IF (UNIX)
|
||||
SET_TARGET_PROPERTIES( TelldusCommon PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden")
|
||||
ENDIF (UNIX)
|
||||
|
||||
TARGET_LINK_LIBRARIES( TelldusCommon ${telldus-common_LIBRARIES} )
|
||||
88
telldus-core/common/Event.cpp
Normal file
88
telldus-core/common/Event.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include "common/Event.h"
|
||||
#include <list>
|
||||
#include "common/EventHandler.h"
|
||||
#include "common/Mutex.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
EventData::~EventData() {
|
||||
}
|
||||
|
||||
bool EventData::isValid() const {
|
||||
return false;
|
||||
};
|
||||
|
||||
bool EventDataBase::isValid() const {
|
||||
return true;
|
||||
};
|
||||
|
||||
class EventBase::PrivateData {
|
||||
public:
|
||||
TelldusCore::Mutex mutex;
|
||||
EventHandler *handler;
|
||||
std::list<EventDataRef> eventDataList;
|
||||
};
|
||||
|
||||
EventBase::EventBase(TelldusCore::EventHandler *handler) {
|
||||
d = new PrivateData;
|
||||
d->handler = handler;
|
||||
}
|
||||
|
||||
EventBase::~EventBase(void) {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void EventBase::clearHandler() {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
d->handler = 0;
|
||||
}
|
||||
|
||||
void EventBase::popSignal() {
|
||||
this->takeSignal();
|
||||
}
|
||||
|
||||
EventHandler *EventBase::handler() const {
|
||||
return d->handler;
|
||||
}
|
||||
|
||||
bool EventBase::isSignaled() {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
return (d->eventDataList.size() > 0);
|
||||
}
|
||||
|
||||
void EventBase::signal() {
|
||||
signal(new EventData());
|
||||
}
|
||||
|
||||
void EventBase::signal(EventData *eventData) {
|
||||
this->signal(EventDataRef(eventData));
|
||||
}
|
||||
|
||||
void EventBase::signal(EventDataRef eventData) {
|
||||
{
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
d->eventDataList.push_back(eventData);
|
||||
}
|
||||
sendSignal();
|
||||
}
|
||||
|
||||
EventDataRef EventBase::takeSignal() {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
if (d->eventDataList.size() == 0) {
|
||||
return EventDataRef(new EventData());
|
||||
}
|
||||
EventDataRef data = d->eventDataList.front();
|
||||
d->eventDataList.pop_front();
|
||||
if (d->eventDataList.size() == 0) {
|
||||
this->clearSignal();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
80
telldus-core/common/Event.h
Normal file
80
telldus-core/common/Event.h
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#ifndef TELLDUS_CORE_COMMON_EVENT_H_
|
||||
#define TELLDUS_CORE_COMMON_EVENT_H_
|
||||
|
||||
|
||||
#ifndef _WINDOWS
|
||||
#include <tr1/memory>
|
||||
typedef void* EVENT_T;
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <memory>
|
||||
typedef HANDLE EVENT_T;
|
||||
#endif
|
||||
#include "common/Thread.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
class EventHandler;
|
||||
|
||||
class EventData {
|
||||
public:
|
||||
virtual ~EventData();
|
||||
virtual bool isValid() const;
|
||||
};
|
||||
|
||||
class EventDataBase : public EventData {
|
||||
public:
|
||||
virtual bool isValid() const;
|
||||
};
|
||||
|
||||
typedef std::tr1::shared_ptr<EventData> EventDataRef;
|
||||
|
||||
class EventBase {
|
||||
public:
|
||||
virtual ~EventBase();
|
||||
|
||||
void popSignal();
|
||||
bool isSignaled();
|
||||
void signal();
|
||||
void signal(EventData *eventData);
|
||||
void signal(EventDataRef eventData);
|
||||
EventDataRef takeSignal();
|
||||
|
||||
protected:
|
||||
explicit EventBase(EventHandler *handler);
|
||||
void clearHandler();
|
||||
virtual void clearSignal() = 0;
|
||||
EventHandler *handler() const;
|
||||
virtual void sendSignal() = 0;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d;
|
||||
};
|
||||
|
||||
class Event : public EventBase {
|
||||
public:
|
||||
virtual ~Event();
|
||||
|
||||
protected:
|
||||
explicit Event(EventHandler *handler);
|
||||
EVENT_T retrieveNative();
|
||||
virtual void clearSignal();
|
||||
virtual void sendSignal();
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d;
|
||||
|
||||
friend class EventHandler;
|
||||
};
|
||||
|
||||
typedef std::tr1::shared_ptr<Event> EventRef;
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_EVENT_H_
|
||||
39
telldus-core/common/EventHandler.h
Normal file
39
telldus-core/common/EventHandler.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#ifndef TELLDUS_CORE_COMMON_EVENTHANDLER_H_
|
||||
#define TELLDUS_CORE_COMMON_EVENTHANDLER_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include "common/Event.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class EventHandler {
|
||||
public:
|
||||
EventHandler();
|
||||
virtual ~EventHandler(void);
|
||||
|
||||
EventRef addEvent();
|
||||
|
||||
bool waitForAny();
|
||||
|
||||
protected:
|
||||
void signal(Event *event);
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d;
|
||||
bool listIsSignalled();
|
||||
friend class Event;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_EVENTHANDLER_H_
|
||||
96
telldus-core/common/EventHandler_unix.cpp
Normal file
96
telldus-core/common/EventHandler_unix.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <list>
|
||||
#include "common/EventHandler.h"
|
||||
#include "common/Event.h"
|
||||
#include "common/Mutex.h"
|
||||
#include "common/Thread.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class EventHandler::PrivateData {
|
||||
public:
|
||||
pthread_cond_t event;
|
||||
pthread_mutex_t mutex;
|
||||
std::list<EventRef> eventList;
|
||||
TelldusCore::Mutex listMutex;
|
||||
bool isSignalled;
|
||||
};
|
||||
|
||||
EventHandler::EventHandler() {
|
||||
d = new PrivateData;
|
||||
pthread_cond_init(&d->event, NULL);
|
||||
pthread_cond_init(&d->event, NULL);
|
||||
pthread_mutex_init(&d->mutex, NULL);
|
||||
d->isSignalled = false;
|
||||
}
|
||||
|
||||
EventHandler::~EventHandler(void) {
|
||||
pthread_mutex_destroy(&d->mutex);
|
||||
pthread_cond_destroy(&d->event);
|
||||
|
||||
std::list<EventRef>::const_iterator it = d->eventList.begin();
|
||||
for(; it != d->eventList.end(); ++it) {
|
||||
// We clear the handler if someone else still has a reference to the event
|
||||
(*it)->clearHandler();
|
||||
}
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
EventRef EventHandler::addEvent() {
|
||||
EventRef event(new Event(this));
|
||||
TelldusCore::MutexLocker locker(&d->listMutex);
|
||||
d->eventList.push_back(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
bool EventHandler::listIsSignalled() {
|
||||
TelldusCore::MutexLocker locker(&d->listMutex);
|
||||
|
||||
std::list<EventRef>::const_iterator it = d->eventList.begin();
|
||||
for(; it != d->eventList.end(); ++it) {
|
||||
if((*it)->isSignaled()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EventHandler::signal(Event *event) {
|
||||
pthread_mutex_lock(&d->mutex);
|
||||
d->isSignalled = true;
|
||||
// event->setSignaled();
|
||||
pthread_cond_signal(&d->event);
|
||||
pthread_mutex_unlock(&d->mutex);
|
||||
}
|
||||
|
||||
bool EventHandler::waitForAny() {
|
||||
pthread_mutex_lock(&d->mutex);
|
||||
int ret;
|
||||
while (!d->isSignalled) {
|
||||
timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
uint64_t abstime_ns_large = now.tv_usec*1000 + 60000000000; // add 60 seconds wait (5 seconds before)?
|
||||
timespec abstime = { now.tv_sec + (abstime_ns_large / 1000000000), abstime_ns_large % 1000000000 };
|
||||
ret = pthread_cond_timedwait(&d->event, &d->mutex, &abstime);
|
||||
if (ret == ETIMEDOUT) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!listIsSignalled()) {
|
||||
d->isSignalled = false;
|
||||
}
|
||||
pthread_mutex_unlock(&d->mutex);
|
||||
return listIsSignalled();
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
76
telldus-core/common/EventHandler_win.cpp
Normal file
76
telldus-core/common/EventHandler_win.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include "common/EventHandler.h"
|
||||
#include <windows.h>
|
||||
#include <list>
|
||||
|
||||
#include "common/Event.h"
|
||||
#include "common/Mutex.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class EventHandler::PrivateData {
|
||||
public:
|
||||
HANDLE *eventArray;
|
||||
EventRef *eventObjectArray;
|
||||
TelldusCore::Mutex mutex;
|
||||
int eventCount;
|
||||
};
|
||||
|
||||
EventHandler::EventHandler() {
|
||||
d = new PrivateData;
|
||||
d->eventCount = 0;
|
||||
d->eventArray = new HANDLE[0];
|
||||
d->eventObjectArray = new EventRef[0];
|
||||
}
|
||||
|
||||
EventHandler::~EventHandler(void) {
|
||||
delete[] d->eventObjectArray;
|
||||
delete[] d->eventArray;
|
||||
delete d;
|
||||
}
|
||||
|
||||
EventRef EventHandler::addEvent() {
|
||||
EventRef event(new Event(this));
|
||||
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
|
||||
HANDLE *newArray = new HANDLE[d->eventCount+1];
|
||||
EventRef *newObjectArray = new EventRef[d->eventCount+1];
|
||||
for (int i = 0; i < d->eventCount; ++i) {
|
||||
newArray[i] = d->eventArray[i];
|
||||
newObjectArray[i] = d->eventObjectArray[i];
|
||||
}
|
||||
delete[] d->eventArray;
|
||||
delete[] d->eventObjectArray;
|
||||
d->eventArray = newArray;
|
||||
d->eventObjectArray = newObjectArray;
|
||||
d->eventArray[d->eventCount] = event->retrieveNative();
|
||||
d->eventObjectArray[d->eventCount] = event;
|
||||
++d->eventCount;
|
||||
return event;
|
||||
}
|
||||
|
||||
void EventHandler::signal(Event *event) {
|
||||
}
|
||||
|
||||
bool EventHandler::waitForAny() {
|
||||
while(1) {
|
||||
int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000);
|
||||
if (result == WAIT_TIMEOUT) {
|
||||
continue;
|
||||
}
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
int eventIndex = result - WAIT_OBJECT_0;
|
||||
if (eventIndex >= d->eventCount) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
36
telldus-core/common/Event_unix.cpp
Normal file
36
telldus-core/common/Event_unix.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include "common/Event.h"
|
||||
#include "common/EventHandler.h"
|
||||
#include "common/Thread.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class Event::PrivateData {
|
||||
public:
|
||||
};
|
||||
|
||||
Event::Event(EventHandler *handler)
|
||||
:EventBase(handler) {
|
||||
d = new PrivateData;
|
||||
}
|
||||
|
||||
Event::~Event(void) {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Event::clearSignal() {
|
||||
}
|
||||
|
||||
void Event::sendSignal() {
|
||||
EventHandler *handler = this->handler();
|
||||
if (handler) {
|
||||
handler->signal(this);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
40
telldus-core/common/Event_win.cpp
Normal file
40
telldus-core/common/Event_win.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include "common/Event.h"
|
||||
#include "common/Thread.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class Event::PrivateData {
|
||||
public:
|
||||
EVENT_T event;
|
||||
};
|
||||
|
||||
Event::Event(EventHandler *handler)
|
||||
:EventBase(handler) {
|
||||
d = new PrivateData;
|
||||
d->event = CreateEvent(NULL, true, false, NULL);
|
||||
}
|
||||
|
||||
Event::~Event(void) {
|
||||
CloseHandle(d->event);
|
||||
delete d;
|
||||
}
|
||||
|
||||
EVENT_T Event::retrieveNative() {
|
||||
return d->event;
|
||||
}
|
||||
|
||||
void Event::clearSignal() {
|
||||
ResetEvent(d->event);
|
||||
}
|
||||
|
||||
void Event::sendSignal() {
|
||||
SetEvent(d->event);
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
131
telldus-core/common/Message.cpp
Normal file
131
telldus-core/common/Message.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include "common/Message.h"
|
||||
#include <wctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sstream>
|
||||
#include "common/Socket.h"
|
||||
#include "common/Strings.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
Message::Message()
|
||||
: std::wstring() {
|
||||
}
|
||||
|
||||
Message::Message(const std::wstring &functionName)
|
||||
:std::wstring() {
|
||||
this->addArgument(functionName);
|
||||
}
|
||||
|
||||
Message::~Message(void) {
|
||||
}
|
||||
|
||||
void Message::addArgument(const std::wstring &value) {
|
||||
// std::wstringstream st;
|
||||
// st << (int)value.size();
|
||||
this->append(TelldusCore::intToWstring(value.size())); // st.str());
|
||||
this->append(L":");
|
||||
this->append(value);
|
||||
}
|
||||
|
||||
void Message::addArgument(int value) {
|
||||
// std::wstringstream st;
|
||||
// st << (int)value;
|
||||
this->append(L"i");
|
||||
this->append(TelldusCore::intToWstring(value)); // st.str());
|
||||
this->append(L"s");
|
||||
}
|
||||
|
||||
/*
|
||||
void Message::addSpecialArgument(const std::wstring &value){
|
||||
int i = 0;
|
||||
while(i<1000000){
|
||||
i++;
|
||||
|
||||
char numstr[21]; // enough to hold all numbers up to 64-bits
|
||||
//sprintf(numstr, "%d", value.size());
|
||||
//this->append(TelldusCore::charToWstring(numstr)); //.str());
|
||||
|
||||
itoa(value.size(), numstr, 10);
|
||||
std::string test(numstr);
|
||||
std::wstring temp(test.length(), L' ');
|
||||
std::copy(test.begin(), test.end(), temp.begin());
|
||||
|
||||
this->append(temp);
|
||||
this->append(L":");
|
||||
this->append(value);
|
||||
|
||||
|
||||
std::wstringstream st;
|
||||
st << (int)value.size();
|
||||
this->append(st.str());
|
||||
this->append(L":");
|
||||
this->append(value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Message::addSpecialArgument(int value){
|
||||
int i = 0;
|
||||
while(i<1000000){
|
||||
i++;
|
||||
//std::wstringstream st;
|
||||
//st << (int)value;
|
||||
this->append(L"i");
|
||||
//this->append(st.str());
|
||||
this->append(L"s");
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
void Message::addSpecialArgument(const char *value){
|
||||
this->addSpecialArgument(TelldusCore::charToWstring(value));
|
||||
}
|
||||
*/
|
||||
|
||||
void Message::addArgument(const char *value) {
|
||||
this->addArgument(TelldusCore::charToWstring(value));
|
||||
}
|
||||
|
||||
bool Message::nextIsInt(const std::wstring &message) {
|
||||
if (message.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
return (message.at(0) == 'i');
|
||||
}
|
||||
|
||||
bool Message::nextIsString(const std::wstring &message) {
|
||||
if (message.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
return (iswdigit(message.at(0)) != 0);
|
||||
}
|
||||
|
||||
std::wstring Message::takeString(std::wstring *message) {
|
||||
if (!Message::nextIsString(*message)) {
|
||||
return L"";
|
||||
}
|
||||
size_t index = message->find(':');
|
||||
int length = wideToInteger(message->substr(0, index));
|
||||
std::wstring retval(message->substr(index+1, length));
|
||||
message->erase(0, index+length+1);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Message::takeInt(std::wstring *message) {
|
||||
if (!Message::nextIsInt(*message)) {
|
||||
return 0;
|
||||
}
|
||||
size_t index = message->find('s');
|
||||
int value = wideToInteger(message->substr(1, index - 1));
|
||||
message->erase(0, index+1);
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
36
telldus-core/common/Message.h
Normal file
36
telldus-core/common/Message.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#ifndef TELLDUS_CORE_COMMON_MESSAGE_H_
|
||||
#define TELLDUS_CORE_COMMON_MESSAGE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace TelldusCore {
|
||||
class Message : public std::wstring {
|
||||
public:
|
||||
Message();
|
||||
explicit Message(const std::wstring &functionName);
|
||||
~Message(void);
|
||||
|
||||
void addArgument(const std::wstring &value);
|
||||
// void addSpecialArgument(const std::wstring &);
|
||||
// void addSpecialArgument(int);
|
||||
// void addSpecialArgument(const char *);
|
||||
void addArgument(int value);
|
||||
void addArgument(const char *value);
|
||||
|
||||
static bool nextIsInt(const std::wstring &message);
|
||||
static bool nextIsString(const std::wstring &message);
|
||||
|
||||
static std::wstring takeString(std::wstring *message);
|
||||
static int takeInt(std::wstring *message);
|
||||
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_MESSAGE_H_
|
||||
88
telldus-core/common/Mutex.cpp
Normal file
88
telldus-core/common/Mutex.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// C++ Implementation: Thread
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
//
|
||||
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
|
||||
#include "common/Mutex.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
typedef HANDLE MUTEX_T;
|
||||
#else
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutex_t MUTEX_T;
|
||||
#endif
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class Mutex::PrivateData {
|
||||
public:
|
||||
MUTEX_T mutex;
|
||||
};
|
||||
|
||||
Mutex::Mutex() {
|
||||
d = new PrivateData;
|
||||
#ifdef _WINDOWS
|
||||
d->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
#else
|
||||
pthread_mutex_init(&d->mutex, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
Mutex::~Mutex() {
|
||||
#ifdef _WINDOWS
|
||||
CloseHandle(d->mutex);
|
||||
#else
|
||||
pthread_mutex_destroy(&d->mutex);
|
||||
#endif
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Mutex::lock() {
|
||||
#ifdef _WINDOWS
|
||||
WaitForSingleObject(d->mutex, INFINITE);
|
||||
#else
|
||||
pthread_mutex_lock(&d->mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mutex::unlock() {
|
||||
#ifdef _WINDOWS
|
||||
ReleaseMutex(d->mutex);
|
||||
#else
|
||||
pthread_mutex_unlock(&d->mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void LoggedMutex::lock() {
|
||||
debuglog(0, "Locking");
|
||||
Mutex::lock();
|
||||
debuglog(0, "Locked");
|
||||
}
|
||||
|
||||
void LoggedMutex::unlock() {
|
||||
debuglog(0, "Unlocking");
|
||||
Mutex::unlock();
|
||||
debuglog(0, "Unlocked");
|
||||
}
|
||||
|
||||
MutexLocker::MutexLocker(Mutex *m)
|
||||
:mutex(m) {
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
MutexLocker::~MutexLocker() {
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
45
telldus-core/common/Mutex.h
Normal file
45
telldus-core/common/Mutex.h
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// C++ Interface: Thread
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
//
|
||||
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2010
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#ifndef TELLDUS_CORE_COMMON_MUTEX_H_
|
||||
#define TELLDUS_CORE_COMMON_MUTEX_H_
|
||||
|
||||
namespace TelldusCore {
|
||||
class Mutex {
|
||||
public:
|
||||
Mutex();
|
||||
virtual ~Mutex();
|
||||
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
|
||||
private:
|
||||
Mutex(const Mutex&); // Disable copy
|
||||
Mutex& operator = (const Mutex&);
|
||||
class PrivateData;
|
||||
PrivateData *d;
|
||||
};
|
||||
class LoggedMutex : public Mutex {
|
||||
public:
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
class MutexLocker {
|
||||
public:
|
||||
explicit MutexLocker(Mutex *m);
|
||||
~MutexLocker();
|
||||
private:
|
||||
Mutex *mutex;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_MUTEX_H_
|
||||
39
telldus-core/common/Socket.h
Normal file
39
telldus-core/common/Socket.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#ifndef TELLDUS_CORE_COMMON_SOCKET_H_
|
||||
#define TELLDUS_CORE_COMMON_SOCKET_H_
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
typedef HANDLE SOCKET_T;
|
||||
#else
|
||||
typedef int SOCKET_T;
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace TelldusCore {
|
||||
class Socket {
|
||||
public:
|
||||
Socket();
|
||||
explicit Socket(SOCKET_T hPipe);
|
||||
virtual ~Socket(void);
|
||||
|
||||
void connect(const std::wstring &server);
|
||||
bool isConnected();
|
||||
std::wstring read();
|
||||
std::wstring read(int timeout);
|
||||
void stopReadWait();
|
||||
void write(const std::wstring &msg);
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_SOCKET_H_
|
||||
144
telldus-core/common/Socket_unix.cpp
Normal file
144
telldus-core/common/Socket_unix.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
|
||||
#include "common/Socket.h"
|
||||
#include "common/Mutex.h"
|
||||
#include "common/Strings.h"
|
||||
|
||||
#define BUFSIZE 512
|
||||
#if defined(_MACOSX) && !defined(SOCK_CLOEXEC)
|
||||
#define SOCK_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
return connect(sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
class Socket::PrivateData {
|
||||
public:
|
||||
SOCKET_T socket;
|
||||
bool connected;
|
||||
fd_set infds;
|
||||
Mutex mutex;
|
||||
};
|
||||
|
||||
Socket::Socket() {
|
||||
d = new PrivateData;
|
||||
d->socket = 0;
|
||||
d->connected = false;
|
||||
FD_ZERO(&d->infds);
|
||||
}
|
||||
|
||||
Socket::Socket(SOCKET_T socket) {
|
||||
d = new PrivateData;
|
||||
d->socket = socket;
|
||||
FD_ZERO(&d->infds);
|
||||
d->connected = true;
|
||||
}
|
||||
|
||||
Socket::~Socket(void) {
|
||||
if(d->socket) {
|
||||
close(d->socket);
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Socket::connect(const std::wstring &server) {
|
||||
struct sockaddr_un remote;
|
||||
socklen_t len;
|
||||
|
||||
if ((d->socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) {
|
||||
return;
|
||||
}
|
||||
#if defined(_MACOSX)
|
||||
int op = fcntl(d->socket, F_GETFD);
|
||||
fcntl(d->socket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet
|
||||
#endif
|
||||
std::string name = "/tmp/" + std::string(server.begin(), server.end());
|
||||
remote.sun_family = AF_UNIX;
|
||||
snprintf(remote.sun_path, sizeof(remote.sun_path), "%s", name.c_str());
|
||||
|
||||
len = SUN_LEN(&remote);
|
||||
if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
d->connected = true;
|
||||
}
|
||||
|
||||
bool Socket::isConnected() {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
return d->connected;
|
||||
}
|
||||
|
||||
std::wstring Socket::read() {
|
||||
return this->read(0);
|
||||
}
|
||||
|
||||
std::wstring Socket::read(int timeout) {
|
||||
struct timeval tv;
|
||||
char inbuf[BUFSIZE];
|
||||
|
||||
FD_SET(d->socket, &d->infds);
|
||||
std::string msg;
|
||||
while(isConnected()) {
|
||||
tv.tv_sec = floor(timeout / 1000.0);
|
||||
tv.tv_usec = timeout % 1000;
|
||||
|
||||
int response = select(d->socket+1, &d->infds, NULL, NULL, &tv);
|
||||
if (response == 0 && timeout > 0) {
|
||||
return L"";
|
||||
} else if (response <= 0) {
|
||||
FD_SET(d->socket, &d->infds);
|
||||
continue;
|
||||
}
|
||||
|
||||
int received = BUFSIZE;
|
||||
while(received >= (BUFSIZE - 1)) {
|
||||
memset(inbuf, '\0', sizeof(inbuf));
|
||||
received = recv(d->socket, inbuf, BUFSIZE - 1, 0);
|
||||
if(received > 0) {
|
||||
msg.append(std::string(inbuf));
|
||||
}
|
||||
}
|
||||
if (received < 0) {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
d->connected = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return TelldusCore::charToWstring(msg.c_str());
|
||||
}
|
||||
|
||||
void Socket::stopReadWait() {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
d->connected = false;
|
||||
// TODO(stefan): somehow signal the socket here?
|
||||
}
|
||||
|
||||
void Socket::write(const std::wstring &msg) {
|
||||
std::string newMsg(TelldusCore::wideToString(msg));
|
||||
int sent = send(d->socket, newMsg.c_str(), newMsg.length(), 0);
|
||||
if (sent < 0) {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
d->connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
187
telldus-core/common/Socket_win.cpp
Normal file
187
telldus-core/common/Socket_win.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include <AccCtrl.h>
|
||||
#include <Aclapi.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "common/common.h"
|
||||
#include "common/Socket.h"
|
||||
|
||||
#define BUFSIZE 512
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class Socket::PrivateData {
|
||||
public:
|
||||
HANDLE hPipe;
|
||||
HANDLE readEvent;
|
||||
bool connected;
|
||||
bool running;
|
||||
};
|
||||
|
||||
Socket::Socket() {
|
||||
d = new PrivateData;
|
||||
d->hPipe = INVALID_HANDLE_VALUE;
|
||||
d->connected = false;
|
||||
d->running = true;
|
||||
}
|
||||
|
||||
Socket::Socket(SOCKET_T hPipe) {
|
||||
d = new PrivateData;
|
||||
d->hPipe = hPipe;
|
||||
d->connected = true;
|
||||
d->running = true;
|
||||
}
|
||||
|
||||
|
||||
Socket::~Socket(void) {
|
||||
d->running = false;
|
||||
SetEvent(d->readEvent); // signal for break
|
||||
if (d->hPipe != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(d->hPipe);
|
||||
d->hPipe = 0;
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Socket::connect(const std::wstring &server) {
|
||||
BOOL fSuccess = false;
|
||||
|
||||
std::wstring name(L"\\\\.\\pipe\\" + server);
|
||||
d->hPipe = CreateFile(
|
||||
(const wchar_t *)name.c_str(), // pipe name
|
||||
GENERIC_READ | // read and write access
|
||||
GENERIC_WRITE,
|
||||
0, // no sharing
|
||||
NULL, // default security attributes
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
FILE_FLAG_OVERLAPPED, // default attributes
|
||||
NULL); // no template file
|
||||
|
||||
if (d->hPipe == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD dwMode = PIPE_READMODE_MESSAGE;
|
||||
fSuccess = SetNamedPipeHandleState(
|
||||
d->hPipe, // pipe handle
|
||||
&dwMode, // new pipe mode
|
||||
NULL, // don't set maximum bytes
|
||||
NULL); // don't set maximum time
|
||||
|
||||
if (!fSuccess) {
|
||||
return;
|
||||
}
|
||||
d->connected = true;
|
||||
}
|
||||
|
||||
void Socket::stopReadWait() {
|
||||
d->running = false;
|
||||
SetEvent(d->readEvent);
|
||||
}
|
||||
|
||||
std::wstring Socket::read() {
|
||||
return read(INFINITE);
|
||||
}
|
||||
|
||||
std::wstring Socket::read(int timeout) {
|
||||
wchar_t buf[BUFSIZE];
|
||||
int result;
|
||||
DWORD cbBytesRead = 0;
|
||||
OVERLAPPED oOverlap;
|
||||
|
||||
memset(&oOverlap, 0, sizeof(OVERLAPPED));
|
||||
|
||||
d->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
oOverlap.hEvent = d->readEvent;
|
||||
BOOL fSuccess = false;
|
||||
std::wstring returnString;
|
||||
bool moreData = true;
|
||||
|
||||
while(moreData) {
|
||||
moreData = false;
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
|
||||
ReadFile( d->hPipe, &buf, sizeof(buf)-sizeof(wchar_t), &cbBytesRead, &oOverlap);
|
||||
|
||||
result = WaitForSingleObject(oOverlap.hEvent, timeout);
|
||||
|
||||
if(!d->running) {
|
||||
CancelIo(d->hPipe);
|
||||
WaitForSingleObject(oOverlap.hEvent, INFINITE);
|
||||
d->readEvent = 0;
|
||||
CloseHandle(oOverlap.hEvent);
|
||||
return L"";
|
||||
}
|
||||
|
||||
if (result == WAIT_TIMEOUT) {
|
||||
CancelIo(d->hPipe);
|
||||
// Cancel, we still need to cleanup
|
||||
}
|
||||
fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, true);
|
||||
|
||||
if (!fSuccess) {
|
||||
DWORD err = GetLastError();
|
||||
|
||||
if(err == ERROR_MORE_DATA) {
|
||||
moreData = true;
|
||||
} else {
|
||||
buf[0] = 0;
|
||||
}
|
||||
if (err == ERROR_BROKEN_PIPE) {
|
||||
d->connected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
returnString.append(buf);
|
||||
}
|
||||
d->readEvent = 0;
|
||||
CloseHandle(oOverlap.hEvent);
|
||||
return returnString;
|
||||
}
|
||||
|
||||
void Socket::write(const std::wstring &msg) {
|
||||
OVERLAPPED oOverlap;
|
||||
DWORD bytesWritten = 0;
|
||||
int result;
|
||||
BOOL fSuccess = false;
|
||||
|
||||
memset(&oOverlap, 0, sizeof(OVERLAPPED));
|
||||
|
||||
HANDLE writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
oOverlap.hEvent = writeEvent;
|
||||
|
||||
BOOL writeSuccess = WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap);
|
||||
result = GetLastError();
|
||||
if (writeSuccess || result == ERROR_IO_PENDING) {
|
||||
result = WaitForSingleObject(writeEvent, 30000);
|
||||
if (result == WAIT_TIMEOUT) {
|
||||
CancelIo(d->hPipe);
|
||||
WaitForSingleObject(oOverlap.hEvent, INFINITE);
|
||||
CloseHandle(writeEvent);
|
||||
CloseHandle(d->hPipe);
|
||||
d->hPipe = 0;
|
||||
d->connected = false;
|
||||
return;
|
||||
}
|
||||
fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE);
|
||||
}
|
||||
|
||||
CloseHandle(writeEvent);
|
||||
if (!fSuccess) {
|
||||
CloseHandle(d->hPipe);
|
||||
d->hPipe = 0;
|
||||
d->connected = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool Socket::isConnected() {
|
||||
return d->connected;
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
276
telldus-core/common/Strings.cpp
Normal file
276
telldus-core/common/Strings.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
|
||||
#include "common/Strings.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
#ifdef _MACOSX
|
||||
#define WCHAR_T_ENCODING "UCS-4-INTERNAL"
|
||||
#else
|
||||
#define WCHAR_T_ENCODING "WCHAR_T"
|
||||
#endif
|
||||
|
||||
#ifndef va_copy
|
||||
#ifdef __va_copy
|
||||
#define va_copy(a, b) __va_copy(a, b)
|
||||
#else /* !__va_copy */
|
||||
#define va_copy(a, b) ((a)=(b))
|
||||
#endif /* __va_copy */
|
||||
#endif /* va_copy */
|
||||
|
||||
std::wstring TelldusCore::charToWstring(const char *value) {
|
||||
#ifdef _WINDOWS
|
||||
// Determine size
|
||||
int size = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
|
||||
if (size == 0) {
|
||||
return L"";
|
||||
}
|
||||
wchar_t *buffer;
|
||||
buffer = new wchar_t[size];
|
||||
memset(buffer, 0, sizeof(wchar_t)*(size));
|
||||
|
||||
int bytes = MultiByteToWideChar(CP_UTF8, 0, value, -1, buffer, size);
|
||||
std::wstring retval(buffer);
|
||||
delete[] buffer;
|
||||
return retval;
|
||||
|
||||
#else
|
||||
size_t utf8Length = strlen(value);
|
||||
size_t outbytesLeft = utf8Length*sizeof(wchar_t);
|
||||
|
||||
// Copy the instring
|
||||
char *inString = new char[utf8Length+1];
|
||||
snprintf(inString, utf8Length+1, "%s", value);
|
||||
|
||||
// Create buffer for output
|
||||
char *outString = reinterpret_cast<char*>(new wchar_t[utf8Length+1]);
|
||||
memset(outString, 0, sizeof(wchar_t)*(utf8Length+1));
|
||||
|
||||
#ifdef _FREEBSD
|
||||
const char *inPointer = inString;
|
||||
#else
|
||||
char *inPointer = inString;
|
||||
#endif
|
||||
char *outPointer = outString;
|
||||
|
||||
iconv_t convDesc = iconv_open(WCHAR_T_ENCODING, "UTF-8");
|
||||
iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft);
|
||||
iconv_close(convDesc);
|
||||
|
||||
std::wstring retval( reinterpret_cast<wchar_t *>(outString) );
|
||||
|
||||
// Cleanup
|
||||
delete[] inString;
|
||||
delete[] outString;
|
||||
|
||||
return retval;
|
||||
#endif
|
||||
}
|
||||
|
||||
int TelldusCore::charToInteger(const char *input) {
|
||||
std::stringstream inputstream;
|
||||
inputstream << input;
|
||||
int retval;
|
||||
inputstream >> retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::wstring TelldusCore::charUnsignedToWstring(const unsigned char value) {
|
||||
std::wstringstream st;
|
||||
st << value;
|
||||
return st.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method doesn't support all locales
|
||||
*/
|
||||
bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) {
|
||||
transform(stringA.begin(), stringA.end(), stringA.begin(), toupper);
|
||||
transform(stringB.begin(), stringB.end(), stringB.begin(), toupper);
|
||||
|
||||
return stringA == stringB;
|
||||
}
|
||||
|
||||
std::wstring TelldusCore::intToWstring(int value) {
|
||||
#ifdef _WINDOWS
|
||||
// no stream used
|
||||
// TODO(stefan): Make effective and safe...
|
||||
wchar_t numstr[21]; // enough to hold all numbers up to 64-bits
|
||||
_itow_s(value, numstr, sizeof(numstr), 10);
|
||||
std::wstring newstring(numstr);
|
||||
return newstring;
|
||||
// return TelldusCore::charToWstring(stdstring.c_str());
|
||||
// std::wstring temp = TelldusCore::charToWstring(stdstring.c_str());
|
||||
// std::wstring temp(stdstring.length(), L' ');
|
||||
// std::copy(stdstring.begin(), stdstring.end(), temp.begin());
|
||||
// return temp;
|
||||
#else
|
||||
std::wstringstream st;
|
||||
st << value;
|
||||
return st.str();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string TelldusCore::intToString(int value) {
|
||||
// Not sure if this is neecssary (for ordinary stringstream that is)
|
||||
#ifdef _WINDOWS
|
||||
char numstr[21]; // enough to hold all numbers up to 64-bits
|
||||
_itoa_s(value, numstr, sizeof(numstr), 10);
|
||||
std::string stdstring(numstr);
|
||||
return stdstring;
|
||||
#else
|
||||
std::stringstream st;
|
||||
st << value;
|
||||
return st.str();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
std::wstring TelldusCore::intToWStringSafe(int value){
|
||||
#ifdef _WINDOWS
|
||||
//no stream used
|
||||
//TODO! Make effective and safe...
|
||||
char numstr[21]; // enough to hold all numbers up to 64-bits
|
||||
itoa(value, numstr, 10);
|
||||
std::string stdstring(numstr);
|
||||
return TelldusCore::charToWstring(stdstring.c_str());
|
||||
//std::wstring temp = TelldusCore::charToWstring(stdstring.c_str());
|
||||
//std::wstring temp(stdstring.length(), L' ');
|
||||
//std::copy(stdstring.begin(), stdstring.end(), temp.begin());
|
||||
//return temp;
|
||||
#else
|
||||
return TelldusCore::intToWString(value);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
uint64_t TelldusCore::hexTo64l(const std::string data) {
|
||||
#ifdef _WINDOWS
|
||||
return _strtoui64(data.c_str(), NULL, 16);
|
||||
#elif defined(_MACOSX)
|
||||
return strtoq(data.c_str(), NULL, 16);
|
||||
#else
|
||||
return strtoull(data.c_str(), NULL, 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
int TelldusCore::wideToInteger(const std::wstring &input) {
|
||||
std::wstringstream inputstream;
|
||||
inputstream << input;
|
||||
int retval;
|
||||
inputstream >> retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string TelldusCore::wideToString(const std::wstring &input) {
|
||||
#ifdef _WINDOWS
|
||||
// Determine size
|
||||
int size = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, NULL, 0, NULL, NULL);
|
||||
if (size == 0) {
|
||||
return "";
|
||||
}
|
||||
char *buffer;
|
||||
buffer = new char[size];
|
||||
memset(buffer, 0, sizeof(*buffer)*size);
|
||||
|
||||
int bytes = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, buffer, size, NULL, NULL);
|
||||
std::string retval(buffer);
|
||||
delete[] buffer;
|
||||
return retval;
|
||||
|
||||
#else
|
||||
size_t wideSize = sizeof(wchar_t)*input.length();
|
||||
// We cannot know how many wide character there is yet
|
||||
size_t outbytesLeft = wideSize+sizeof(char); // NOLINT(runtime/sizeof)
|
||||
|
||||
// Copy the instring
|
||||
char *inString = reinterpret_cast<char*>(new wchar_t[input.length()+1]);
|
||||
memcpy(inString, input.c_str(), wideSize+sizeof(wchar_t));
|
||||
|
||||
// Create buffer for output
|
||||
char *outString = new char[outbytesLeft];
|
||||
memset(outString, 0, sizeof(*outString)*(outbytesLeft));
|
||||
|
||||
#ifdef _FREEBSD
|
||||
const char *inPointer = inString;
|
||||
#else
|
||||
char *inPointer = inString;
|
||||
#endif
|
||||
char *outPointer = outString;
|
||||
|
||||
iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING);
|
||||
iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft);
|
||||
iconv_close(convDesc);
|
||||
|
||||
std::string retval(outString);
|
||||
|
||||
// Cleanup
|
||||
delete[] inString;
|
||||
delete[] outString;
|
||||
|
||||
return retval;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string TelldusCore::formatf(const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
std::string retval = sformatf(format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string TelldusCore::sformatf(const char *format, va_list ap) {
|
||||
// This code is based on code from the Linux man-pages project (man vsprintf)
|
||||
int n;
|
||||
int size = 100; /* Guess we need no more than 100 bytes. */
|
||||
char *p, *np;
|
||||
|
||||
if ((p = reinterpret_cast<char*>(malloc(size))) == NULL) {
|
||||
return "";
|
||||
}
|
||||
|
||||
while (1) {
|
||||
/* Try to print in the allocated space. */
|
||||
va_list ap2;
|
||||
va_copy(ap2, ap);
|
||||
n = vsnprintf(p, size, format, ap2);
|
||||
va_end(ap2);
|
||||
|
||||
/* If that worked, return the string. */
|
||||
if (n > -1 && n < size) {
|
||||
std::string retval(p);
|
||||
free(p);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Else try again with more space. */
|
||||
|
||||
if (n > -1) { /* glibc 2.1 */
|
||||
size = n+1; /* precisely what is needed */
|
||||
} else { /* glibc 2.0 */
|
||||
size *= 2; /* twice the old size */
|
||||
}
|
||||
if ((np = reinterpret_cast<char *>(realloc (p, size))) == NULL) {
|
||||
free(p);
|
||||
return "";
|
||||
} else {
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
telldus-core/common/Strings.h
Normal file
39
telldus-core/common/Strings.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#ifndef TELLDUS_CORE_COMMON_STRINGS_H_
|
||||
#define TELLDUS_CORE_COMMON_STRINGS_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <string>
|
||||
|
||||
namespace TelldusCore {
|
||||
std::wstring charToWstring(const char *value);
|
||||
int charToInteger(const char *value);
|
||||
std::wstring charUnsignedToWstring(const unsigned char value);
|
||||
|
||||
bool comparei(std::wstring stringA, std::wstring stringB);
|
||||
std::wstring intToWstring(int value);
|
||||
// std::wstring intToWStringSafe(int value);
|
||||
std::string intToString(int value);
|
||||
uint64_t hexTo64l(const std::string data);
|
||||
std::string wideToString(const std::wstring &input);
|
||||
|
||||
int wideToInteger(const std::wstring &input);
|
||||
|
||||
std::string formatf(const char *format, ...);
|
||||
std::string sformatf(const char *format, va_list ap);
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_STRINGS_H_
|
||||
98
telldus-core/common/Thread.cpp
Normal file
98
telldus-core/common/Thread.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// C++ Implementation: Thread
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
//
|
||||
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
|
||||
#include "common/Thread.h"
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "common/EventHandler.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
|
||||
class ThreadPrivate {
|
||||
public:
|
||||
bool running;
|
||||
EventRef threadStarted;
|
||||
Mutex *mutex;
|
||||
#ifdef _WINDOWS
|
||||
HANDLE thread;
|
||||
DWORD threadId;
|
||||
#else
|
||||
pthread_t thread;
|
||||
#endif
|
||||
};
|
||||
|
||||
Thread::Thread() {
|
||||
d = new ThreadPrivate;
|
||||
d->thread = 0;
|
||||
d->mutex = 0;
|
||||
}
|
||||
|
||||
Thread::~Thread() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Thread::start() {
|
||||
#ifdef _WINDOWS
|
||||
d->running = true;
|
||||
d->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Thread::exec, this, 0, &d->threadId);
|
||||
#else
|
||||
pthread_create(&d->thread, NULL, &Thread::exec, this );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Thread::startAndLock(Mutex *lock) {
|
||||
EventHandler handler;
|
||||
d->threadStarted = handler.addEvent();
|
||||
d->mutex = lock;
|
||||
this->start();
|
||||
while (!handler.waitForAny()) {
|
||||
continue;
|
||||
}
|
||||
d->threadStarted.reset();
|
||||
}
|
||||
|
||||
bool Thread::wait() {
|
||||
if (!d->thread) {
|
||||
return true;
|
||||
}
|
||||
#ifdef _WINDOWS
|
||||
while(d->running) {
|
||||
WaitForSingleObject(d->thread, 200);
|
||||
}
|
||||
CloseHandle(d->thread);
|
||||
#else
|
||||
pthread_join(d->thread, 0);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void *Thread::exec( void *ptr ) {
|
||||
Thread *t = reinterpret_cast<Thread *>(ptr);
|
||||
if (t) {
|
||||
if (t->d->threadStarted) {
|
||||
t->d->mutex->lock();
|
||||
t->d->threadStarted->signal();
|
||||
}
|
||||
t->run();
|
||||
if (t->d->mutex) {
|
||||
t->d->mutex->unlock();
|
||||
}
|
||||
t->d->running = false;
|
||||
}
|
||||
#ifdef _WINDOWS
|
||||
ExitThread(0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace TelldusCore
|
||||
37
telldus-core/common/Thread.h
Normal file
37
telldus-core/common/Thread.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// C++ Interface: Thread
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
//
|
||||
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#ifndef TELLDUS_CORE_COMMON_THREAD_H_
|
||||
#define TELLDUS_CORE_COMMON_THREAD_H_
|
||||
|
||||
#include <string>
|
||||
#include "common/Mutex.h"
|
||||
|
||||
namespace TelldusCore {
|
||||
class ThreadPrivate;
|
||||
class Thread {
|
||||
public:
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
void start();
|
||||
void startAndLock(Mutex *lock);
|
||||
bool wait();
|
||||
|
||||
protected:
|
||||
virtual void run() = 0;
|
||||
|
||||
private:
|
||||
static void* exec( void *ptr );
|
||||
ThreadPrivate *d;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_THREAD_H_
|
||||
108
telldus-core/common/common.h
Normal file
108
telldus-core/common/common.h
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef TELLDUS_CORE_COMMON_COMMON_H_
|
||||
#define TELLDUS_CORE_COMMON_COMMON_H_
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define strcasecmp _stricmp
|
||||
#define strncasecmp _strnicmp
|
||||
#include <ole2.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <fstream> // NOLINT(readability/streams)
|
||||
#endif
|
||||
#include <string>
|
||||
#include "common/Strings.h"
|
||||
|
||||
inline void msleep( const int msec) {
|
||||
#ifdef _WINDOWS
|
||||
Sleep(msec);
|
||||
#else
|
||||
usleep(msec*1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void dlog(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
inline void debuglogfilename(const int intMessage, const std::string strMessage, const std::string filename) {
|
||||
#ifdef _WINDOWS
|
||||
static bool firstRun = true;
|
||||
std::ofstream file;
|
||||
|
||||
if (firstRun) {
|
||||
file.open(filename.c_str(), std::ios::out);
|
||||
firstRun = false;
|
||||
} else {
|
||||
file.open(filename.c_str(), std::ios::out | std::ios::app);
|
||||
}
|
||||
|
||||
__time32_t now = _time32(0);
|
||||
|
||||
// Convert now to tm struct for local timezone
|
||||
struct tm localtm;
|
||||
_localtime32_s(&localtm, &now);
|
||||
char thetime[32];
|
||||
errno_t err = asctime_s(thetime, 32, &localtm);
|
||||
if (!err) {
|
||||
file << thetime << " [" << GetCurrentThreadId() << "] " << intMessage << " - " << strMessage << "\n";
|
||||
file.flush();
|
||||
file.close();
|
||||
}
|
||||
|
||||
#elif !defined(_MACOSX) && !defined(__FreeBSD__)
|
||||
pthread_t thread = pthread_self();
|
||||
printf("[%i] %i - %s\n", static_cast<int>(thread), intMessage, strMessage.c_str());
|
||||
fflush(stdout);
|
||||
#else
|
||||
printf("%i - %s\n", intMessage, strMessage.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void debuglogservice(const int intMessage, const std::string strMessage) {
|
||||
std::string filename("C:/telldus_service_debug.txt");
|
||||
debuglogfilename(intMessage, strMessage, filename);
|
||||
}
|
||||
|
||||
inline void debuglog(const int intMessage, const std::string strMessage) {
|
||||
std::string filename("C:/telldus_client_debug.txt");
|
||||
debuglogfilename(intMessage, strMessage, filename);
|
||||
}
|
||||
|
||||
inline char *wrapStdString( const std::string &string) {
|
||||
#ifdef _WINDOWS
|
||||
return reinterpret_cast<char *>(SysAllocStringByteLen(string.c_str(), (unsigned int)string.size()));
|
||||
#else
|
||||
char *returnVal;
|
||||
returnVal = reinterpret_cast<char *>(malloc(sizeof(*returnVal) * (string.size()+1)));
|
||||
snprintf(returnVal, string.size()+1, "%s", string.c_str());
|
||||
return returnVal;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline char *wrapStdWstring( const std::wstring &wstring) {
|
||||
return wrapStdString(TelldusCore::wideToString(wstring));
|
||||
}
|
||||
|
||||
#endif // TELLDUS_CORE_COMMON_COMMON_H_
|
||||
73
telldus-core/common/stdlibc_workaround.cpp
Normal file
73
telldus-core/common/stdlibc_workaround.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include <istream> // NOLINT(readability/streams)
|
||||
// Workarounds for symbols that are missing from Leopard stdlibc++.dylib.
|
||||
_GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
// From ostream_insert.h
|
||||
template ostream& __ostream_insert(ostream&, const char*, streamsize);
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template wostream& __ostream_insert(wostream&, const wchar_t*, streamsize);
|
||||
#endif
|
||||
|
||||
// From ostream.tcc
|
||||
template ostream& ostream::_M_insert(long); // NOLINT(runtime/int)
|
||||
template ostream& ostream::_M_insert(unsigned long); // NOLINT(runtime/int)
|
||||
template ostream& ostream::_M_insert(bool); // NOLINT(readability/function)
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template ostream& ostream::_M_insert(long long); // NOLINT(runtime/int)
|
||||
template ostream& ostream::_M_insert(unsigned long long); // NOLINT(runtime/int)
|
||||
#endif
|
||||
template ostream& ostream::_M_insert(double); // NOLINT(readability/function)
|
||||
template ostream& ostream::_M_insert(long double);
|
||||
template ostream& ostream::_M_insert(const void*);
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template wostream& wostream::_M_insert(long); // NOLINT(runtime/int)
|
||||
template wostream& wostream::_M_insert(unsigned long); // NOLINT(runtime/int)
|
||||
template wostream& wostream::_M_insert(bool); // NOLINT(readability/function)
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template wostream& wostream::_M_insert(long long); // NOLINT(runtime/int)
|
||||
template wostream& wostream::_M_insert(unsigned long long); // NOLINT(runtime/int)
|
||||
#endif
|
||||
template wostream& wostream::_M_insert(double); // NOLINT(readability/function)
|
||||
template wostream& wostream::_M_insert(long double);
|
||||
template wostream& wostream::_M_insert(const void*);
|
||||
#endif
|
||||
|
||||
// From istream.tcc
|
||||
template istream& istream::_M_extract(unsigned short&); // NOLINT(runtime/int)
|
||||
template istream& istream::_M_extract(unsigned int&);
|
||||
template istream& istream::_M_extract(long&); // NOLINT(runtime/int)
|
||||
template istream& istream::_M_extract(unsigned long&); // NOLINT(runtime/int)
|
||||
template istream& istream::_M_extract(bool&);
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template istream& istream::_M_extract(long long&); // NOLINT(runtime/int)
|
||||
template istream& istream::_M_extract(unsigned long long&); // NOLINT(runtime/int)
|
||||
#endif
|
||||
template istream& istream::_M_extract(float&);
|
||||
template istream& istream::_M_extract(double&);
|
||||
template istream& istream::_M_extract(long double&);
|
||||
template istream& istream::_M_extract(void*&);
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template wistream& wistream::_M_extract(unsigned short&); // NOLINT(runtime/int)
|
||||
template wistream& wistream::_M_extract(unsigned int&);
|
||||
template wistream& wistream::_M_extract(long&); // NOLINT(runtime/int)
|
||||
template wistream& wistream::_M_extract(unsigned long&); // NOLINT(runtime/int)
|
||||
template wistream& wistream::_M_extract(bool&);
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
template wistream& wistream::_M_extract(long long&); // NOLINT(runtime/int)
|
||||
template wistream& wistream::_M_extract(unsigned long long&); // NOLINT(runtime/int)
|
||||
#endif
|
||||
template wistream& wistream::_M_extract(float&);
|
||||
template wistream& wistream::_M_extract(double&);
|
||||
template wistream& wistream::_M_extract(long double&);
|
||||
template wistream& wistream::_M_extract(void*&);
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE
|
||||
Reference in New Issue
Block a user