summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJesse Gilles <jgilles@multitech.com>2015-04-20 16:49:52 -0500
committerJesse Gilles <jgilles@multitech.com>2015-04-20 16:49:52 -0500
commit17b117e73df71925d73ee026b4f54aa1867ce0a5 (patch)
tree382610c8e598a77a961c5ceb32b9b614ed00e757 /src
downloadlibmts-17b117e73df71925d73ee026b4f54aa1867ce0a5.tar.gz
libmts-17b117e73df71925d73ee026b4f54aa1867ce0a5.tar.bz2
libmts-17b117e73df71925d73ee026b4f54aa1867ce0a5.zip
initial commit
Diffstat (limited to 'src')
-rw-r--r--src/MTS_Buffer.cpp159
-rw-r--r--src/MTS_Condition.cpp115
-rw-r--r--src/MTS_Lock.cpp114
-rw-r--r--src/MTS_Logger.cpp312
-rw-r--r--src/MTS_Object.cpp41
-rw-r--r--src/MTS_SignalThread.cpp103
-rw-r--r--src/MTS_System.cpp156
-rw-r--r--src/MTS_Text.cpp701
-rw-r--r--src/MTS_Thread.cpp227
-rw-r--r--src/MTS_Timer.cpp103
-rw-r--r--src/MTS_TimerThread.cpp116
11 files changed, 2147 insertions, 0 deletions
diff --git a/src/MTS_Buffer.cpp b/src/MTS_Buffer.cpp
new file mode 100644
index 0000000..91ece42
--- /dev/null
+++ b/src/MTS_Buffer.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_Buffer.h>
+#include <stdexcept>
+#include <string>
+
+using namespace MTS;
+
+const uint32_t Buffer::DEFAULT_CAPACITY = 80;
+
+Buffer::Buffer(uint32_t capacity) {
+ setCapacity(capacity);
+}
+
+Buffer::Buffer(const uint8_t* bytes, uint32_t count)
+: m_vBuffer(bytes, bytes + count) {
+
+}
+
+Buffer::Buffer(const Buffer& other)
+: m_vBuffer(other.m_vBuffer.begin(), other.m_vBuffer.end()) {
+
+}
+
+Buffer::~Buffer() {
+
+}
+
+Buffer&
+Buffer::operator=(const Buffer& other) {
+ if (&other == this) {
+ return *this;
+ }
+ m_vBuffer = other.m_vBuffer;
+ return *this;
+}
+
+const uint8_t*
+Buffer::getBuffer() const {
+ return &m_vBuffer.at(0);
+}
+
+std::string Buffer::str() const {
+ return std::string(reinterpret_cast<const char*>(&m_vBuffer.at(0)), m_vBuffer.size());
+}
+
+uint32_t Buffer::getSize() const {
+ return m_vBuffer.size();
+}
+
+void Buffer::setSize(uint32_t newSize) {
+ m_vBuffer.resize(newSize);
+}
+
+uint32_t Buffer::getCapacity() const {
+ return m_vBuffer.capacity();
+}
+
+void Buffer::setCapacity(uint32_t newCapacity) {
+ m_vBuffer.reserve(newCapacity);
+}
+
+void Buffer::clear() {
+ m_vBuffer.clear();
+}
+
+void Buffer::compact() {
+ m_vBuffer.resize(m_vBuffer.size());
+}
+
+uint8_t Buffer::operator[](uint32_t index) const {
+ return m_vBuffer[index];
+}
+
+uint8_t Buffer::operator[](uint32_t index) {
+ return m_vBuffer[index];
+}
+
+const uint8_t&
+Buffer::at(uint32_t index) const {
+ return m_vBuffer.at(index);
+}
+
+uint8_t&
+Buffer::at(uint32_t index) {
+ return m_vBuffer.at(index);
+}
+
+Buffer&
+Buffer::append(uint8_t byte) {
+ m_vBuffer.push_back(byte);
+ return *this;
+}
+
+Buffer& Buffer::append(const uint8_t* bytes, uint32_t count) {
+ m_vBuffer.resize(m_vBuffer.size() + count);
+ std::copy(bytes, bytes + count, std::back_inserter(m_vBuffer));
+ return *this;
+}
+
+Buffer&
+Buffer::insert(uint32_t index, uint8_t byte) {
+ m_vBuffer.insert(m_vBuffer.begin() + index, byte);
+ return *this;
+}
+
+Buffer&
+Buffer::insert(uint32_t index, const uint8_t* bytes, uint32_t count) {
+ m_vBuffer.insert(m_vBuffer.begin() + index, bytes, bytes + count);
+ return *this;
+}
+
+Buffer&
+Buffer::remove(uint32_t index) {
+ m_vBuffer.erase(m_vBuffer.begin() + index);
+ return *this;
+}
+
+Buffer&
+Buffer::remove(uint32_t start, uint32_t end) {
+ m_vBuffer.erase(m_vBuffer.begin() + start, m_vBuffer.begin() + end);
+ return *this;
+}
+
+Buffer&
+Buffer::replace(uint32_t start, uint32_t end, const uint8_t* bytes,
+uint32_t count) {
+ if (end - start == count) {
+ if (start > end || end > m_vBuffer.size()) {
+ throw std::out_of_range("Buffer| index out of bounds");
+ }
+ std::copy(bytes, bytes + count, m_vBuffer.begin());
+ return *this;
+ }
+ return remove(start, end).insert(start, bytes, count);
+}
+
+Buffer* Buffer::clone() const {
+ return new Buffer(*this);
+}
+
diff --git a/src/MTS_Condition.cpp b/src/MTS_Condition.cpp
new file mode 100644
index 0000000..d238d50
--- /dev/null
+++ b/src/MTS_Condition.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_Condition.h>
+#include <mts/MTS_Lock.h>
+#include <mts/MTS_System.h>
+#include <mts/MTS_Logger.h>
+#include <cassert>
+#include <cerrno>
+#include <stdexcept>
+
+using namespace MTS;
+
+Condition::Condition(Lock* pLock)
+: m_pLock(pLock) {
+ if (pLock == 0) {
+ throw std::invalid_argument("Condition| constructing lock is null");
+ }
+#ifdef WIN32
+ m_apCondition.reset(CreateEvent(NULL, FALSE, FALSE, NULL));
+ if (m_pCondition.get() == NULL) {
+ throw std::bad_alloc();
+ }
+#else
+ m_apCondition.reset(new pthread_cond_t());
+ const uint32_t result = pthread_cond_init(m_apCondition.get(), NULL);
+ if (result != 0) {
+ throw std::runtime_error("Condition| failed to initialize condition");
+ }
+#endif
+}
+
+Condition::~Condition() {
+ if (!m_apCondition.isNull()) {
+#ifdef WIN32
+ const BOOL ok = CloseHandle(m_apCondition.get());
+ assert(ok);
+#else
+ const uint32_t result = pthread_cond_destroy(m_apCondition.get());
+ if (result != 0) {
+ printWarning("Condition| failed to destroy condition");
+ }
+ assert(result == 0);
+#endif
+ }
+}
+
+void Condition::wait() {
+#ifdef WIN32
+ wait(INFINITE);
+#else
+ const uint32_t result = pthread_cond_wait(m_apCondition.get(),
+ m_pLock->m_apMutex.get());
+ if (result != 0) {
+ printWarning("Condition| failed to wait on condition");
+ }
+ assert(result == 0);
+#endif
+}
+
+void Condition::wait(uint32_t millis) {
+ assert(m_pLock->isLocked());
+ if(!m_pLock->isLocked()) {
+ printWarning("Condition| lock was not locked. not waiting on signal.");
+ return;
+ }
+#ifdef WIN32
+ ResetEvent(m_apCondition.get());
+ m_pLock->unlock();
+ const DWORD waitResult = WaitForSingleObject(m_apCondition.get(), millis);
+ assert(waitResult == WAIT_OBJECT_0 || waitResult == WAIT_TIMEOUT);
+ m_pLock->lock();
+#else
+ timespec abstime;
+ int64_t micros = System::timeMicros() + (millis * 1000);
+ abstime.tv_sec = static_cast<long>(micros / 1000000);
+ abstime.tv_nsec = static_cast<long>((micros % 1000000) * 1000);
+ const uint32_t result = pthread_cond_timedwait(m_apCondition.get(),
+ m_pLock->m_apMutex.get(), &abstime);
+ if (result != 0 && result != ETIMEDOUT) {
+ printWarning("Condition| failed to time wait on condition");
+ }
+ assert(result == 0 || result == ETIMEDOUT);
+#endif
+}
+
+void Condition::signal() {
+#ifdef WIN32
+ const BOOL ok = SetEvent(m_apCondition.get());
+ assert(ok);
+#else
+ const uint32_t result = pthread_cond_broadcast(m_apCondition.get());
+ if (result != 0) {
+ printWarning("Condition| failed to signal condition");
+ }
+ assert(result == 0);
+#endif
+}
diff --git a/src/MTS_Lock.cpp b/src/MTS_Lock.cpp
new file mode 100644
index 0000000..dc2e7c0
--- /dev/null
+++ b/src/MTS_Lock.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_Lock.h>
+#include <mts/MTS_Logger.h>
+#include <cassert>
+#include <stdexcept>
+
+using namespace MTS;
+
+Lock::Lock()
+: m_bLocked(false) {
+#ifdef WIN32
+ m_apMutex.reset(CreateMutex(NULL, FALSE, NULL));
+ if (m_apMutex.get() == NULL) {
+ throw std::bad_alloc();
+ }
+#else
+ m_apMutexAttr.reset(new pthread_mutexattr_t());
+ int result = pthread_mutexattr_init(m_apMutexAttr.get());
+ if (result != 0) {
+ throw std::runtime_error("failed to initialize mutex attributes");
+ }
+ result = pthread_mutexattr_settype(m_apMutexAttr.get(),
+ PTHREAD_MUTEX_RECURSIVE);
+ if (result != 0) {
+ throw std::runtime_error("failed to set mutex recursive");
+ }
+ m_apMutex.reset(new pthread_mutex_t());
+ result = pthread_mutex_init(m_apMutex.get(), m_apMutexAttr.get());
+ if (result != 0) {
+ throw std::runtime_error("failed to initialize mutex");
+ }
+#endif
+
+}
+
+Lock::~Lock() {
+ if (isLocked()) {
+ unlock();
+ }
+#ifdef WIN32
+ const BOOL ok = CloseHandle(m_apMutex.release());
+ assert(ok);
+#else
+ if (!m_apMutex.isNull()) {
+ const int result = pthread_mutex_destroy(m_apMutex.get());
+ if (result != 0) {
+ printWarning("Lock| Failed to destroy mutex");
+ }
+ assert(result == 0);
+ }
+ if (!m_apMutexAttr.isNull()) {
+ const int result = pthread_mutexattr_destroy(m_apMutexAttr.get());
+ if (result != 0) {
+ printWarning("Lock| Failed to destroy mutex attributes");
+ }
+ assert(result == 0);
+ }
+#endif
+}
+
+void Lock::lock() {
+#ifdef WIN32
+ const DWORD waitResult = WaitForSingleObject(m_apMutex.get(), INFINITE);
+ assert(waitResult == WAIT_OBJECT_0);
+#else
+ const int result = pthread_mutex_lock(m_apMutex.get());
+ if (result != 0) {
+ printWarning("Lock| Failed to lock mutex");
+ }
+ assert(result == 0);
+#endif
+ m_bLocked = true;
+}
+
+void Lock::unlock() {
+ m_bLocked = false;
+#ifdef WIN32
+ const BOOL ok = ReleaseMutex(m_apMutex.get());
+ assert(ok);
+#else
+ const int result = pthread_mutex_unlock(m_apMutex.get());
+ if (result != 0) {
+ printWarning("Lock| Failed to unlock mutex");
+ }
+ assert(result == 0);
+#endif
+}
+
+bool Lock::isLocked() const {
+ return m_bLocked;
+}
+
+Condition* Lock::createCondition() {
+ return new Condition(this);
+}
diff --git a/src/MTS_Logger.cpp b/src/MTS_Logger.cpp
new file mode 100644
index 0000000..93775fe
--- /dev/null
+++ b/src/MTS_Logger.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_Lock.h>
+#include <mts/MTS_Text.h>
+#include <mts/MTS_System.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+#include <iostream>
+
+using namespace MTS;
+
+const char* Logger::PrintLevel::OFF_LABEL = "OFF";
+const char* Logger::PrintLevel::FATAL_LABEL = "FATAL";
+const char* Logger::PrintLevel::ERROR_LABEL = "ERROR";
+const char* Logger::PrintLevel::WARNING_LABEL = "WARNING";
+const char* Logger::PrintLevel::INFO_LABEL = "INFO";
+const char* Logger::PrintLevel::CONFIG_LABEL = "CONFIG";
+const char* Logger::PrintLevel::DEBUG_LABEL = "DEBUG";
+const char* Logger::PrintLevel::TRACE_LABEL = "TRACE";
+const char* Logger::PrintLevel::MAXIMUM_LABEL = "MAXIMUM";
+
+const int Logger::PrintLevel::OFF_LEVEL = 0;
+const int Logger::PrintLevel::MINIMUM_LEVEL = 1;
+const int Logger::PrintLevel::FATAL_LEVEL = 1;
+const int Logger::PrintLevel::ERROR_LEVEL = 10;
+const int Logger::PrintLevel::WARNING_LEVEL = 20;
+const int Logger::PrintLevel::INFO_LEVEL = 30;
+const int Logger::PrintLevel::CONFIG_LEVEL = 40;
+const int Logger::PrintLevel::DEBUG_LEVEL = 50;
+const int Logger::PrintLevel::TRACE_LEVEL = 60;
+const int Logger::PrintLevel::MAXIMUM_LEVEL = 100;
+
+volatile int Logger::m_iPrintLevel = Logger::PrintLevel::MAXIMUM_LEVEL;
+std::string Logger::m_sPrintLevel = Logger::PrintLevel::MAXIMUM_LABEL;
+Logger::PrintMode Logger::m_eMode = Logger::PrintMode::STDOUT_ONLY;
+FILE* Logger::m_pFile = NULL;
+int Logger::m_iLogFacility = -1;
+Lock Logger::m_oPrintLock;
+std::string Logger::m_sIdent;
+std::string Logger::m_sFileName;
+
+int Logger::getPrintLevel() {
+ return m_iPrintLevel;
+}
+
+const std::string& Logger::getPrintLevelString() {
+ if (m_iPrintLevel == PrintLevel::OFF_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::OFF_LABEL);
+ else if (m_iPrintLevel == PrintLevel::FATAL_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::FATAL_LABEL);
+ else if (m_iPrintLevel > PrintLevel::FATAL_LEVEL && m_iPrintLevel <= PrintLevel::ERROR_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::ERROR_LABEL);
+ else if (m_iPrintLevel > PrintLevel::ERROR_LEVEL && m_iPrintLevel <= PrintLevel::WARNING_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::WARNING_LABEL);
+ else if (m_iPrintLevel > PrintLevel::WARNING_LEVEL && m_iPrintLevel <= PrintLevel::INFO_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::INFO_LABEL);
+ else if (m_iPrintLevel > PrintLevel::INFO_LEVEL && m_iPrintLevel <= PrintLevel::CONFIG_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::CONFIG_LABEL);
+ else if (m_iPrintLevel > PrintLevel::CONFIG_LEVEL && m_iPrintLevel <= PrintLevel::DEBUG_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::DEBUG_LABEL);
+ else if (m_iPrintLevel > PrintLevel::DEBUG_LEVEL && m_iPrintLevel <= PrintLevel::TRACE_LEVEL)
+ m_sPrintLevel = std::string(PrintLevel::TRACE_LABEL);
+ else
+ m_sPrintLevel = std::string(PrintLevel::MAXIMUM_LABEL);
+
+ return m_sPrintLevel;
+}
+
+void Logger::setPrintLevel(int32_t level, bool silent) {
+ m_iPrintLevel = level;
+ if (!silent) {
+ printf(level, "Logger Level Changed to %d\n", level);
+ }
+}
+
+bool Logger::isPrintable(int32_t level) {
+ int32_t currentLevel = getPrintLevel();
+ return (level <= currentLevel) && (currentLevel > PrintLevel::OFF_LEVEL);
+}
+
+int32_t Logger::syslogPrintLevelConversion(const int32_t& level) {
+ if (level < 10) {
+ return LOG_EMERG;
+ } else if (level < 20) {
+ return LOG_ERR;
+ } else if (level < 30) {
+ return LOG_WARNING;
+ } else if (level < 50) {
+ return LOG_INFO;
+ } else {
+ return LOG_DEBUG;
+ }
+}
+
+void Logger::printMessage(const int32_t& level, const char* label, const char* format, va_list argptr) {
+
+ m_oPrintLock.lock();
+ switch (m_eMode) {
+ case Logger::PrintMode::STDOUT_ONLY:
+ ::printf("%s|%s|", MTS::Text::time(MTS::System::timeMicros()).c_str(), label);
+ vprintf(format, argptr);
+ ::printf("\n");
+ break;
+
+ case Logger::PrintMode::FILE_ONLY:
+ fprintf(m_pFile, "%s|%s| ", MTS::Text::time(MTS::System::timeMicros()).c_str(), label);
+ vfprintf(m_pFile, format, argptr);
+ fprintf(m_pFile, "\n");
+ fflush(m_pFile);
+ break;
+
+ case Logger::PrintMode::SYSLOG_ONLY:
+ if (level <= Logger::PrintLevel::TRACE_LEVEL) {
+ vsyslog(syslogPrintLevelConversion(level), format, argptr);
+ }
+ break;
+
+ case Logger::PrintMode::STDOUT_AND_FILE: {
+ const std::string timestr(MTS::Text::time(MTS::System::timeMicros()));
+ va_list argptr2;
+ va_copy(argptr2, argptr);
+ ::printf("%s|%s|", timestr.c_str(), label);
+ vprintf(format, argptr);
+ ::printf("\n");
+ fprintf(m_pFile, "%s|%s| ", timestr.c_str(), label);
+ vfprintf(m_pFile, format, argptr2);
+ fprintf(m_pFile, "\n");
+ fflush(m_pFile);
+ va_end(argptr2);
+ }
+ break;
+
+ case Logger::PrintMode::STDOUT_AND_SYSLOG: {
+ if (level <= Logger::PrintLevel::TRACE_LEVEL) {
+ va_list argptr2;
+ va_copy(argptr2, argptr);
+ vsyslog(syslogPrintLevelConversion(level), format, argptr2);
+ va_end(argptr2);
+ }
+ ::printf("%s|", MTS::Text::time(MTS::System::timeMicros()).c_str());
+ ::printf("%s|", label);
+ vprintf(format, argptr);
+ ::printf("\n");
+ }
+ break;
+
+ case Logger::PrintMode::NO_PRINTING:
+ default:
+ break;
+
+ }
+ m_oPrintLock.unlock();
+}
+
+void Logger::printfFatal(const char* format, ...) {
+ if (isPrintable(PrintLevel::FATAL_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(PrintLevel::FATAL_LEVEL, PrintLevel::FATAL_LABEL, format, argptr);
+ va_end(argptr);
+ }
+}
+
+void Logger::printfError(const char* format, ...) {
+ if (isPrintable(PrintLevel::ERROR_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(PrintLevel::ERROR_LEVEL, PrintLevel::ERROR_LABEL, format, argptr);
+ va_end(argptr);
+ }
+}
+
+void Logger::printfWarning(const char* format, ...) {
+ if (isPrintable(PrintLevel::WARNING_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(PrintLevel::WARNING_LEVEL, PrintLevel::WARNING_LABEL, format, argptr);
+ va_end(argptr);
+ }
+}
+
+void Logger::printfInfo(const char* format, ...) {
+ if (isPrintable(PrintLevel::INFO_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(PrintLevel::INFO_LEVEL, PrintLevel::INFO_LABEL, format, argptr);
+ va_end(argptr);
+ }
+}
+
+void Logger::printfConfig(const char* format, ...) {
+ if (isPrintable(PrintLevel::CONFIG_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(PrintLevel::CONFIG_LEVEL, PrintLevel::CONFIG_LABEL, format, argptr);
+ va_end(argptr);
+ }
+}
+
+void Logger::printfDebug(const char* format, ...) {
+ if (isPrintable(PrintLevel::DEBUG_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(PrintLevel::DEBUG_LEVEL, PrintLevel::DEBUG_LABEL, format, argptr);
+ va_end(argptr);
+ }
+}
+
+void Logger::printfTrace(const char* format, ...) {
+ if (isPrintable(PrintLevel::TRACE_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(PrintLevel::TRACE_LEVEL, PrintLevel::TRACE_LABEL, format, argptr);
+ va_end(argptr);
+ }
+}
+
+void Logger::printfGeneric(int level, const char* label, const char* format, ...) {
+ va_list argptr;
+ va_start(argptr, format);
+ printMessage(level, label, format, argptr);
+ va_end(argptr);
+}
+
+void Logger::printf(int level, const char* format, ...) {
+ if (isPrintable(level)) {
+ va_list argptr;
+ va_start(argptr, format);
+ m_oPrintLock.lock();
+ vprintf(format, argptr);
+ m_oPrintLock.unlock();
+ va_end(argptr);
+ }
+}
+
+void Logger::printf(const char* format, ...) {
+ if (isPrintable(PrintLevel::MAXIMUM_LEVEL)) {
+ va_list argptr;
+ va_start(argptr, format);
+ m_oPrintLock.lock();
+ vprintf(format, argptr);
+ m_oPrintLock.unlock();
+ va_end(argptr);
+ }
+}
+
+bool Logger::setup(const PrintMode& mode) {
+ m_oPrintLock.lock();
+ m_eMode = mode;
+ m_oPrintLock.unlock();
+ return true;
+}
+
+bool Logger::setup(const PrintMode& mode, const std::string& filename) {
+ /* close the handle and reopen it each time setup() is called in case
+ * we are being used with programs like logrotate, etc
+ *
+ * if the file is different, switch to the new file */
+
+ m_oPrintLock.lock();
+ if (m_pFile) {
+ fclose(m_pFile);
+ }
+ if (m_sFileName != filename) {
+ m_sFileName = filename;
+ }
+ m_pFile = fopen(m_sFileName.c_str(), "a");
+ m_iLogFacility = -1;
+ m_oPrintLock.unlock();
+
+ if (!m_pFile) {
+ fprintf(stderr, "Error opening logfile %s\n", m_sFileName.c_str());
+ return false;
+ }
+ m_eMode = mode;
+ return true;
+}
+
+bool Logger::setup(const PrintMode& mode, const std::string& ident, const int& option, const int& facility) {
+ m_oPrintLock.lock();
+ m_pFile = NULL;
+ m_sFileName = "";
+ m_iLogFacility = facility;
+ m_sIdent = ident;
+ m_eMode = mode;
+ m_oPrintLock.unlock();
+ openlog(m_sIdent.c_str(), option, m_iLogFacility);
+ return true;
+}
+
diff --git a/src/MTS_Object.cpp b/src/MTS_Object.cpp
new file mode 100644
index 0000000..c798c70
--- /dev/null
+++ b/src/MTS_Object.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_Object.h>
+#include <sstream>
+#include <typeinfo>
+
+using namespace MTS;
+
+Object::Object() {
+}
+
+Object::~Object() {
+}
+
+std::string Object::toString() const {
+ return std::string("MTS::Object");
+}
+
+std::string Object::toIDD() const {
+ std::stringstream ss;
+ ss << typeid(*this).name() << "@" << reinterpret_cast<const void*>(this);
+ return ss.str().erase(0, 6);
+}
diff --git a/src/MTS_SignalThread.cpp b/src/MTS_SignalThread.cpp
new file mode 100644
index 0000000..99975c0
--- /dev/null
+++ b/src/MTS_SignalThread.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_SignalThread.h>
+#include <mts/MTS_Logger.h>
+
+using namespace MTS;
+
+SignalThread::SignalThread(const std::string& name)
+: Thread(name, true)
+, m_bShouldExecute(false)
+, m_bCurrentlyExecuting(false)
+, m_ui32WaitMillis(200)
+{
+ init();
+}
+
+SignalThread::SignalThread(const std::string& name, uint32_t waitMillis)
+: Thread(name, true)
+, m_bShouldExecute(false)
+, m_bCurrentlyExecuting(false)
+, m_ui32WaitMillis(waitMillis)
+{
+ init();
+}
+
+void SignalThread::init()
+{
+ printConfig("SignalThread| %s - starting up", Thread::getName().c_str());
+ m_apStateLock.reset(new MTS::Lock);
+ m_apConditionLock.reset(new MTS::Lock);
+ m_apCondition.reset(m_apConditionLock->createCondition());
+}
+
+SignalThread::~SignalThread()
+{
+ stop();
+ m_apStateLock.reset();
+ m_apConditionLock.reset();
+ m_apCondition.reset();
+ printConfig("SignalThread| %s - shutting down", Thread::getName().c_str());
+}
+
+void SignalThread::signal()
+{
+ m_apConditionLock->lock();
+ m_bShouldExecute = true;
+ m_apCondition->signal();
+ m_apConditionLock->unlock();
+}
+
+void SignalThread::run()
+{
+ while (! Thread::isCanceled())
+ {
+ m_apConditionLock->lock();
+ if (! m_bShouldExecute)
+ {
+ m_apCondition->wait(m_ui32WaitMillis);
+ }
+ if (m_bShouldExecute)
+ {
+ printTrace("SignalThread| %s - starting execute() function", Thread::getName().c_str());
+ m_apStateLock->lock();
+ m_bCurrentlyExecuting = true;
+ m_apStateLock->unlock();
+ execute();
+ m_apStateLock->lock();
+ m_bCurrentlyExecuting = false;
+ m_apStateLock->unlock();
+ printTrace("SignalThread| %s - finished execute() function", Thread::getName().c_str());
+ }
+ m_bShouldExecute = false;
+ m_apConditionLock->unlock();
+ }
+}
+
+bool SignalThread::isExecuting() const
+{
+ bool retval = false;
+ m_apStateLock->lock();
+ retval = m_bCurrentlyExecuting;
+ m_apStateLock->unlock();
+
+ return retval;
+}
diff --git a/src/MTS_System.cpp b/src/MTS_System.cpp
new file mode 100644
index 0000000..e1ed348
--- /dev/null
+++ b/src/MTS_System.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_System.h>
+#include <fstream>
+#include <sstream>
+#include <cassert>
+
+#ifdef WIN32
+#include <windows.h>
+
+//WIN32: FILETIME structure has a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601.
+
+static int64_t getEpochTimeMicros() {
+ const SYSTEMTIME EPOCH = {1970, 1, 4, 1, 0, 0, 0, 0};
+ FILETIME ft;
+ BOOL ok = SystemTimeToFileTime(&EPOCH, &ft);
+ assert(ok);
+ int64_t epochTimeMicros = ((static_cast<uint64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) / 10;
+ return epochTimeMicros;
+}
+
+static int64_t getSystemTimeMicros() {
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ FILETIME ft;
+ BOOL ok = SystemTimeToFileTime(&st, &ft);
+ assert(ok);
+ int64_t systemTimeMicros = ((static_cast<uint64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) / 10;
+ return systemTimeMicros;
+}
+
+static int64_t getClockFrequency() {
+ LARGE_INTEGER freq;
+ BOOL ok = QueryPerformanceFrequency(&freq);
+ assert(ok);
+ return freq.QuadPart;
+}
+
+static int64_t getClockValue() {
+ LARGE_INTEGER value;
+ BOOL ok = QueryPerformanceCounter(&value);
+ assert(ok);
+ return value.QuadPart;
+}
+
+#else
+#include <time.h>
+#endif
+
+using namespace MTS;
+
+uint64_t System::timeMicros() {
+ int64_t micros = 0;
+#ifdef WIN32
+ static const int64_t EPOCH_TIME_MICROS = getEpochTimeMicros();
+ micros = getSystemTimeMicros() - EPOCH_TIME_MICROS;
+#else
+ timespec ts;
+ int result = clock_gettime(CLOCK_REALTIME, &ts);
+ if (result == 0) {
+ micros = (static_cast<int64_t>(ts.tv_sec) * 1000000)
+ + (ts.tv_nsec / 1000);
+ }
+#endif
+ return micros;
+}
+
+uint64_t System::precisionTimeMicros() {
+ int64_t micros = 0;
+#ifdef WIN32
+ static const double TO_MICROS = 1000000.0 / getClockFrequency();
+ int64_t value = getClockValue();
+ micros = static_cast<int64_t>(value * TO_MICROS);
+#else
+ micros = timeMicros();
+#endif
+ return micros;
+}
+
+bool System::isBigEndian() {
+ static union {
+ uint32_t i;
+ char c[4];
+ } endian = { 0x01020304 };
+
+ return endian.c[0] == 1;
+}
+
+void System::swapBytes(uint8_t* const pBuffer, const uint32_t iSize) {
+ if (iSize > 1 && pBuffer != 0) {
+ uint8_t cByte = 0;
+ uint32_t i;
+ uint32_t j;
+ for (i = 0, j = iSize - 1; i < j; i++, j--) {
+ cByte = pBuffer[i];
+ pBuffer[i] = pBuffer[j];
+ pBuffer[j] = cByte;
+ }
+ }
+}
+
+int32_t System::cmd(const std::string& cmd, std::string& result) {
+ std::string output;
+ FILE * stream;
+ const int max_buffer = 256;
+ char buffer[max_buffer];
+ int32_t code = -1;
+
+ stream = popen(cmd.c_str(), "r");
+ if (stream) {
+ while (!feof(stream))
+ if (fgets(buffer, max_buffer, stream) != NULL)
+ output.append(buffer);
+ code = pclose(stream);
+ }
+
+ result = output;
+
+ return code;
+}
+
+int32_t System::readFile(const std::string& path, std::string& result) {
+ std::ifstream infile(path.c_str());
+ std::stringstream ss;
+
+ if (!infile.is_open()) {
+ return -1;
+ }
+
+ ss << infile.rdbuf();
+
+ infile.close();
+
+ result = ss.str();
+
+ return 0;
+}
+
diff --git a/src/MTS_Text.cpp b/src/MTS_Text.cpp
new file mode 100644
index 0000000..d823bfe
--- /dev/null
+++ b/src/MTS_Text.cpp
@@ -0,0 +1,701 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License