From e5cea3ead078302df24d17ce43895ceae5c5046c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 20:31:08 +0200 Subject: [PATCH 01/12] service interface stream enhancements --- serviceinterface/ServiceInterfaceBuffer.cpp | 28 +++++++++++++-------- serviceinterface/ServiceInterfaceBuffer.h | 28 ++++++++++++++++----- serviceinterface/ServiceInterfaceStream.cpp | 6 ++--- serviceinterface/ServiceInterfaceStream.h | 7 +++--- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 58065994a..2a97ab90b 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -23,14 +23,16 @@ int ServiceInterfaceBuffer::sync(void) { if (this->isActive) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - char preamble[96] = { 0 }; - sprintf(preamble, "%s: | %lu:%02lu:%02lu.%03lu | ", - this->log_message.c_str(), (unsigned long) loggerTime.hour, - (unsigned long) loggerTime.minute, - (unsigned long) loggerTime.second, - (unsigned long) loggerTime.usecond /1000); + std::string preamble; + if(addCrToPreamble) { + preamble += "\r"; + } + preamble += log_message + ": | " + zero_padded(loggerTime.hour, 2) + + ":" + zero_padded(loggerTime.minute, 2) + ":" + + zero_padded(loggerTime.second, 2) + "." + + zero_padded(loggerTime.usecond/1000, 3) + " | "; // Write log_message and time - this->putChars(preamble, preamble + sizeof(preamble)); + this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); // Handle output this->putChars(pbase(), pptr()); } @@ -39,9 +41,13 @@ int ServiceInterfaceBuffer::sync(void) { return 0; } + + #ifndef UT699 -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, + uint16_t port, bool addCrToPreamble) { + this->addCrToPreamble = addCrToPreamble; this->log_message = set_message; this->isActive = true; setp( buf, buf + BUF_SIZE ); @@ -55,17 +61,19 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { } memcpy(array, begin, length); - for( ; begin != end; begin++){ + for(; begin != end; begin++){ printChar(begin); } } #endif + #ifdef UT699 #include -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, + uint16_t port) { this->log_message = set_message; this->isActive = true; setp( buf, buf + BUF_SIZE ); diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index b42c8a197..a2bc4f4b1 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -2,32 +2,36 @@ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #include -#include #include #include +#include #ifndef UT699 -class ServiceInterfaceBuffer: public std::basic_streambuf > { +class ServiceInterfaceBuffer: + public std::basic_streambuf> { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port); + ServiceInterfaceBuffer(std::string set_message, uint16_t port, + bool addCrToPreamble); protected: bool isActive; // This is called when buffer becomes full. If // buffer is not used, then this is called every // time when characters are put to stream. - virtual int overflow(int c = Traits::eof()); + int overflow(int c = Traits::eof()) override; // This function is called when stream is flushed, // for example when std::endl is put to stream. - virtual int sync(void); + int sync(void) override; private: // For additional message information std::string log_message; // For EOF detection typedef std::char_traits Traits; + // This is useful for some terminal programs which do not have + // implicit carriage return with newline characters. + bool addCrToPreamble; // Work in buffer mode. It is also possible to work without buffer. static size_t const BUF_SIZE = 128; @@ -35,6 +39,18 @@ private: // In this function, the characters are parsed. void putChars(char const* begin, char const* end); + + template + std::string zero_padded(const T& num, uint8_t width) { + std::ostringstream string_to_pad; + string_to_pad << std::setw(width) << std::setfill('0') << num; + std::string result = string_to_pad.str(); + if (result.length() > width) + { + result.erase(0, result.length() - width); + } + return result; + } }; #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index c2979f369..40f52f1fe 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -5,7 +5,7 @@ void ServiceInterfaceStream::setActive( bool myActive) { } ServiceInterfaceStream::ServiceInterfaceStream(std::string set_message, - uint16_t port) : - std::basic_ostream >(&buf), buf( - set_message, port) { + bool addCrToPreamble, uint16_t port) : + std::basic_ostream>(&buf), + buf(set_message, port, addCrToPreamble) { } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index df736a1b6..a445dcedd 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -17,14 +17,15 @@ extern std::ostream error; } -class ServiceInterfaceStream : public std::basic_ostream< char, std::char_traits< char > > { +class ServiceInterfaceStream : + public std::basic_ostream> { protected: ServiceInterfaceBuffer buf; public: - ServiceInterfaceStream( std::string set_message, uint16_t port = 1234 ); + ServiceInterfaceStream( std::string set_message, + bool addCrToPreamble = false, uint16_t port = 1234); void setActive( bool ); }; - #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ From 7259a1356959ab9fb18472bfdeb45a2c88f864dd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 3 Jun 2020 23:14:17 +0200 Subject: [PATCH 02/12] more improvements: 1. New optional flag to redirect print to stderr. THis can be useful on host environemtns (e.g linux) 2. non-buffered mode if this flag is true: the preamble msut be printed manually 2. Getter function for preamble for that case. 3. printChar function: specify whether to print to stderr or stdout --- serviceinterface/ServiceInterfaceBuffer.cpp | 94 ++++++++++++--------- serviceinterface/ServiceInterfaceBuffer.h | 50 ++++++++--- serviceinterface/ServiceInterfaceStream.cpp | 12 ++- serviceinterface/ServiceInterfaceStream.h | 37 ++++++-- 4 files changed, 131 insertions(+), 62 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 2a97ab90b..93de88b39 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -3,9 +3,42 @@ #include // to be implemented by bsp -extern "C" void printChar(const char*); +extern "C" void printChar(const char*, bool errStream); + +#ifndef UT699 + +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, + bool errStream, bool addCrToPreamble, uint16_t port): + isActive(true), logMessage(setMessage), + addCrToPreamble(addCrToPreamble), errStream(errStream) { + if(not errStream) { + // Set pointers if the stream is buffered. + setp( buf, buf + BUF_SIZE ); + } +} + +void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { + char array[BUF_SIZE]; + uint32_t length = end - begin; + if (length > sizeof(array)) { + length = sizeof(array); + } + memcpy(array, begin, length); + + for(; begin != end; begin++){ + printChar(begin, false); + } +} + +#endif int ServiceInterfaceBuffer::overflow(int c) { + if(errStream and this->isActive) { + if (c != Traits::eof()) { + printChar(reinterpret_cast(&c), true); + } + return 0; + } // Handle output putChars(pbase(), pptr()); if (c != Traits::eof()) { @@ -20,53 +53,38 @@ int ServiceInterfaceBuffer::overflow(int c) { } int ServiceInterfaceBuffer::sync(void) { - if (this->isActive) { - Clock::TimeOfDay_t loggerTime; - Clock::getDateAndTime(&loggerTime); - std::string preamble; - if(addCrToPreamble) { - preamble += "\r"; + if(not this->isActive or errStream) { + if(not errStream) { + setp(buf, buf + BUF_SIZE - 1); } - preamble += log_message + ": | " + zero_padded(loggerTime.hour, 2) - + ":" + zero_padded(loggerTime.minute, 2) + ":" - + zero_padded(loggerTime.second, 2) + "." - + zero_padded(loggerTime.usecond/1000, 3) + " | "; - // Write log_message and time - this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); - // Handle output - this->putChars(pbase(), pptr()); + return 0; } + + auto preamble = getPreamble(); + // Write logMessage and time + this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); + // Handle output + this->putChars(pbase(), pptr()); // This tells that buffer is empty again setp(buf, buf + BUF_SIZE - 1); return 0; } - -#ifndef UT699 - -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, - uint16_t port, bool addCrToPreamble) { - this->addCrToPreamble = addCrToPreamble; - this->log_message = set_message; - this->isActive = true; - setp( buf, buf + BUF_SIZE ); +std::string ServiceInterfaceBuffer::getPreamble() { + Clock::TimeOfDay_t loggerTime; + Clock::getDateAndTime(&loggerTime); + std::string preamble; + if(addCrToPreamble) { + preamble += "\r"; + } + preamble += logMessage + ": | " + zero_padded(loggerTime.hour, 2) + + ":" + zero_padded(loggerTime.minute, 2) + ":" + + zero_padded(loggerTime.second, 2) + "." + + zero_padded(loggerTime.usecond/1000, 3) + " | "; + return preamble; } -void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { - char array[BUF_SIZE]; - uint32_t length = end - begin; - if (length > sizeof(array)) { - length = sizeof(array); - } - memcpy(array, begin, length); - - for(; begin != end; begin++){ - printChar(begin); - } - -} -#endif #ifdef UT699 diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index a2bc4f4b1..74facafe0 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -3,43 +3,64 @@ #include #include -#include #include #ifndef UT699 + +/** + * @brief This is the underlying stream buffer which implements the + * streambuf class and overloads the overflow() and sync() methods + * @details + * This class is used to modify the output of the stream, for example by adding. + * It also calls the char printing function which is implemented in the + * board supply package (BSP). + */ class ServiceInterfaceBuffer: - public std::basic_streambuf> { + public std::streambuf { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port, - bool addCrToPreamble); + ServiceInterfaceBuffer(std::string setMessage, bool errStream, + bool addCrToPreamble, uint16_t port); + protected: bool isActive; - // This is called when buffer becomes full. If - // buffer is not used, then this is called every - // time when characters are put to stream. + //! This is called when buffer becomes full. If + //! buffer is not used, then this is called every + //! time when characters are put to stream. int overflow(int c = Traits::eof()) override; - // This function is called when stream is flushed, - // for example when std::endl is put to stream. + //! This function is called when stream is flushed, + //! for example when std::endl is put to stream. int sync(void) override; private: - // For additional message information - std::string log_message; + //! For additional message information + std::string logMessage; // For EOF detection typedef std::char_traits Traits; - // This is useful for some terminal programs which do not have - // implicit carriage return with newline characters. + //! This is useful for some terminal programs which do not have + //! implicit carriage return with newline characters. bool addCrToPreamble; + //! This specifies to print to stderr and work in unbuffered mode. + bool errStream; // Work in buffer mode. It is also possible to work without buffer. static size_t const BUF_SIZE = 128; char buf[BUF_SIZE]; - // In this function, the characters are parsed. + //! In this function, the characters are parsed. void putChars(char const* begin, char const* end); + std::string getPreamble(); + + /** + * This helper function returns the zero padded string version of a number. + * The type is deduced automatically. + * @tparam T + * @param num + * @param width + * @return + */ template std::string zero_padded(const T& num, uint8_t width) { std::ostringstream string_to_pad; @@ -52,6 +73,7 @@ private: return result; } }; + #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 40f52f1fe..783715484 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -1,11 +1,15 @@ #include +ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, + bool errStream, bool addCrToPreamble, uint16_t port) : + std::ostream(&buf), + buf(setMessage, errStream, addCrToPreamble, port) { +} + void ServiceInterfaceStream::setActive( bool myActive) { this->buf.isActive = myActive; } -ServiceInterfaceStream::ServiceInterfaceStream(std::string set_message, - bool addCrToPreamble, uint16_t port) : - std::basic_ostream>(&buf), - buf(set_message, port, addCrToPreamble) { +std::string ServiceInterfaceStream::getPreamble() { + return buf.getPreamble(); } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index a445dcedd..aecd45c37 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -3,11 +3,9 @@ #include #include -#include -#include #include -// Unfortunately, there must be a forward declaration of log_fe +// Unfortunately, there must be a forward declaration of the log front end // (MUST be defined in main), to let the system know where to write to. namespace sif { extern std::ostream debug; @@ -18,14 +16,41 @@ extern std::ostream error; class ServiceInterfaceStream : - public std::basic_ostream> { + public std::ostream { protected: ServiceInterfaceBuffer buf; public: - ServiceInterfaceStream( std::string set_message, - bool addCrToPreamble = false, uint16_t port = 1234); + /** + * This constructor is used by specifying the preamble message. + * Optionally, the output can be directed to stderr and a CR character + * can be prepended to the preamble. + * @param set_message + * @param errStream + * @param addCrToPreamble + * @param port + */ + ServiceInterfaceStream(std::string setMessage, + bool errStream = false, bool addCrToPreamble = false, + uint16_t port = 1234); + + //! An inactive stream will not print anything. void setActive( bool ); + + /** + * This can be used to retrieve the preamble in case it should be printed in + * the unbuffered mode. + * @return Preamle consisting of log message and timestamp. + */ + std::string getPreamble(); }; +// Forward declaration of interface streams. These are needed so the public +// functions can be used by including this header +namespace sif { +extern ServiceInterfaceStream debugStream; +extern ServiceInterfaceStream infoStream; +extern ServiceInterfaceStream warningStream; +extern ServiceInterfaceStream errorStream; +} #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ From 9361568b4513645fb42a571659e8e060b3d374c7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 3 Jun 2020 23:28:31 +0200 Subject: [PATCH 03/12] clarifying commnet --- serviceinterface/ServiceInterfaceStream.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index aecd45c37..375a18759 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -5,8 +5,11 @@ #include #include -// Unfortunately, there must be a forward declaration of the log front end -// (MUST be defined in main), to let the system know where to write to. +/* Unfortunately, there must be a forward declaration of the log front end + * (MUST be defined in main), to let the system know where to write to. + * The ServiceInterfaceStream instances, which are declared below and + * can instantaited somewhere else can be passed to these front ends by passing + * their underlying buffers with .rdbuf() */ namespace sif { extern std::ostream debug; extern std::ostream info; From 764608005b0934c02faedf9913ae7b3153e11ba3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 13:26:35 +0200 Subject: [PATCH 04/12] buf renamed to streambuf --- osal/FreeRTOS/MessageQueue.cpp | 3 ++- serviceinterface/ServiceInterfaceStream.cpp | 8 ++++---- serviceinterface/ServiceInterfaceStream.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index e5da04427..18e7aa3d0 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -97,7 +97,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, bool ignoreFault) { message->setSender(sentFrom); - BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo),reinterpret_cast(message->getBuffer()), 0); + BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo), + reinterpret_cast(message->getBuffer()), 0); if (result != pdPASS) { if (!ignoreFault) { InternalErrorReporterIF* internalErrorReporter = objectManager->get( diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 783715484..d9bc980a7 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -2,14 +2,14 @@ ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, bool errStream, bool addCrToPreamble, uint16_t port) : - std::ostream(&buf), - buf(setMessage, errStream, addCrToPreamble, port) { + std::ostream(&streambuf), + streambuf(setMessage, errStream, addCrToPreamble, port) { } void ServiceInterfaceStream::setActive( bool myActive) { - this->buf.isActive = myActive; + this->streambuf.isActive = myActive; } std::string ServiceInterfaceStream::getPreamble() { - return buf.getPreamble(); + return streambuf.getPreamble(); } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index 375a18759..c44fe03a0 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -21,7 +21,7 @@ extern std::ostream error; class ServiceInterfaceStream : public std::ostream { protected: - ServiceInterfaceBuffer buf; + ServiceInterfaceBuffer streambuf; public: /** * This constructor is used by specifying the preamble message. From f8fb370ae7698c8b27c86428ab01129042cedfa3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 14:08:26 +0200 Subject: [PATCH 05/12] preamble changes started --- osal/FreeRTOS/FixedTimeslotTask.cpp | 2 +- serviceinterface/ServiceInterfaceBuffer.cpp | 65 +++++++++++++++------ serviceinterface/ServiceInterfaceBuffer.h | 8 ++- serviceinterface/ServiceInterfaceStream.cpp | 28 +++++++-- serviceinterface/ServiceInterfaceStream.h | 53 ++++++++--------- 5 files changed, 104 insertions(+), 52 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index fb3c3b03e..549ffbf17 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -68,7 +68,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, } sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; + " not found, not adding it to pst\r" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 93de88b39..321b1d3ca 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -8,13 +8,15 @@ extern "C" void printChar(const char*, bool errStream); #ifndef UT699 ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, - bool errStream, bool addCrToPreamble, uint16_t port): + bool addCrToPreamble, bool buffered , bool errStream, uint16_t port): isActive(true), logMessage(setMessage), - addCrToPreamble(addCrToPreamble), errStream(errStream) { - if(not errStream) { + addCrToPreamble(addCrToPreamble), buffered(buffered), + errStream(errStream) { + if(buffered) { // Set pointers if the stream is buffered. setp( buf, buf + BUF_SIZE ); } + preamble.reserve(96); } void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { @@ -26,16 +28,27 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { memcpy(array, begin, length); for(; begin != end; begin++){ - printChar(begin, false); + if(errStream) { + printChar(begin, true); + } + else { + printChar(begin, false); + } + } } #endif int ServiceInterfaceBuffer::overflow(int c) { - if(errStream and this->isActive) { + if(not buffered and this->isActive) { if (c != Traits::eof()) { - printChar(reinterpret_cast(&c), true); + if(errStream) { + printChar(reinterpret_cast(&c), true); + } + else { + printChar(reinterpret_cast(&c), false); + } } return 0; } @@ -53,16 +66,17 @@ int ServiceInterfaceBuffer::overflow(int c) { } int ServiceInterfaceBuffer::sync(void) { - if(not this->isActive or errStream) { - if(not errStream) { + if(not this->isActive) { + if(not buffered) { setp(buf, buf + BUF_SIZE - 1); } return 0; } - auto preamble = getPreamble(); + size_t preambleSize = 0; + auto preamble = getPreamble(&preambleSize); // Write logMessage and time - this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); + this->putChars(preamble.c_str(), preamble.c_str() + preambleSize); // Handle output this->putChars(pbase(), pptr()); // This tells that buffer is empty again @@ -71,17 +85,34 @@ int ServiceInterfaceBuffer::sync(void) { } -std::string ServiceInterfaceBuffer::getPreamble() { +std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - std::string preamble; + //preamble.clear(); + //std::string preamble; + size_t currentSize = 0; if(addCrToPreamble) { - preamble += "\r"; + preamble[0] = '\r'; + currentSize += 1; } - preamble += logMessage + ": | " + zero_padded(loggerTime.hour, 2) - + ":" + zero_padded(loggerTime.minute, 2) + ":" - + zero_padded(loggerTime.second, 2) + "." - + zero_padded(loggerTime.usecond/1000, 3) + " | "; + logMessage.copy(preamble.data() + 1, logMessage.size()); + currentSize += logMessage.size(); + preamble[++currentSize] = ':'; + preamble[++currentSize] = ' '; + preamble[++currentSize] = '|'; + zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) + //preamble.c_str() + 1 = logMessage; +// +// + ": | " + zero_padded(loggerTime.hour, 2) +// + ":" + zero_padded(loggerTime.minute, 2) + ":" +// + zero_padded(loggerTime.second, 2) + "." +// + zero_padded(loggerTime.usecond/1000, 3) + " | "; + currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; + preamble[currentSize] = '\0'; + printf("%s", preamble.c_str()); + uint8_t debugArray[96]; + memcpy(debugArray, preamble.data(), currentSize); + *preambleSize = currentSize; return preamble; } diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 74facafe0..ab5d8c901 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -19,8 +19,8 @@ class ServiceInterfaceBuffer: public std::streambuf { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string setMessage, bool errStream, - bool addCrToPreamble, uint16_t port); + ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, + bool buffered, bool errStream, uint16_t port); protected: bool isActive; @@ -36,11 +36,13 @@ protected: private: //! For additional message information std::string logMessage; + std::string preamble; // For EOF detection typedef std::char_traits Traits; //! This is useful for some terminal programs which do not have //! implicit carriage return with newline characters. bool addCrToPreamble; + bool buffered; //! This specifies to print to stderr and work in unbuffered mode. bool errStream; @@ -51,7 +53,7 @@ private: //! In this function, the characters are parsed. void putChars(char const* begin, char const* end); - std::string getPreamble(); + std::string getPreamble(size_t * preambleSize = nullptr); /** * This helper function returns the zero padded string version of a number. diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index d9bc980a7..bef8136e1 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -1,15 +1,33 @@ #include ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, - bool errStream, bool addCrToPreamble, uint16_t port) : - std::ostream(&streambuf), - streambuf(setMessage, errStream, addCrToPreamble, port) { + bool addCrToPreamble, bool buffered, bool errStream, uint16_t port) : + std::ostream(&buf), + buf(setMessage, addCrToPreamble, buffered, errStream, port) { } void ServiceInterfaceStream::setActive( bool myActive) { - this->streambuf.isActive = myActive; + this->buf.isActive = myActive; } std::string ServiceInterfaceStream::getPreamble() { - return streambuf.getPreamble(); + return buf.getPreamble(); +} + +void ServiceInterfaceStream::print(std::string error, + bool withPreamble, bool withNewline, bool flush) { + if(not buffered and withPreamble) { + *this << getPreamble() << error; + } + else { + *this << error; + } + + if(withNewline) { + *this << "\n"; + } + // if mode is non-buffered, no need to flush. + if(flush and buffered) { + this->flush(); + } } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index c44fe03a0..9b8b5b6ed 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -5,36 +5,28 @@ #include #include -/* Unfortunately, there must be a forward declaration of the log front end - * (MUST be defined in main), to let the system know where to write to. - * The ServiceInterfaceStream instances, which are declared below and - * can instantaited somewhere else can be passed to these front ends by passing - * their underlying buffers with .rdbuf() */ -namespace sif { -extern std::ostream debug; -extern std::ostream info; -extern std::ostream warning; -extern std::ostream error; -} - - +/** + * Generic service interface stream which can be used like std::cout or + * std::cerr but has additional capability. Add preamble and timestamp + * to output. Can be run in buffered or unbuffered mode. + */ class ServiceInterfaceStream : public std::ostream { protected: - ServiceInterfaceBuffer streambuf; + ServiceInterfaceBuffer buf; public: /** * This constructor is used by specifying the preamble message. * Optionally, the output can be directed to stderr and a CR character * can be prepended to the preamble. - * @param set_message - * @param errStream - * @param addCrToPreamble - * @param port + * @param setMessage message of preamble. + * @param addCrToPreamble Useful for applications like Puttty. + * @param buffered specify whether to use buffered mode. + * @param errStream specify which output stream to use (stderr or stdout). */ ServiceInterfaceStream(std::string setMessage, - bool errStream = false, bool addCrToPreamble = false, - uint16_t port = 1234); + bool addCrToPreamble = false, bool buffered = true, + bool errStream = false, uint16_t port = 1234); //! An inactive stream will not print anything. void setActive( bool ); @@ -45,15 +37,24 @@ public: * @return Preamle consisting of log message and timestamp. */ std::string getPreamble(); + + /** + * This prints an error with a preamble. Useful if using the unbuffered + * mode. Flushes in default mode (prints immediately). + */ + void print(std::string error, bool withPreamble = true, + bool withNewline = true, bool flush = true); + + bool buffered = false; }; -// Forward declaration of interface streams. These are needed so the public -// functions can be used by including this header +// Forward declaration of interface streams. These should be instantiated in +// main. They can then be used like std::cout or std::cerr. namespace sif { -extern ServiceInterfaceStream debugStream; -extern ServiceInterfaceStream infoStream; -extern ServiceInterfaceStream warningStream; -extern ServiceInterfaceStream errorStream; +extern ServiceInterfaceStream debug; +extern ServiceInterfaceStream info; +extern ServiceInterfaceStream warning; +extern ServiceInterfaceStream error; } #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ From 966c9c3993df460de712823a43c5fef04213dd53 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 14:22:04 +0200 Subject: [PATCH 06/12] buffer changes --- serviceinterface/ServiceInterfaceBuffer.cpp | 52 ++++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 321b1d3ca..3c365f177 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -95,24 +95,40 @@ std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { preamble[0] = '\r'; currentSize += 1; } - logMessage.copy(preamble.data() + 1, logMessage.size()); - currentSize += logMessage.size(); - preamble[++currentSize] = ':'; - preamble[++currentSize] = ' '; - preamble[++currentSize] = '|'; - zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) - //preamble.c_str() + 1 = logMessage; -// -// + ": | " + zero_padded(loggerTime.hour, 2) -// + ":" + zero_padded(loggerTime.minute, 2) + ":" -// + zero_padded(loggerTime.second, 2) + "." -// + zero_padded(loggerTime.usecond/1000, 3) + " | "; - currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; - preamble[currentSize] = '\0'; - printf("%s", preamble.c_str()); - uint8_t debugArray[96]; - memcpy(debugArray, preamble.data(), currentSize); - *preambleSize = currentSize; + int32_t charCount = sprintf(preamble.data() + currentSize, + "%s: | %lu:%02lu:%02lu.%03lu | ", + this->logMessage.c_str(), (unsigned long) loggerTime.hour, + (unsigned long) loggerTime.minute, + (unsigned long) loggerTime.second, + (unsigned long) loggerTime.usecond /1000); + if(charCount < 0) { + printf("ServiceInterfaceBuffer: Failure parsing preamble"); + return ""; + } + currentSize += charCount; +// size_t currentSize = 0; +// if(addCrToPreamble) { +// preamble[0] = '\r'; +// currentSize += 1; +// } +// logMessage.copy(preamble.data() + 1, logMessage.size()); +// currentSize += logMessage.size(); +// preamble[++currentSize] = ':'; +// preamble[++currentSize] = ' '; +// preamble[++currentSize] = '|'; +// zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) +// //preamble.c_str() + 1 = logMessage; +//// +//// + ": | " + zero_padded(loggerTime.hour, 2) +//// + ":" + zero_padded(loggerTime.minute, 2) + ":" +//// + zero_padded(loggerTime.second, 2) + "." +//// + zero_padded(loggerTime.usecond/1000, 3) + " | "; +// currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; +// preamble[currentSize] = '\0'; +// printf("%s", preamble.c_str()); +// uint8_t debugArray[96]; +// memcpy(debugArray, preamble.data(), currentSize); +// *preambleSize = currentSize; return preamble; } From 1cb241ca0cb3ab729b4bf67167a3e36f5dc2bcb3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 17:30:09 +0200 Subject: [PATCH 07/12] zero padded not using dyn mem alloc now --- serviceinterface/ServiceInterfaceBuffer.h | 31 ++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index ab5d8c901..a032691ce 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -1,6 +1,7 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ +#include #include #include #include @@ -58,21 +59,33 @@ private: /** * This helper function returns the zero padded string version of a number. * The type is deduced automatically. + * TODO: This uses dynamic memory allocation, so we should provide + * a custom streambuf class to use it (which takes maxSize as argument) + * Then we would propably * @tparam T * @param num * @param width * @return */ template - std::string zero_padded(const T& num, uint8_t width) { - std::ostringstream string_to_pad; - string_to_pad << std::setw(width) << std::setfill('0') << num; - std::string result = string_to_pad.str(); - if (result.length() > width) - { - result.erase(0, result.length() - width); - } - return result; + ReturnValue_t zeroPadded(std::string stringToFill, const T& num, + uint8_t width) { + auto numString = std::to_string(num); + uint8_t i = 0; + for(i = 0; i < width; i++) { + stringToFill[i] = '0'; + } + numString.copy(stringToFill.data() + i, numString.size()); +// std::streambuf streambuf; +// std::ostringstream string_to_pad; +// string_to_pad << std::setw(width) << std::setfill('0') << num; +// std::string result = string_to_pad.str(); +// if (result.length() > width) +// { +// result.erase(0, result.length() - width); +// } +// return result; + //std::string dest = std::string( number_of_zeros, '0').append( original_string); } }; From d466921aa0f5ac1adc8fe8b95f83d8b518eb7653 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 17:58:22 +0200 Subject: [PATCH 08/12] some more experiments --- serviceinterface/ServiceInterfaceBuffer.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 3c365f177..7cf75a36f 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -75,6 +75,8 @@ int ServiceInterfaceBuffer::sync(void) { size_t preambleSize = 0; auto preamble = getPreamble(&preambleSize); + uint8_t debugArray[96]; + memcpy(debugArray, preamble.data(), preambleSize); // Write logMessage and time this->putChars(preamble.c_str(), preamble.c_str() + preambleSize); // Handle output @@ -124,12 +126,11 @@ std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { //// + zero_padded(loggerTime.second, 2) + "." //// + zero_padded(loggerTime.usecond/1000, 3) + " | "; // currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; -// preamble[currentSize] = '\0'; -// printf("%s", preamble.c_str()); -// uint8_t debugArray[96]; -// memcpy(debugArray, preamble.data(), currentSize); -// *preambleSize = currentSize; - return preamble; + preamble[++currentSize] = '\0'; + uint8_t debugArray[96]; + memcpy(debugArray, preamble.data(), currentSize); + *preambleSize = currentSize; + return std::move(preamble); } From c0808e71d99324fd40082bbbbb16d4cbbff9a7ab Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:07:04 +0200 Subject: [PATCH 09/12] no dyn memory allocation, print seems to work --- objectmanager/ObjectManagerIF.h | 1 - serviceinterface/ServiceInterfaceBuffer.cpp | 48 +++++++-------------- serviceinterface/ServiceInterfaceBuffer.h | 18 +------- 3 files changed, 17 insertions(+), 50 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index aca24a24a..830aa4006 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -9,7 +9,6 @@ #define OBJECTMANAGERIF_H_ #include -#include #include #include diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 7cf75a36f..30149ce0b 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include // to be implemented by bsp extern "C" void printChar(const char*, bool errStream); @@ -17,6 +18,7 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, setp( buf, buf + BUF_SIZE ); } preamble.reserve(96); + preamble.resize(96); } void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { @@ -78,7 +80,7 @@ int ServiceInterfaceBuffer::sync(void) { uint8_t debugArray[96]; memcpy(debugArray, preamble.data(), preambleSize); // Write logMessage and time - this->putChars(preamble.c_str(), preamble.c_str() + preambleSize); + this->putChars(preamble.data(), preamble.data() + preambleSize); // Handle output this->putChars(pbase(), pptr()); // This tells that buffer is empty again @@ -90,47 +92,29 @@ int ServiceInterfaceBuffer::sync(void) { std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - //preamble.clear(); - //std::string preamble; + std::string preamble (96, 0); size_t currentSize = 0; + char* parsePosition = &preamble[0]; if(addCrToPreamble) { preamble[0] = '\r'; currentSize += 1; + parsePosition += 1; } - int32_t charCount = sprintf(preamble.data() + currentSize, - "%s: | %lu:%02lu:%02lu.%03lu | ", - this->logMessage.c_str(), (unsigned long) loggerTime.hour, - (unsigned long) loggerTime.minute, - (unsigned long) loggerTime.second, - (unsigned long) loggerTime.usecond /1000); + int32_t charCount = sprintf(parsePosition, + "%s: | %02" SCNu32 ":%02" SCNu32 ":%02" SCNu32 ".%03" SCNu32 " | ", + this->logMessage.c_str(), loggerTime.hour, + loggerTime.minute, + loggerTime.second, + loggerTime.usecond /1000); if(charCount < 0) { printf("ServiceInterfaceBuffer: Failure parsing preamble"); return ""; } currentSize += charCount; -// size_t currentSize = 0; -// if(addCrToPreamble) { -// preamble[0] = '\r'; -// currentSize += 1; -// } -// logMessage.copy(preamble.data() + 1, logMessage.size()); -// currentSize += logMessage.size(); -// preamble[++currentSize] = ':'; -// preamble[++currentSize] = ' '; -// preamble[++currentSize] = '|'; -// zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) -// //preamble.c_str() + 1 = logMessage; -//// -//// + ": | " + zero_padded(loggerTime.hour, 2) -//// + ":" + zero_padded(loggerTime.minute, 2) + ":" -//// + zero_padded(loggerTime.second, 2) + "." -//// + zero_padded(loggerTime.usecond/1000, 3) + " | "; -// currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; - preamble[++currentSize] = '\0'; - uint8_t debugArray[96]; - memcpy(debugArray, preamble.data(), currentSize); - *preambleSize = currentSize; - return std::move(preamble); + if(preambleSize != nullptr) { + *preambleSize = currentSize; + } + return preamble; } diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index a032691ce..9a4ae4798 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -76,29 +76,13 @@ private: stringToFill[i] = '0'; } numString.copy(stringToFill.data() + i, numString.size()); -// std::streambuf streambuf; -// std::ostringstream string_to_pad; -// string_to_pad << std::setw(width) << std::setfill('0') << num; -// std::string result = string_to_pad.str(); -// if (result.length() > width) -// { -// result.erase(0, result.length() - width); -// } -// return result; - //std::string dest = std::string( number_of_zeros, '0').append( original_string); + return HasReturnvaluesIF::RETURN_OK; } }; #endif - - - - - - - #ifdef UT699 class ServiceInterfaceBuffer: public std::basic_streambuf > { From 3a573c1b4c460cb19163d8bb9f319b501657f1e8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:37:33 +0200 Subject: [PATCH 10/12] no run-time dyn memory allocation now --- serviceinterface/ServiceInterfaceBuffer.cpp | 8 +++++- serviceinterface/ServiceInterfaceBuffer.h | 28 ++---------------- serviceinterface/ServiceInterfaceStream.cpp | 13 ++++----- serviceinterface/ServiceInterfaceStream.h | 32 ++++++++++----------- 4 files changed, 31 insertions(+), 50 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 30149ce0b..f1332637c 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -68,12 +68,15 @@ int ServiceInterfaceBuffer::overflow(int c) { } int ServiceInterfaceBuffer::sync(void) { - if(not this->isActive) { + if(not this->isActive and not buffered) { if(not buffered) { setp(buf, buf + BUF_SIZE - 1); } return 0; } + if(not buffered) { + return 0; + } size_t preambleSize = 0; auto preamble = getPreamble(&preambleSize); @@ -88,6 +91,9 @@ int ServiceInterfaceBuffer::sync(void) { return 0; } +bool ServiceInterfaceBuffer::isBuffered() const { + return buffered; +} std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 9a4ae4798..00a8e74a3 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -34,6 +34,7 @@ protected: //! for example when std::endl is put to stream. int sync(void) override; + bool isBuffered() const; private: //! For additional message information std::string logMessage; @@ -43,10 +44,10 @@ private: //! This is useful for some terminal programs which do not have //! implicit carriage return with newline characters. bool addCrToPreamble; - bool buffered; + //! This specifies to print to stderr and work in unbuffered mode. bool errStream; - + bool buffered; // Work in buffer mode. It is also possible to work without buffer. static size_t const BUF_SIZE = 128; char buf[BUF_SIZE]; @@ -55,29 +56,6 @@ private: void putChars(char const* begin, char const* end); std::string getPreamble(size_t * preambleSize = nullptr); - - /** - * This helper function returns the zero padded string version of a number. - * The type is deduced automatically. - * TODO: This uses dynamic memory allocation, so we should provide - * a custom streambuf class to use it (which takes maxSize as argument) - * Then we would propably - * @tparam T - * @param num - * @param width - * @return - */ - template - ReturnValue_t zeroPadded(std::string stringToFill, const T& num, - uint8_t width) { - auto numString = std::to_string(num); - uint8_t i = 0; - for(i = 0; i < width; i++) { - stringToFill[i] = '0'; - } - numString.copy(stringToFill.data() + i, numString.size()); - return HasReturnvaluesIF::RETURN_OK; - } }; #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index bef8136e1..76481ed12 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -2,21 +2,20 @@ ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, bool addCrToPreamble, bool buffered, bool errStream, uint16_t port) : - std::ostream(&buf), - buf(setMessage, addCrToPreamble, buffered, errStream, port) { -} + std::ostream(&streambuf), + streambuf(setMessage, addCrToPreamble, buffered, errStream, port) {} void ServiceInterfaceStream::setActive( bool myActive) { - this->buf.isActive = myActive; + this->streambuf.isActive = myActive; } std::string ServiceInterfaceStream::getPreamble() { - return buf.getPreamble(); + return streambuf.getPreamble(); } void ServiceInterfaceStream::print(std::string error, bool withPreamble, bool withNewline, bool flush) { - if(not buffered and withPreamble) { + if(not streambuf.isBuffered() and withPreamble) { *this << getPreamble() << error; } else { @@ -27,7 +26,7 @@ void ServiceInterfaceStream::print(std::string error, *this << "\n"; } // if mode is non-buffered, no need to flush. - if(flush and buffered) { + if(flush and streambuf.isBuffered()) { this->flush(); } } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index 9b8b5b6ed..9e19c228c 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -10,25 +10,22 @@ * std::cerr but has additional capability. Add preamble and timestamp * to output. Can be run in buffered or unbuffered mode. */ -class ServiceInterfaceStream : - public std::ostream { -protected: - ServiceInterfaceBuffer buf; +class ServiceInterfaceStream : public std::ostream { public: - /** - * This constructor is used by specifying the preamble message. - * Optionally, the output can be directed to stderr and a CR character - * can be prepended to the preamble. - * @param setMessage message of preamble. - * @param addCrToPreamble Useful for applications like Puttty. - * @param buffered specify whether to use buffered mode. - * @param errStream specify which output stream to use (stderr or stdout). - */ - ServiceInterfaceStream(std::string setMessage, - bool addCrToPreamble = false, bool buffered = true, + /** + * This constructor is used by specifying the preamble message. + * Optionally, the output can be directed to stderr and a CR character + * can be prepended to the preamble. + * @param setMessage message of preamble. + * @param addCrToPreamble Useful for applications like Puttty. + * @param buffered specify whether to use buffered mode. + * @param errStream specify which output stream to use (stderr or stdout). + */ + ServiceInterfaceStream(std::string setMessage, + bool addCrToPreamble = false, bool buffered = true, bool errStream = false, uint16_t port = 1234); - //! An inactive stream will not print anything. + //! An inactive stream will not print anything. void setActive( bool ); /** @@ -45,7 +42,8 @@ public: void print(std::string error, bool withPreamble = true, bool withNewline = true, bool flush = true); - bool buffered = false; +protected: + ServiceInterfaceBuffer streambuf; }; // Forward declaration of interface streams. These should be instantiated in From 7014833c1c89938d0475e88a7a57b628933051e5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:50:56 +0200 Subject: [PATCH 11/12] improvements and fixes --- serviceinterface/ServiceInterfaceBuffer.cpp | 15 ++++++++------- serviceinterface/ServiceInterfaceBuffer.h | 9 +++++++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index f1332637c..5c80862c2 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -17,8 +17,8 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, // Set pointers if the stream is buffered. setp( buf, buf + BUF_SIZE ); } - preamble.reserve(96); - preamble.resize(96); + preamble.reserve(MAX_PREAMBLE_SIZE); + preamble.resize(MAX_PREAMBLE_SIZE); } void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { @@ -36,7 +36,6 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { else { printChar(begin, false); } - } } @@ -80,8 +79,6 @@ int ServiceInterfaceBuffer::sync(void) { size_t preambleSize = 0; auto preamble = getPreamble(&preambleSize); - uint8_t debugArray[96]; - memcpy(debugArray, preamble.data(), preambleSize); // Write logMessage and time this->putChars(preamble.data(), preamble.data() + preambleSize); // Handle output @@ -98,7 +95,6 @@ bool ServiceInterfaceBuffer::isBuffered() const { std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - std::string preamble (96, 0); size_t currentSize = 0; char* parsePosition = &preamble[0]; if(addCrToPreamble) { @@ -113,7 +109,12 @@ std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { loggerTime.second, loggerTime.usecond /1000); if(charCount < 0) { - printf("ServiceInterfaceBuffer: Failure parsing preamble"); + printf("ServiceInterfaceBuffer: Failure parsing preamble\r\n"); + return ""; + } + if(charCount > MAX_PREAMBLE_SIZE) { + printf("ServiceInterfaceBuffer: Char count too large for maximum " + "preamble size"); return ""; } currentSize += charCount; diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 00a8e74a3..39ea25c2d 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -20,6 +20,8 @@ class ServiceInterfaceBuffer: public std::streambuf { friend class ServiceInterfaceStream; public: + static constexpr uint8_t MAX_PREAMBLE_SIZE = 40; + ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, bool buffered, bool errStream, uint16_t port); @@ -41,14 +43,17 @@ private: std::string preamble; // For EOF detection typedef std::char_traits Traits; + //! This is useful for some terminal programs which do not have //! implicit carriage return with newline characters. bool addCrToPreamble; + //! Specifies whether the stream operates in buffered or unbuffered mode. + bool buffered; //! This specifies to print to stderr and work in unbuffered mode. bool errStream; - bool buffered; - // Work in buffer mode. It is also possible to work without buffer. + + //! Needed for buffered mode. static size_t const BUF_SIZE = 128; char buf[BUF_SIZE]; From 639b517edaffc63094870cd1bcdcdb9bed9229ca Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:57:25 +0200 Subject: [PATCH 12/12] removed unnecessary change --- osal/FreeRTOS/FixedTimeslotTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 549ffbf17..fb3c3b03e 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -68,7 +68,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, } sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst\r" << std::endl; + " not found, not adding it to pst" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; }