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_ */