/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2008-2018, 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 "log.h" #include #include #include "utf8/utf8.h" namespace Winix { Log::Log() { current_level = 100; // nothing to log (call Init() first) request = 0; max_requests = 1; lines = 0; max_lines = 5000; file_log = nullptr; buffer = nullptr; } Log::~Log() { SaveLogAndClear(); } void Log::SetLogBuffer(TextStream * buffer) { this->buffer = buffer; } void Log::SetFileLog(FileLog * pfile_log) { this->file_log = pfile_log; } FileLog * Log::GetFileLog() { return file_log; } void Log::SetDependency(Log * log) { buffer = log->buffer; file_log = log->file_log; } void Log::Init(int max_requests) { this->max_requests = max_requests; } void Log::PrintDate(const PT::Date & date) { if( file_log ) { (*this) << file_log->get_local_date(date); } else { (*this) << date; } } Log & Log::operator<<(const void * s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const char * s) { if( current_level <= file_log->get_log_level() && buffer && s ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const std::string & s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const std::string * s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << *s; } return *this; } Log & Log::operator<<(const wchar_t * s) { if( current_level <= file_log->get_log_level() && buffer && s ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const std::wstring & s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const std::wstring * s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << *s; } return *this; } Log & Log::operator<<(int s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(long s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(char s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(wchar_t s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(size_t s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(double s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const PT::Space & s) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << s; } return *this; } Log & Log::operator<<(const PT::Date & date) { if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << date; } return *this; } Log & Log::operator<<(LogManipulators m) { switch(m) { case logend: if( current_level <= file_log->get_log_level() && buffer ) { (*buffer) << '\n'; lines += 1; if( file_log->should_save_each_line() ) SaveLogAndClear(); } break; case logsave: SaveLogAndClear(); break; case logendrequest: if( ++request >= max_requests || lines > max_lines ) SaveLogAndClear(); 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; } char Log::GetHEXdigit(unsigned char c) { if( c < 10 ) return c + '0'; return c - 10 + 'A'; } void Log::ToHEX(char * buf, unsigned char c) { buf[0] = GetHEXdigit(c >> 4); buf[1] = GetHEXdigit(c & 0xf); buf[2] = 0; } void Log::LogBinary(const char * blob, size_t blob_len) { size_t i=0; char buf[3]; if( !buffer ) return; while( i < blob_len ) { size_t oldi = i; for(size_t a=0 ; a<16 ; ++a) { if( i < blob_len ) { ToHEX(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; } } void Log::LogBinary(const std::string & blob) { LogBinary(blob.c_str(), blob.size()); } void Log::SystemErr(int err) { (*this) << "errno: " << err; const char * err_msg = strerror(err); if( err_msg ) (*this) << " (" << err_msg << ")"; } void Log::SaveLogAndClear() { SaveLog(); if( buffer ) { buffer->Clear(); } request = 0; lines = 0; } void Log::SaveLog() { if( buffer ) { file_log->save_log(buffer); } } } // namespace Winix