update parser (#5)

This commit is contained in:
tompzf
2026-01-16 11:40:02 +01:00
committed by GitHub
parent 5039a37131
commit 234be8917f
115 changed files with 14038 additions and 5380 deletions

View File

@@ -40,14 +40,24 @@ namespace asc
enum class EState {header, body, footer} eState = EState::header;
while (std::getline(fstream, ssLine))
{
// Compare two characters and two strings case insensitive
auto ichar_equals = [](char a, char b)
{
return std::tolower(static_cast<unsigned char>(a)) == std::tolower(static_cast<unsigned char>(b));
};
auto iequals = [&](const std::string& a, const std::string& b)
{
return std::equal(a.begin(), a.end(), b.begin(), b.end(), ichar_equals);
};
switch (eState)
{
case EState::header:
if (ssLine.compare(0, 18, "Begin TriggerBlock") == 0)
if (iequals(ssLine.substr(0, 18), "Begin TriggerBlock"))
eState = EState::body;
break;
case EState::body:
if (ssLine.compare(0, 16, "End TriggerBlock") == 0)
if (iequals(ssLine.substr(0, 16), "End TriggerBlock"))
eState = EState::footer;
else
ProcessSample(ssLine);
@@ -74,7 +84,7 @@ namespace asc
uint32_t CAscReader::GetMessageCount() const
{
return m_lstMessages.size();
return static_cast<uint32_t>(m_lstMessages.size());
}
uint32_t CAscReader::GetLoopCount() const

View File

@@ -5,6 +5,7 @@
#include <functional>
#include <filesystem>
#include <thread>
#include <atomic>
namespace asc
{
@@ -159,8 +160,8 @@ namespace asc
std::list<SCanMessage> m_lstMessages; ///< Vector with messages
std::list<SCanMessage>::iterator m_itCurrent; ///< Current iterator position
std::thread m_threadPlayback; ///< Playback thread.
bool m_bPlaybackThread = false; ///< Set when running playback thread
bool m_bPlayback = false; ///< Set when running playback
std::atomic_bool m_bPlaybackThread = false; ///< Set when running playback thread
std::atomic_bool m_bPlayback = false; ///< Set when running playback
std::atomic<uint32_t> m_uiLoopCount{ 0 }; ///< Counter how often the data set was sent
};
}

View File

@@ -58,7 +58,8 @@ bool CArgumentDefBase::CompareNameAndAssign(CArgumentIterator& rargit, const std
while (nPos < rssArgument.size())
{
char c = rssArgument[nPos];
if (!std::isalnum(c) && c != '_' && c != '?')
// Protect against multi-byte characters (UTF-8).
if (static_cast<uint8_t>(c) > 127u || (!std::isalnum(c) && c != '_' && c != '?'))
break;
ssArgNameCS += c;
ssArgNameCI += static_cast<char>(std::tolower(c));

View File

@@ -1389,7 +1389,7 @@ public:
* @param[in] rtArgument Reference to the argument.
* @param[in] rssValue Reference to the string containing the value to be assigned.
*/
void Parse(TVar& /*rtArgument*/, const std::string& /*rssValue*/) {}
void Parse([[maybe_unused]] TVar& rtArgument, [[maybe_unused]] const std::string& rssValue) {}
/**
* @brief Get the markup string for the argument type. Overload in derived class.

View File

@@ -8,12 +8,28 @@
#include <filesystem>
#include <string>
#include <sstream>
#include <thread>
#include <queue>
#include <chrono>
#include <atomic>
#include "exec_dir_helper.h"
#ifndef ENABLE_DEBUG_LOG
/**
* @brief Enable debug log by defining it and assigning it the value 1.
* @brief Enable debug log by defining the ENABLE_DEBUG_LOG to a value other than zero.
*/
#define ENABLE_DEBUG_LOG 1
#endif
#ifndef DECOUPLED_DEBUG_LOG
/**
* @brief When DECOUPLED is set to a value not zero, the logging is decoupled from the writing.
* @attention Decoupling the logging from the writing might improve the accuracy of the logging, and reduce influencing the program
* to an absolute minimum. It does, however, cause messages to be written delayed, which might lead to missing the clue when a
* crash occurs. To log messages synchronously with the program code, set DECOUPLED_DEBUG_LOG to the value zero.
*/
#define DECOUPLED_DEBUG_LOG 1
#endif
/**
* @brief Debug namespace
@@ -33,14 +49,6 @@ namespace debug
CLogger()
{
m_pathLogFile = GetExecDirectory() / GetExecFilename().replace_extension(".log");
std::unique_lock<std::mutex> lock(m_mtxLogger);
std::ofstream fstream(m_pathLogFile, std::ios_base::out | std::ios_base::trunc);
if (fstream.is_open())
{
fstream << "Starting log of " << GetExecFilename().generic_u8string() << std::endl;
fstream.close();
}
std::clog << "Starting log of " << GetExecFilename().generic_u8string() << std::flush << std::endl;
}
/**
@@ -48,14 +56,18 @@ namespace debug
*/
~CLogger()
{
std::unique_lock<std::mutex> lock(m_mtxLogger);
std::ofstream fstream(m_pathLogFile, std::ios_base::out | std::ios_base::app);
if (fstream.is_open())
#if DECOUPLED_DEBUG_LOG != 0
// Shut down the logger thread
if (m_threadLogger.joinable())
{
fstream << "End of log..." << std::endl;
fstream.close();
m_bShutdown = true;
m_threadLogger.join();
}
std::clog << "End of log..." << std::flush << std::endl;
// Prevent the logger mutex to be still in use.
std::unique_lock<std::mutex> lock(m_mtxLogger);
lock.unlock();
#endif
}
/**
@@ -64,16 +76,28 @@ namespace debug
*/
void Log(const std::string& rss)
{
// Create the message structure
SLogMsg sMsg{std::this_thread::get_id(), DepthPerThreadOperation(EDepthOperation::report_only), rss};
#if DECOUPLED_DEBUG_LOG != 0
std::unique_lock<std::mutex> lock(m_mtxLogger);
std::ofstream fstream(m_pathLogFile, std::ios_base::out | std::ios_base::app);
std::string ssIndent(m_nDepth, '>');
if (!ssIndent.empty()) ssIndent += ' ';
if (fstream.is_open())
// First log entry starts logging
if (!m_threadLogger.joinable())
{
fstream << ssIndent << rss << std::endl;
fstream.close();
m_threadLogger = std::thread(&CLogger::LogToFileThreadFunc, this);
while (!m_threadLogger.joinable())
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
std::clog << ssIndent << rss << std::flush << std::endl;
std::cout << rss << std::endl;
// Add message to the log queue
m_queueLogger.push(sMsg);
#else
std::ofstream fstream;
fstream.open(m_pathLogFile, std::ios_base::out | std::ios_base::app);
LogMsg(fstream, sMsg);
#endif
}
/**
@@ -81,7 +105,7 @@ namespace debug
*/
void IncrDepth()
{
m_nDepth++;
DepthPerThreadOperation(EDepthOperation::increase);
}
/**
@@ -89,13 +113,141 @@ namespace debug
*/
void DecrDepth()
{
if (m_nDepth)
m_nDepth--;
DepthPerThreadOperation(EDepthOperation::decrease);
}
private:
std::filesystem::path m_pathLogFile; ///< Path to the log file.
std::mutex m_mtxLogger; ///< Protect against multiple log entries at the same time.
size_t m_nDepth; ///< Depth level for indentation.
/**
* @brief Start the logging
*/
void StartLog()
{
std::ofstream fstream;
fstream.open(m_pathLogFile, std::ios_base::out | std::ios_base::trunc);
if (fstream.is_open())
{
fstream << "Starting log of " << GetExecFilename().generic_u8string() << std::endl;
fstream.close();
}
std::cout << "Starting log of " << GetExecFilename().generic_u8string() << std::endl << std::flush;
}
/**
* @brief Finish the logging
*/
void FinishLog()
{
// Finish logging
std::ofstream fstream;
fstream.open(m_pathLogFile, std::ios_base::out | std::ios_base::app);
if (fstream.is_open())
{
fstream << "End log of " << GetExecFilename().generic_u8string() << std::endl;
fstream.close();
}
std::cout << "End log of " << GetExecFilename().generic_u8string() << std::endl << std::flush;
}
/**
* @brief Log structure containing thread and log information.
*/
struct SLogMsg
{
std::thread::id id; ///< Thread ID
size_t nDepth; ///< Depth within the calls
std::string ssMsg; ///< Message to log
};
/**
* @brief Log a message.
* @param[in] rfstream Reference to the stream to log to.
* @param[in9 rsMsg Reference to the message to log.
*/
void LogMsg(std::ofstream& rfstream, const SLogMsg& rsMsg)
{
std::string ssIndent(rsMsg.nDepth, '>');
if (!ssIndent.empty())
ssIndent += ' ';
if (rfstream.is_open())
{
rfstream << rsMsg.id << ": " << ssIndent << rsMsg.ssMsg << std::endl;
rfstream.close();
}
std::cout << rsMsg.id << ": " << ssIndent << rsMsg.ssMsg << std::endl << std::flush;
}
#if DECOUPLED_DEBUG_LOG != 0
/**
* @brief Log to file thread function.
*/
void LogToFileThreadFunc()
{
// Start logging
StartLog();
// Log until shutdown
while (!m_bShutdown)
{
std::unique_lock<std::mutex> lock(m_mtxLogger);
// Are there any message. If not, pause for 100 ms
if (m_queueLogger.empty())
{
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
continue;
}
std::queue<SLogMsg> queueLocal = std::move(m_queueLogger);
lock.unlock();
// Open the file and log all messages that are in the queue
std::ofstream fstream;
fstream.open(m_pathLogFile, std::ios_base::out | std::ios_base::app);
while (!queueLocal.empty())
{
auto sMsg = std::move(queueLocal.front());
queueLocal.pop();
LogMsg(fstream, sMsg);
}
}
// Finish logging
FinishLog();
}
#endif
/**
* @brief Depth operation selection.
*/
enum class EDepthOperation
{
increase,
decrease,
report_only,
};
/**
* @brief Do a per thread function depth operation (increase, decrease or report).
* @param[in] eOperation The operation to do.
* @return The current function call depth.
*/
size_t DepthPerThreadOperation(EDepthOperation eOperation)
{
thread_local static size_t nDepth = 0; ///< Depth level for indentation.
if (eOperation == EDepthOperation::increase)
nDepth++;
else if (eOperation == EDepthOperation::decrease && nDepth)
nDepth--;
return nDepth;
}
std::filesystem::path m_pathLogFile; ///< Path to the log file.
#if DECOUPLED_DEBUG_LOG != 0
std::mutex m_mtxLogger; ///< Protect against multiple log entries at the same time.
std::thread m_threadLogger; ///< Logger thread
std::atomic_bool m_bShutdown = false; ///< When set, terminate the logging thread
std::queue<SLogMsg> m_queueLogger; ///< Queue with messages to log.
#endif
};
/**

View File

@@ -125,7 +125,9 @@ namespace ipc
else
{
std::srand(static_cast<unsigned>(std::time(nullptr))); // Use current time as seed for random generator
m_ssName = std::string("NAMED_MUTEX_") + std::to_string(std::rand());
uint32_t uiRand = 0;
while (!uiRand) uiRand = std::rand();
m_ssName = std::string("NAMED_MUTEX_") + std::to_string(uiRand);
}
m_handle = CreateMutexA(nullptr, FALSE, (std::string("Global\\") + m_ssName).c_str());
}
@@ -191,7 +193,9 @@ namespace ipc
else
{
std::srand(static_cast<unsigned>(std::time(nullptr))); // Use current time as seed for random generator
m_ssName = std::string("NAMED_MUTEX_") + std::to_string(std::rand());
uint32_t uiRand = 0;
while (!uiRand) uiRand = std::rand();
m_ssName = std::string("NAMED_MUTEX_") + std::to_string(uiRand);
}
m_handle = sem_open(m_ssName.c_str(), O_CREAT, 0777 /*O_RDWR*/, 1);
}

View File

@@ -11,7 +11,7 @@
#include <support/interface_ptr.h>
/**
* \brief Local memory manager class allowing the use of the SDV support classes without having to start the framework.
* @brief Local memory manager class allowing the use of the SDV support classes without having to start the framework.
* \attention Do not use the local memory manager together with the framework's memory manager.
*/
class CLocalMemMgr : public sdv::core::IMemoryAlloc, public sdv::IInterfaceAccess,
@@ -19,13 +19,13 @@ class CLocalMemMgr : public sdv::core::IMemoryAlloc, public sdv::IInterfaceAcces
{
public:
/**
* \brief Constructor assigning this class to the local services.
* @brief Constructor assigning this class to the local services.
*/
CLocalMemMgr()
{}
/**
* \brief Destructor removing this class from the local services.
* @brief Destructor removing this class from the local services.
*/
~CLocalMemMgr()
{}

View File

@@ -32,7 +32,7 @@
* extension ending with "n" match.
* - "subdir?_*" - all files from a directory starting with the name "subdir" followed by a single digit or character, followed
* with a "_" and zero or more characters.
* - "**\/file*.bin" - all files starting with the name "file" followed by zero or more characters and the extension ".bin" in this
* - "**\\/file*.bin" - all files starting with the name "file" followed by zero or more characters and the extension ".bin" in this
* and any subdirectory.
* @param[in] rpathRel Reference to the relative path to check for a match.
* @param[in] rssPattern Reference to the string containing the pattern to match.

View File

@@ -3,7 +3,11 @@
#include <thread>
#include <cstdint>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <atomic>
#ifdef _WIN32
// Prevent reassignment of "interface"
#pragma push_macro("interface")
@@ -65,11 +69,49 @@ public:
}
private:
#ifdef _WIN32
#elif defined __linux__
/**
* @brief Check whether the debugger is present and running the application.
* @return Returns true when the debugger is present or false otherwise.
*/
bool IsDebuggerPresent()
{
std::string ssFilename = "/proc/self/status"; // For the current process
std::ifstream fstreamStatus(ssFilename);
if (!fstreamStatus.is_open()) return false; // Cannot open file, assume not debugged
std::string ssLine;
while (std::getline(fstreamStatus, ssLine))
{
if (ssLine.substr(0, 9) == "TracerPid")
{
std::stringstream sstreamLine(ssLine);
std::string ssKey;
int iTracerPid = 0;
sstreamLine >> ssKey >> iTracerPid;
return iTracerPid != 0;
}
}
return false; // TracerPid not found
}
#else
/**
* @brief Check whether the debugger is present and running the application.
* @return Returns true when the debugger is present or false otherwise.
*/
bool IsDebuggerPresent()
{
// No implementation available to check for a debugger.
return false;
}
#endif
/**
* @brief Watch thread function.
* @param[in] iWatchdogTimeS The duration the watchdog is monitoring before process termination in seconds (default 120s).
* @param[in] iWatchdogTimeS The duration the watchdog is monitoring before process termination in seconds.
*/
void WatchdogThreadFunc(int64_t iWatchdogTimeS = 120ll)
void WatchdogThreadFunc(int64_t iWatchdogTimeS)
{
// Run for the most the set time; then terminate...
auto tpStart = std::chrono::steady_clock::now();
@@ -79,6 +121,9 @@ private:
auto tpNow = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::seconds>(tpNow - tpStart).count() > iWatchdogTimeS)
{
// Do not end the process when a debugger is present.
if (IsDebuggerPresent()) continue;
std::cerr << "WATCHDOG TERMINATION ENFORCED!!!" << std::endl;
std::cerr.flush();
#ifdef _WIN32
@@ -97,8 +142,8 @@ private:
}
}
bool m_bTerminateWatchdog = false; ///< When set, allows the thread to terminate.
std::thread m_threadWatchdog; ///< The watchdog thread.
std::atomic_bool m_bTerminateWatchdog = false; ///< When set, allows the thread to terminate.
std::thread m_threadWatchdog; ///< The watchdog thread.
};
#endif // !defined PROCESS_WATCHDOG_H

