pikotools/src/log/log.cpp

735 lines
9.5 KiB
C++

/*
* This file is a part of PikoTools
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* 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:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 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 OWNER 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 <ctime>
#include <string.h>
#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 )
{
buffer->size();
}
return 0;
}
void Log::reserve(size_t len)
{
if( buffer )
{
buffer->reserve(len);
}
}
size_t Log::capacity() const
{
if( buffer )
{
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<blob_len ; ++a, ++i)
{
if( blob[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