/* * 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. * */ #include #include #include "log.h" #include "date/date.h" #include "utf8/utf8.h" #ifdef PT_HAS_MORM_LIBRARY #include "morm.h" #endif namespace pt { Log::Log() { buffer = nullptr; file_log = nullptr; current_level = 4; max_buffer_length = 2 * 1024 * 1024; } Log::~Log() { } bool Log::can_put_log() { return (buffer && file_log && current_level <= file_log->get_log_level()); } bool Log::is_char_stream() const { return false; } bool Log::is_wchar_stream() const { return true; } void Log::clear() { if( buffer ) { buffer->clear(); } } bool Log::empty() const { if( buffer ) { return buffer->empty(); } return true; } size_t Log::size() const { if( buffer ) { return buffer->size(); } return 0; } void Log::reserve(size_t len) { if( buffer ) { buffer->reserve(len); } } size_t Log::capacity() const { if( buffer ) { return buffer->capacity(); } return 0; } void Log::to_str(std::string & str, bool clear_string) const { if( buffer ) { buffer->to_str(str, clear_string); } } void Log::to_str(std::wstring & str, bool clear_string) const { if( buffer ) { buffer->to_str(str, clear_string); } } std::string Log::to_str() const { if( buffer ) { return buffer->to_str(); } return std::string(); } std::wstring Log::to_wstr() const { if( buffer ) { return buffer->to_wstr(); } return std::wstring(); } char Log::get_char(size_t index) const { if( buffer ) { return buffer->get_char(index); } return 0; } wchar_t Log::get_wchar(size_t index) const { if( buffer ) { return buffer->get_wchar(index); } return 0; } Log & Log::operator<<(const char * s) { if( can_put_log() ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const std::string & s) { if( can_put_log() ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const wchar_t * s) { if( can_put_log() ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const std::wstring & s) { if( can_put_log() ) { (*buffer) << s; } return *this; } Log & Log::operator<<(char val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(unsigned char val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(wchar_t val) { if( buffer && file_log && current_level <= file_log->get_log_level() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(bool val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(short val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(int val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(long val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(long long val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(unsigned short val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(unsigned int val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(unsigned long val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(unsigned long long val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(float val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(double s) { if( buffer && file_log && current_level <= file_log->get_log_level() ) { (*buffer) << s; } return *this; } Log & Log::operator<<(long double val) { if( can_put_log() ) { (*buffer) << val; } return *this; } Log & Log::operator<<(const void * s) { if( can_put_log() ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const Stream & stream) { if( can_put_log() ) { (*buffer) << stream; } return *this; } Log & Log::operator<<(const Space & s) { if( can_put_log() ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const Date & date) { if( can_put_log() ) { (*buffer) << date; } return *this; } #ifdef PT_HAS_MORM_LIBRARY Log & Log::operator<<(morm::Model & model) { operator<<(model.to_string()); return *this; } #endif Log & Log::write(const char * buf, size_t len) { if( can_put_log() ) { buffer->write(buf, len); } return *this; } Log & Log::write(const wchar_t * buf, size_t len) { if( can_put_log() ) { buffer->write(buf, len); } return *this; } Log & Log::operator<<(Manipulators m) { switch(m) { case logend: if( can_put_log() ) { (*buffer) << '\n'; if( file_log->should_save_each_line() || buffer->size() > max_buffer_length ) save_log_and_clear(); } break; case logsave: save_log_and_clear(); break; case log1: current_level = 1; break; case log2: current_level = 2; break; case log3: current_level = 3; break; case log4: current_level = 4; break; default: break; } return *this; } void Log::set_log_buffer(WTextStream * buffer) { this->buffer = buffer; } WTextStream * Log::get_log_buffer() { return buffer; } void Log::set_max_buffer_length(size_t max_buffer_length) { this->max_buffer_length = max_buffer_length; } size_t Log::get_max_buffer_length() { return max_buffer_length; } void Log::set_file_log(FileLog * file_log) { this->file_log = file_log; } FileLog * Log::get_file_log() { return file_log; } Log & Log::int_min_width(size_t min_width) { if( buffer ) { buffer->int_min_width(min_width); } return *this; } Log & Log::put_string(const std::string & value, size_t max_size) { return log_string_generic(value, max_size); } Log & Log::put_string(const std::wstring & value, size_t max_size) { return log_string_generic(value, max_size); } char Log::get_hex_digit(unsigned char c) { if( c < 10 ) return c + '0'; return c - 10 + 'A'; } void Log::to_hex(char * buf, unsigned char c) { buf[0] = get_hex_digit(c >> 4); buf[1] = get_hex_digit(c & 0xf); buf[2] = 0; } Log & Log::put_binary_blob(const char * blob, size_t blob_len) { size_t i=0; char buf[3]; if( can_put_log() ) { while( i < blob_len ) { size_t oldi = i; for(size_t a=0 ; a<16 ; ++a) { if( i < blob_len ) { to_hex(buf, blob[i]); (*buffer) << buf << ' '; ++i; } else { (*buffer) << " "; } if( a == 7 ) { if( i < blob_len ) (*buffer) << "- "; else (*buffer) << " "; } } i = oldi; (*buffer) << ' '; for(size_t a=0 ; a<16 && i 31 && blob[i] < 127 ) (*buffer) << blob[i]; else (*buffer) << '.'; } (*this) << logend; } } return *this; } Log & Log::put_binary_blob(const std::string & blob) { return put_binary_blob(blob.c_str(), blob.size()); } void Log::save_log_and_clear() { save_log(); if( buffer ) { buffer->clear(); } } void Log::save_log() { if( file_log && buffer ) { file_log->save_log(buffer); } } Log & Log::put_multiline(const char * prefix, const char * msg) { put_multiline_generic(prefix, msg); return *this; } Log & Log::put_multiline(const wchar_t * prefix, const wchar_t * msg) { put_multiline_generic(prefix, msg); return *this; } Log & Log::put_multiline(const char * prefix, const std::string & msg) { put_multiline_generic(prefix, msg.c_str()); return *this; } Log & Log::put_multiline(const wchar_t * prefix, const std::wstring & msg) { put_multiline_generic(prefix, msg.c_str()); return *this; } Log & Log::put_multiline(const std::string & prefix, const std::string & msg) { put_multiline_generic(prefix.c_str(), msg.c_str()); return *this; } Log & Log::put_multiline(const std::wstring & prefix, const std::wstring & msg) { put_multiline_generic(prefix.c_str(), msg.c_str()); return *this; } } // namespace