View File

@@ -10,6 +10,7 @@
#include <condition_variable>
#include <cstdint>
#include <list>
#include <atomic>
#include "../flags.h"
/**
@@ -112,8 +113,8 @@ private:
void ThreadFunc();
std::thread m_thread; ///< The thread that executes the tasks.
bool m_bShutdown = false; ///< Set when the thread should terminate.
bool m_bStarted = false; ///< Set when the thread has started.
std::atomic_bool m_bShutdown = false; ///< Set when the thread should terminate.
std::atomic_bool m_bStarted = false; ///< Set when the thread has started.
std::function<void()> m_fnTask; ///< The task to execute (will be updated with new tasks before execution).
std::mutex m_mtxSyncStart; ///< The startup synchronization mutex.
std::condition_variable m_cvStarted; ///< Triggered by the thread to indicate that it has started.

View File

@@ -5,6 +5,9 @@
#include <ctime>
#include <sstream>
#include <iomanip>
#ifdef _MSC_VER
#include <process.h>
#endif
#ifdef __GNUC__
#include <unistd.h>
#endif
@@ -29,7 +32,15 @@ inline std::string GetTimestamp()
const auto current_milliseconds {std::chrono::duration_cast<std::chrono::milliseconds> (current_time_since_epoch).count() % 1000};
std::ostringstream stream;
stream << "PID#" << std::dec << getpid() << " " << std::put_time(&current_localtime, "%H:%M:%S") << "." << std::setw(3) << std::setfill('0') << current_milliseconds << ": ";
#ifdef _MSC_VER
stream << "PID#" << std::dec << _getpid() << " " << std::put_time(&current_localtime, "%H:%M:%S") << "." << std::setw(3) <<
std::setfill('0') << current_milliseconds << ": ";
#elif defined __GNUC__
stream << "PID#" << std::dec << getpid() << " " << std::put_time(&current_localtime, "%H:%M:%S") << "." << std::setw(3) <<
std::setfill('0') << current_milliseconds << ": ";
#else
#error The current OS is not supported!
#endif
return stream.str();
}
@@ -66,7 +77,8 @@ inline void Trace(TArgs... tArgs)
}
#else // ENABLE_TRACE == 0
inline void Trace()
template <typename... TArgs>
inline void Trace(TArgs...)
{}
#ifdef __GNUC__

View File

@@ -6,6 +6,7 @@
#include <string>
#include <sstream>
#include <map>
#include <atomic>
/**
* @brief trace fifo open flags
@@ -460,14 +461,14 @@ private:
*/
void DispatchThreadFunc();
const size_t nReadIndex = 0; ///< The read index of the pipe descriptor.
const size_t nWriteIndex = 1; ///< The write index of the pipe descriptor.
bool m_bShutdown = false; ///< Shutdown flag for the pipe reader thread.
int m_rgPipeStdOut[2] = { -1, -1 }; ///< StdOut pipe with read and write descriptors.
int m_rgPipeStdErr[2] = { -1, -1 }; ///< StdErr pipe with read and write descriptors.
int m_iOldStdOut = -1; ///< Old descriptor for the StdOut
int m_iOldStdErr = -1; ///< Old descriptor for the StdErr
std::thread m_threadDispatch; ///< Dispatch thread
const size_t nReadIndex = 0; ///< The read index of the pipe descriptor.
const size_t nWriteIndex = 1; ///< The write index of the pipe descriptor.
std::atomic_bool m_bShutdown = false; ///< Shutdown flag for the pipe reader thread.
int m_rgPipeStdOut[2] = { -1, -1 }; ///< StdOut pipe with read and write descriptors.
int m_rgPipeStdErr[2] = { -1, -1 }; ///< StdErr pipe with read and write descriptors.
int m_iOldStdOut = -1; ///< Old descriptor for the StdOut
int m_iOldStdErr = -1; ///< Old descriptor for the StdErr
std::thread m_threadDispatch; ///< Dispatch thread
};
#endif // !defined TRACE_FIFO_H