Files
dbc/core/dbc_statement_handler.h
2026-10-14 10:32:44 -04:00

121 lines
3.7 KiB
C++

// SPDX-License-Identifier: MIT
#ifndef DBC_STATEMENT_HANDLER_H
#define DBC_STATEMENT_HANDLER_H
#include "dbc_database.h"
#include "dbc_diagnostic.h"
#include "typefactory.h"
#include <stdexcept>
#include <string>
#include <unordered_map>
struct PendingValueDescriptions {
std::uint32_t canId;
bool isExtended;
std::string signalName;
ValueDescriptions descriptions;
std::size_t lineNumber;
};
struct PendingComment {
std::uint32_t canId;
bool isExtended;
bool isSignal;
std::string signalName;
std::string comment;
std::size_t lineNumber;
};
/** Carries deferred validation locations without parsing exception text. */
class DbcDiagnosticError : public std::runtime_error {
public:
DbcDiagnosticError(DbcDiagnosticCode code, const std::string &filePath,
std::size_t lineNumber, const std::string &message)
: std::runtime_error(filePath + ":" + std::to_string(lineNumber) + ": " + message),
diagnostic{DbcDiagnosticSeverity::Error, code, filePath, lineNumber, message} {}
DbcDiagnostic diagnostic;
};
/** Mutable state belonging to one file parse. Handlers do not retain it. */
struct DbcParseContext {
DbcDatabase &database;
FrameInfo *currentFrame = nullptr;
std::size_t lineNumber = 0U;
std::vector<PendingValueDescriptions> pendingValues = {};
std::vector<std::vector<std::size_t>> signalLines = {};
void ValidateMultiplexing(const std::string &filePath) const;
std::vector<PendingComment> pendingComments = {};
void ResolveComments(const std::string &filePath);
void ResolveValueDescriptions(const std::string &filePath);
};
class DbcStatementHandler {
public:
virtual ~DbcStatementHandler() = default;
virtual void Handle(const std::string &line, DbcParseContext &context) const = 0;
};
class DbcFrameHandler : public DbcStatementHandler {
public:
void Handle(const std::string &line, DbcParseContext &context) const override;
private:
static FrameInfo ParseFrameLine(const std::string &line);
};
class DbcSignalHandler : public DbcStatementHandler {
public:
void Handle(const std::string &line, DbcParseContext &context) const override;
private:
static SignalInfo ParseSignalLine(const std::string &line);
};
class DbcCommentHandler : public DbcStatementHandler {
public:
void Handle(const std::string &line, DbcParseContext &context) const override;
};
class DbcValueDescriptionHandler : public DbcStatementHandler {
public:
void Handle(const std::string &line, DbcParseContext &context) const override;
};
class DbcUnsupportedMultiplexingHandler : public DbcStatementHandler {
public:
void Handle(const std::string &line, DbcParseContext &context) const override;
};
/** Common header metadata does not change the supported decode definitions. */
class DbcHeaderHandler : public DbcStatementHandler {
public:
void Handle(const std::string &line, DbcParseContext &context) const override;
};
/** Exact-key dispatch to handlers created once per registration via TypeFactory. */
class DbcStatementDispatcher {
public:
DbcStatementDispatcher();
template<class Handler>
void RegisterType(const std::string &keyword) {
m_factory.registerType<Handler>(keyword);
m_handlers.insert_or_assign(keyword, m_factory.create(keyword));
}
/** Returns false for an unregistered keyword; input must be trimmed. */
bool Dispatch(const std::string &line, DbcParseContext &context) const;
private:
using HandlerMap = std::unordered_map<std::string, std::shared_ptr<DbcStatementHandler>>;
TypeFactory<std::string, DbcStatementHandler> m_factory;
HandlerMap m_handlers;
};
#endif /* DBC_STATEMENT_HANDLER_H */