203 lines
5.2 KiB
C
203 lines
5.2 KiB
C
#pragma once
|
|
|
|
/**
|
|
\brief Conditional tracing structures
|
|
*/
|
|
struct TraceCondition
|
|
{
|
|
ExpressionParser condition;
|
|
duint steps;
|
|
duint maxSteps;
|
|
|
|
explicit TraceCondition(const String & expression, duint maxCount)
|
|
: condition(expression), steps(0), maxSteps(maxCount) {}
|
|
|
|
bool BreakTrace()
|
|
{
|
|
steps++;
|
|
if(steps >= maxSteps)
|
|
return true;
|
|
duint value;
|
|
return !condition.Calculate(value, valuesignedcalc(), true) || value;
|
|
}
|
|
};
|
|
|
|
struct TextCondition
|
|
{
|
|
ExpressionParser condition;
|
|
String text;
|
|
|
|
explicit TextCondition(const String & expression, const String & text)
|
|
: condition(expression), text(text) {}
|
|
|
|
bool Evaluate(bool defaultValue) const
|
|
{
|
|
duint value;
|
|
if(condition.Calculate(value, valuesignedcalc(), true))
|
|
return !!value;
|
|
return defaultValue;
|
|
}
|
|
};
|
|
|
|
struct TraceState
|
|
{
|
|
bool InitTraceCondition(const String & expression, duint maxSteps)
|
|
{
|
|
delete traceCondition;
|
|
traceCondition = new TraceCondition(expression, maxSteps);
|
|
return traceCondition->condition.IsValidExpression();
|
|
}
|
|
|
|
bool InitLogFile()
|
|
{
|
|
if(logFile.empty())
|
|
return true;
|
|
auto hFile = CreateFileW(logFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
if(hFile == INVALID_HANDLE_VALUE)
|
|
return false;
|
|
logWriter = new BufferedWriter(hFile);
|
|
duint setting;
|
|
if(BridgeSettingGetUint("Misc", "Utf16LogRedirect", &setting))
|
|
writeUtf16 = !!setting;
|
|
return true;
|
|
}
|
|
|
|
void LogWrite(String text)
|
|
{
|
|
if(logWriter)
|
|
{
|
|
if(writeUtf16)
|
|
{
|
|
auto textUtf16 = StringUtils::Utf8ToUtf16(text);
|
|
logWriter->Write(textUtf16.c_str(), textUtf16.size() * 2);
|
|
logWriter->Write(L"\r\n", 4);
|
|
}
|
|
else
|
|
{
|
|
logWriter->Write(text.c_str(), text.size());
|
|
logWriter->Write("\n", 1);
|
|
}
|
|
}
|
|
else
|
|
dprintf_untranslated("%s\n", text.c_str());
|
|
}
|
|
|
|
bool IsActive() const
|
|
{
|
|
return traceCondition != nullptr;
|
|
}
|
|
|
|
bool IsExtended() const
|
|
{
|
|
return logCondition || cmdCondition;
|
|
}
|
|
|
|
bool BreakTrace() const
|
|
{
|
|
return !traceCondition || traceCondition->BreakTrace();
|
|
}
|
|
|
|
duint StepCount() const
|
|
{
|
|
return traceCondition ? traceCondition->steps : 0;
|
|
}
|
|
|
|
bool InitLogCondition(const String & expression, const String & text)
|
|
{
|
|
delete logCondition;
|
|
logCondition = nullptr;
|
|
if(text.empty())
|
|
return true;
|
|
logCondition = new TextCondition(expression, text);
|
|
return logCondition->condition.IsValidExpression();
|
|
}
|
|
|
|
bool EvaluateLog(bool defaultValue) const
|
|
{
|
|
return logCondition && logCondition->Evaluate(defaultValue);
|
|
}
|
|
|
|
const String & LogText() const
|
|
{
|
|
return logCondition ? logCondition->text : emptyString;
|
|
}
|
|
|
|
bool InitCmdCondition(const String & expression, const String & text)
|
|
{
|
|
delete cmdCondition;
|
|
cmdCondition = nullptr;
|
|
if(text.empty())
|
|
return true;
|
|
cmdCondition = new TextCondition(expression, text);
|
|
return cmdCondition->condition.IsValidExpression();
|
|
}
|
|
|
|
bool EvaluateCmd(bool defaultValue) const
|
|
{
|
|
return cmdCondition && cmdCondition->Evaluate(defaultValue);
|
|
}
|
|
|
|
const String & CmdText() const
|
|
{
|
|
return cmdCondition ? cmdCondition->text : emptyString;
|
|
}
|
|
|
|
bool InitSwitchCondition(const String & expression)
|
|
{
|
|
delete switchCondition;
|
|
switchCondition = nullptr;
|
|
if(expression.empty())
|
|
return true;
|
|
switchCondition = new TextCondition(expression, "");
|
|
return switchCondition->condition.IsValidExpression();
|
|
}
|
|
|
|
bool EvaluateSwitch(bool defaultValue) const
|
|
{
|
|
return switchCondition && switchCondition->Evaluate(defaultValue);
|
|
}
|
|
|
|
void SetLogFile(const char* fileName)
|
|
{
|
|
logFile = StringUtils::Utf8ToUtf16(fileName);
|
|
}
|
|
|
|
bool ForceBreakTrace()
|
|
{
|
|
return forceBreakTrace;
|
|
}
|
|
|
|
void SetForceBreakTrace()
|
|
{
|
|
forceBreakTrace = true;
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
delete traceCondition;
|
|
traceCondition = nullptr;
|
|
delete logCondition;
|
|
logCondition = nullptr;
|
|
delete cmdCondition;
|
|
cmdCondition = nullptr;
|
|
delete switchCondition;
|
|
switchCondition = nullptr;
|
|
logFile.clear();
|
|
delete logWriter;
|
|
logWriter = nullptr;
|
|
writeUtf16 = false;
|
|
forceBreakTrace = false;
|
|
}
|
|
|
|
private:
|
|
TraceCondition* traceCondition = nullptr;
|
|
TextCondition* logCondition = nullptr;
|
|
TextCondition* cmdCondition = nullptr;
|
|
TextCondition* switchCondition = nullptr;
|
|
String emptyString;
|
|
WString logFile;
|
|
BufferedWriter* logWriter = nullptr;
|
|
bool writeUtf16 = false;
|
|
bool forceBreakTrace = false;
|
|
};
|