/* * This file is a part of PikoTools * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ifndef headerfile_picotools_log_log #define headerfile_picotools_log_log #include #include #include "textstream/textstream.h" #include "filelog.h" namespace pt { class Log : public Stream { public: /* log1 - the first level log2 log3 log4 - the last level (debug level) logend - the end of a line logsave - current log buffer is saved and cleared */ enum Manipulators { log1, log2, log3, log4, logend, logsave, }; Log(); ~Log(); bool is_char_stream() const; bool is_wchar_stream() const; void clear(); bool empty() const; size_t size() const; void reserve(size_t len); size_t capacity() const; void to_str(std::string & str, bool clear_string = true) const; void to_str(std::wstring & str, bool clear_string = true) const; std::string to_str() const; std::wstring to_wstr() const; char get_char(size_t index) const; wchar_t get_wchar(size_t index) const; Log & operator<<(const char * s); Log & operator<<(const std::string & s); Log & operator<<(const wchar_t * s); Log & operator<<(const std::wstring & s); Log & operator<<(char val); Log & operator<<(unsigned char val); Log & operator<<(wchar_t val); Log & operator<<(bool val); Log & operator<<(short val); Log & operator<<(int s); Log & operator<<(long s); Log & operator<<(long long s); Log & operator<<(unsigned short val); Log & operator<<(unsigned int val); Log & operator<<(unsigned long val); Log & operator<<(unsigned long long val); Log & operator<<(float val); Log & operator<<(double s); Log & operator<<(long double val); Log & operator<<(const void * s); Log & operator<<(const Stream & stream); Log & operator<<(const Space & space); Log & operator<<(const Date & date); #ifdef PT_HAS_MORM_LIBRARY virtual Log & operator<<(morm::Model & model); #endif template Log & operator<<(const TextStreamBase & arg); Log & write(const char * buf, size_t len); Log & write(const wchar_t * buf, size_t len); /* * methods specific to Log class * */ virtual Log & operator<<(Manipulators m); virtual void set_log_buffer(WTextStream * buffer); virtual WTextStream * get_log_buffer(); void set_file_log(FileLog * file_log); FileLog * get_file_log(); void set_max_buffer_length(size_t max_buffer_length); size_t get_max_buffer_length(); virtual Log & int_min_width(size_t min_width); virtual Log & put_string(const std::string & value, size_t max_size); virtual Log & put_string(const std::wstring & value, size_t max_size); virtual Log & put_binary_blob(const char * blob, size_t blob_len); virtual Log & put_binary_blob(const std::string & blob); /* * put multiline message * first and last new characters are trimmed * at the beginning of each line a prefix is inserted */ virtual Log & put_multiline(const char * prefix, const char * msg); virtual Log & put_multiline(const wchar_t * prefix, const wchar_t * msg); virtual Log & put_multiline(const char * prefix, const std::string & msg); virtual Log & put_multiline(const wchar_t * prefix, const std::wstring & msg); virtual Log & put_multiline(const std::string & prefix, const std::string & msg); virtual Log & put_multiline(const std::wstring & prefix, const std::wstring & msg); protected: // buffer for the log WTextStream * buffer; // file logger FileLog * file_log; // current level set by a modifier (e.g. log << log3) int current_level; // if there is logend modifier used and the buffer exceeds max_buffer_length then // the buffer is passed to file_log size_t max_buffer_length; char get_hex_digit(unsigned char c); void to_hex(char * buf, unsigned char c); template Log & log_string_generic(const StringType & value, size_t max_size); virtual bool can_put_log(); virtual void save_log(); virtual void save_log_and_clear(); template void put_multiline_generic(const CharType * prefix, const CharType * msg); }; template Log & Log::operator<<(const TextStreamBase & arg) { if( can_put_log() ) { (*buffer) << arg; } return *this; } template Log & Log::log_string_generic(const StringType & value, size_t max_size) { std::size_t min_size = value.size() < max_size ? value.size() : max_size; if( can_put_log() ) { for(size_t i=0 ; i < min_size ; ++i) { if( value[i] < 32 ) (*buffer) << '.'; // unprintable characters else (*buffer) << value[i]; } } return *this; } template void Log::put_multiline_generic(const CharType * prefix, const CharType * msg) { bool put_prefix = true; bool was_new_line = false; bool was_something_printed = false; while( *msg ) { if( static_cast(*msg) == static_cast('\n') ) { was_new_line = true; put_prefix = true; } else { if( was_new_line ) { if( was_something_printed ) { operator<<(logend); } was_new_line = false; } if( put_prefix ) { operator<<(prefix); put_prefix = false; } operator<<(*msg); was_something_printed = true; } msg += 1; } if( was_something_printed ) { operator<<(logend); } } } // namespace #endif