diff options
| author | Jesse Gilles <jgilles@multitech.com> | 2015-04-20 16:49:52 -0500 |
|---|---|---|
| committer | Jesse Gilles <jgilles@multitech.com> | 2015-04-20 16:49:52 -0500 |
| commit | 17b117e73df71925d73ee026b4f54aa1867ce0a5 (patch) | |
| tree | 382610c8e598a77a961c5ceb32b9b614ed00e757 /src | |
| download | libmts-17b117e73df71925d73ee026b4f54aa1867ce0a5.tar.gz libmts-17b117e73df71925d73ee026b4f54aa1867ce0a5.tar.bz2 libmts-17b117e73df71925d73ee026b4f54aa1867ce0a5.zip | |
initial commit
Diffstat (limited to 'src')
| -rw-r--r-- | src/MTS_Buffer.cpp | 159 | ||||
| -rw-r--r-- | src/MTS_Condition.cpp | 115 | ||||
| -rw-r--r-- | src/MTS_Lock.cpp | 114 | ||||
| -rw-r--r-- | src/MTS_Logger.cpp | 312 | ||||
| -rw-r--r-- | src/MTS_Object.cpp | 41 | ||||
| -rw-r--r-- | src/MTS_SignalThread.cpp | 103 | ||||
| -rw-r--r-- | src/MTS_System.cpp | 156 | ||||
| -rw-r--r-- | src/MTS_Text.cpp | 701 | ||||
| -rw-r--r-- | src/MTS_Thread.cpp | 227 | ||||
| -rw-r--r-- | src/MTS_Timer.cpp | 103 | ||||
| -rw-r--r-- | src/MTS_TimerThread.cpp | 116 |
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 |
