Important Update:

- LogCore:
  - Implement ReadLogLevel() & ReadLogOutput() methods
    Standardised handling of logging parameters
  - Split Log/Output in config to: Log/Output & Log/Options
  - LogOutput (Show) param: first nibble = format, second nibble = options
  - Replace Format constants (OUT_XXX) with enum ELogOutput
  - Add loRaw format - raw untouched output
  - Replace OUT_CRLF with OUT_NOCRLF - Replace \r\n with "."
  - Improved Binary output method
  - Simplified Log->Output() method
- FunctionCore, ApplicationCore:
  - Replace reading of LogConfig with new methods in LogCore
This commit is contained in:
Charl Wentzel
2018-11-25 18:24:36 +02:00
parent bdff82f9c8
commit d770d9f6cb
5 changed files with 129 additions and 127 deletions

View File

@@ -33,7 +33,7 @@ CApplication::CApplication( EDebugLevel pLogLevel )
// Create output logger
Log = new CLogCore( stdout );
LogLevel = pLogLevel;
LogOutput = OUT_NORMAL;
LogOutput = loNormal;
// Create Configuration
DataTree = new CDataMember();
@@ -206,52 +206,18 @@ bool CApplication::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay )
bool CApplication::InitApplication()
{
CDataMember * CoreConfig;
CDataMember * ItemConfig;
CDataMember * LogConfig;
CDataMember * SelectConfig;
EDebugLevel pLogLevel;
int pLogOutput;
char * TempStr;
// Get Core definition
CoreConfig = Definition->GetChild( "Core", true );
// Get debug level
pLogLevel = dlNone;
TempStr = (char*)CoreConfig->GetChStr( "Log/Level", "Medium", true );
if (TempStr)
{
if (!strcasecmp( TempStr, "Low" ))
pLogLevel = dlLow;
else if (!strcasecmp( TempStr, "Medium" ))
pLogLevel = dlMedium;
else if (!strcasecmp( TempStr, "High" ))
pLogLevel = dlHigh;
}
// Set debug output
pLogOutput = 0;
ItemConfig = CoreConfig->GetChild( "Log/Output[0]", true ); // Create first element if not exist
while (ItemConfig)
{
if ((TempStr = (char*)ItemConfig->GetStr( "Normal" ))) // Set default value "Normal" if not set
{
if (!strcasecmp( TempStr, "Normal")) // Normal ASCII -> Unless "AsIs", print special chars as "."
pLogOutput |= OUT_NORMAL;
else if (!strcasecmp( TempStr, "Bin")) // Print as Binary value ('1' and '0')
pLogOutput |= OUT_BIN;
else if (!strcasecmp( TempStr, "Hex")) // Print as Hexadecimal value (0-9,A-F)
pLogOutput |= OUT_HEX;
else if (!strcasecmp( TempStr, "Count")) // Print number of characters
pLogOutput |= OUT_COUNT;
else if (!strcasecmp( TempStr, "AsIs")) // Use with "Normal" -> Do not print special chars as "."
pLogOutput |= OUT_ASIS;
else if (!strcasecmp( TempStr, "CRLF")) // Add \r\n at end of line if not present
pLogOutput |= OUT_CRLF;
else
pLogOutput |= OUT_NORMAL;
}
ItemConfig = ItemConfig->GetNextPeer();
}
// Configure Logging/Debugging
LogConfig = CoreConfig->GetChild( "Log", true );
pLogLevel = Log->ReadLogLevel( LogConfig );
pLogOutput = Log->ReadLogOutput( LogConfig );
SetLogParam( pLogLevel, pLogOutput );
// Configure Selector

View File

@@ -117,8 +117,6 @@ CDataMember::~CDataMember()
// Destroy member
if (Name)
free( Name );
if (Value)
free( Value );
}
//---------------------------------------------------------------------------
@@ -356,9 +354,11 @@ bool CDataMember::SetValuePtr( EDataType pType, const char * pValue, int pLen )
bool CDataMember::SetValue( EDataType pType, const char * pValue, int pLen )
{
// Clear & Update Type
Clear();
Type = pType;
// Set new primitive value
if ((pType == jtString) || (pType == jtFloat) || (pType == jtInt) || (pType == jtBool))
{
Len = (pLen == -1)? strlen(pValue) : pLen;

View File

@@ -44,7 +44,7 @@ CFunctionCore::CFunctionCore( const char * pName, const char * pType ) : Type( p
// Logging
Log = Application->Log;
LogLevel = dlNone;
LogOutput = OUT_NORMAL;
LogOutput = loNormal;
// Stored output
StoredOutput = NULL;
@@ -102,53 +102,19 @@ CFunctionCore::~CFunctionCore()
bool CFunctionCore::Init( CDataMember * FunctionConfig )
{
// Load configuration
CDataMember * ItemConfig;
CDataMember * LogConfig;
CDataMember * ChannelConfig;
EDebugLevel pLogLevel;
int pLogOutput;
char * TempStr;
// Validate
if (!FunctionConfig )
return false;
// Get debug level
pLogLevel = dlNone;
TempStr = (char*)FunctionConfig->GetChStr( "Log/Level", "Medium", true );
if (TempStr)
{
if (!strcasecmp( TempStr, "Low" ))
pLogLevel = dlLow;
else if (!strcasecmp( TempStr, "Medium" ))
pLogLevel = dlMedium;
else if (!strcasecmp( TempStr, "High" ))
pLogLevel = dlHigh;
}
// Set debug output
pLogOutput = 0;
ItemConfig = FunctionConfig->GetChild( "Log/Output[0]", true ); // Create first element if not exist
while (ItemConfig)
{
if ((TempStr = (char*)ItemConfig->GetStr( "Normal" ))) // Set default value "Normal" if not set
{
if (!strcasecmp( TempStr, "Normal")) // Normal ASCII -> Unless "AsIs", print special chars as "."
pLogOutput |= OUT_NORMAL;
else if (!strcasecmp( TempStr, "Bin")) // Print as Binary value ('1' and '0')
pLogOutput |= OUT_BIN;
else if (!strcasecmp( TempStr, "Hex")) // Print as Hexadecimal value (0-9,A-F)
pLogOutput |= OUT_HEX;
else if (!strcasecmp( TempStr, "Count")) // Print number of characters
pLogOutput |= OUT_COUNT;
else if (!strcasecmp( TempStr, "AsIs")) // Use with "Normal" -> Do not print special chars as "."
pLogOutput |= OUT_ASIS;
else if (!strcasecmp( TempStr, "CRLF")) // Add \r\n at end of line if not present
pLogOutput |= OUT_CRLF;
else
pLogOutput |= OUT_NORMAL;
}
ItemConfig = ItemConfig->GetNextPeer();
}
// Configure Logging/Debugging
LogConfig = FunctionConfig->GetChild( "Log", true );
pLogLevel = Log->ReadLogLevel( LogConfig );
pLogOutput = Log->ReadLogOutput( LogConfig );
SetLogParam( pLogLevel, pLogOutput );
// Load Channels

View File

@@ -16,7 +16,9 @@
//---------------------------------------------------------------------------
// Global vars
char LogStr[1000]; // Temporary var to create log messages, globally available to save on memory operations
char LogStr[1000]; // Temporary var to create log messages, globally available to save on memory operations
const char * LogOutputName[] = { "None", "Raw", "Normal", "Hex", "Bin" };
//---------------------------------------------------------------------------
@@ -26,6 +28,79 @@ CLogCore::CLogCore( FILE * pOutputFile )
}
//---------------------------------------------------------------------------
EDebugLevel CLogCore::ReadLogLevel( CDataMember * LogConfig )
{
char * TempStr;
EDebugLevel LogLevel;
// Get debug level
LogLevel = dlNone;
TempStr = (char*)LogConfig->GetChStr( "Level", "Medium", true );
if (TempStr)
{
if (!strcasecmp( TempStr, "None" ))
LogLevel = dlNone;
else if (!strcasecmp( TempStr, "Low" ))
LogLevel = dlLow;
else if (!strcasecmp( TempStr, "Medium" ))
LogLevel = dlMedium;
else if (!strcasecmp( TempStr, "High" ))
LogLevel = dlHigh;
else
LogLevel = dlMedium;
}
return LogLevel;
}
//---------------------------------------------------------------------------
// ls nibble = format, ms nibble = options.
int CLogCore::ReadLogOutput( CDataMember * LogConfig )
{
CDataMember * ItemConfig;
char * TempStr;
ELogOutput LogOutput = loNone;
int LogOutOpt = 0;
// Get Output format
LogOutput = loNone;
TempStr = (char*)LogConfig->GetChStr( "Output", "Normal", true );
if (TempStr)
{
if (!strcasecmp( TempStr, "None" )) // Do not print output (may use option OUT_COUNT)
LogOutput = loNone;
else if (!strcasecmp( TempStr, "Raw" )) // Print all output as is
LogOutput = loRaw;
else if (!strcasecmp( TempStr, "Normal" )) // Print normal, but replace special chars with "."
LogOutput = loNormal;
else if (!strcasecmp( TempStr, "Bin" )) // Print as Binary value ('1' and '0')
LogOutput = loBin;
else if (!strcasecmp( TempStr, "Hex" )) // Print as Hexadecimal value (0-9,A-F)
LogOutput = loHex;
else
LogOutput = loNormal;
}
// Set debug output
ItemConfig = LogConfig->GetChElement( "Options", 0, true );
while (ItemConfig)
{
if ((TempStr = (char*)ItemConfig->GetStr( "Normal" )))
{
if (!strcasecmp( TempStr, "Count" )) // Print number of characters
LogOutOpt |= OUT_COUNT;
else if (!strcasecmp( TempStr, "NoCRLF" )) // With Normal, replace CR/LF with "."
LogOutOpt |= OUT_NOCRLF;
}
ItemConfig = ItemConfig->GetNextPeer();
}
// Combine Output format & options
LogOutOpt = (LogOutput | LogOutOpt)? (LogOutput | LogOutOpt) : loNormal;
return LogOutOpt;
}
//---------------------------------------------------------------------------
bool CLogCore::Message( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const char * Format, ... )
{
va_list ArgPtr;
@@ -53,12 +128,15 @@ bool CLogCore::Message( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const char
}
//---------------------------------------------------------------------------
bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short Show, const char * Buffer, int Len, const char * Format, ... )
bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short OutputFormat, const char * Buffer, int Len, const char * Format, ... )
{
va_list ArgPtr;
int OutFormat = OutputFormat & 0x0F;
bool ShowCount = OutputFormat & OUT_COUNT;
bool NoCrLf = OutputFormat & OUT_NOCRLF;
// Validate values
if (!Buffer || !(Show & (OUT_COUNT | OUT_NORMAL | OUT_HEX | OUT_BIN)))
if (!Buffer || (!OutFormat && !ShowCount))
return false;
// Check debug level
@@ -83,46 +161,39 @@ bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short
}
// Show byte count
if (Show & OUT_COUNT)
if (ShowCount)
{
// Print byte count
fprintf( OutputFile, " [%d] ", Len );
// EOL if only count wanted
if (Show & OUT_COUNT) {
fprintf( OutputFile, "\n" );
}
if (!OutFormat) fprintf( OutputFile, "\n" ); // EOL if only count wanted
}
// Show Normal output
if (Show & OUT_NORMAL)
// Show output
if (OutFormat == loRaw)
{
if (Show & OUT_ASIS) {
// Print entire buffer as is (line feeds included)
fprintf( OutputFile, "%s", Buffer );
}
else {
// Ignore \r\n
for (int i=0; i<Len; i++) {
if ((Buffer[i] < 32) || (Buffer[i] > 126)) {
if ((Show & OUT_CRLF) && ((Buffer[i] == '\r') || (Buffer[i] == '\n')))
fprintf( OutputFile, "%c", Buffer[i] );
else
fprintf( OutputFile, "." );
}
else {
// Print entire buffer as is (line feeds included)
fprintf( OutputFile, "%.*s\n", Len, Buffer );
}
else if (OutFormat == loNormal)
{
// Ignore \r\n
for (int i=0; i<Len; i++) {
if ((Buffer[i] < 32) || (Buffer[i] > 126)) {
if (((Buffer[i] == '\r') || (Buffer[i] == '\n')) && !NoCrLf)
fprintf( OutputFile, "%c", Buffer[i] );
}
else
fprintf( OutputFile, "." );
}
else {
fprintf( OutputFile, "%c", Buffer[i] );
}
}
// Add EOL if not present or ignored
if (!(Show & (OUT_ASIS | OUT_CRLF)) || (Buffer[Len-1] != '\n')) {
if (NoCrLf || (Buffer[Len-1] != '\n')) {
fprintf( OutputFile, "\n" );
}
}
// Show Hex output
if (Show & OUT_HEX)
else if (OutFormat == loHex)
{
// Print Hex values of individual bytes
for (int i=0; i<Len; i++) {
@@ -130,14 +201,13 @@ bool CLogCore::Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short
}
fprintf( OutputFile, "\n" );
}
// Show Binary output
if (Show & OUT_BIN) {
else if (OutFormat == loBin)
{
// Print each byte as 8-bit binary
for (int i=0; i<Len; i++) {
for (int j=0; j<8; j++) {
fprintf( OutputFile, "%d", (bool)((Buffer[i] << j) & 0x80) );
}
fprintf( OutputFile, "%c%c%c%c%c%c%c%c ",
(Buffer[i] & 0x80)?'1':'0', (Buffer[i] & 0x40)?'1':'0', (Buffer[i] & 0x20)?'1':'0', (Buffer[i] & 0x10)?'1':'0',
(Buffer[i] & 0x08)?'1':'0', (Buffer[i] & 0x04)?'1':'0', (Buffer[i] & 0x02)?'1':'0', (Buffer[i] & 0x01)?'1':'0' );
}
fprintf( OutputFile, "\n" );
}

View File

@@ -12,21 +12,18 @@
#include <stdio.h>
// redA Libraries
/* none */
#include "DataTreeCore.h"
//---------------------------------------------------------------------------
// Debug options
// Debug options: LogOutput --> First nibble = output format, second nibble = output options
const short
OUT_COUNT = 1, // Show Length of String
OUT_NORMAL = 2, // Show ASCII output (replace non-printable characters (incl. CR/LF with ".")
OUT_HEX = 4, // Show HEX output
OUT_BIN = 8, // Show BINARY output
OUT_CRLF = 16, // with OUT_NORMAL - do not replace CR/LF with "."
OUT_ASIS = 32; // with OUT_NORMAL - do not replace any non-printable character with "."
OUT_COUNT = 16, // Show Character count
OUT_NOCRLF = 32; // with OUT_NORMAL, show \r\n as "."
//---------------------------------------------------------------------------
typedef enum { loNone = 0, loRaw = 1, loNormal = 2, loHex = 3, loBin = 4 } ELogOutput;
typedef enum { dlNone = 0, dlLow = 1, dlMedium = 2, dlHigh = 3 } EDebugLevel;
//---------------------------------------------------------------------------
@@ -39,8 +36,11 @@ private:
public:
CLogCore( FILE * pOutputFile );
EDebugLevel ReadLogLevel( CDataMember * LogConfig );
int ReadLogOutput( CDataMember * LogConfig );
bool Message( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const char * Format, ... );
bool Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short Show, const char * Buffer, int Len, const char * Format, ... );
bool Output( EDebugLevel DebugLevel, EDebugLevel MsgLevel, const short OutputFormat, const char * Buffer, int Len, const char * Format, ... );
};
//---------------------------------------------------------------------------