Precommit (#1)

* first commit

* cleanup
This commit is contained in:
tompzf
2025-11-04 13:28:06 +01:00
committed by GitHub
parent dba45dc636
commit 6ed4b1534e
898 changed files with 256340 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
# Define project
project (sdv_vss_util VERSION 1.0 LANGUAGES CXX)
# Add include directories
include_directories(../export)
# Define the executable
add_executable(sdv_vss_util
main.cpp
csv_file_reader.h
csv_file_reader.cpp
vss_vd_generator.h
vss_vd_generator.cpp
vss_bs_generator.h
vss_bs_generator.cpp
vss_helper.cpp
vss_helper.h
vss_coding.cpp
vss_coding.h
vss_vd_codingrx.cpp
vss_vd_codingrx.h
vss_bs_codingrx.cpp
vss_bs_codingrx.h
vss_vd_codingtx.cpp
vss_vd_codingtx.h
vss_bs_codingtx.cpp
vss_bs_codingtx.h
codegen_base.cpp)
if (WIN32)
target_link_libraries(sdv_vss_util ${CMAKE_DL_LIBS} Rpcrt4.lib)
else()
target_link_libraries(sdv_vss_util ${CMAKE_DL_LIBS})
endif()
# Build dependencies
add_dependencies(sdv_vss_util CompileCoreIDL)
# Appending the executable to the service list
set(SDV_Executable_List ${SDV_Executable_List} sdv_vss_util PARENT_SCOPE)

View File

@@ -0,0 +1,38 @@
#include "codegen_base.h"
#include <sstream>
std::string CCodeGeneratorBase::ReplaceKeywords(const std::string& rssStr, const CKeywordMap& rmapKeywords, char cMarker /*= '%'*/)
{
std::stringstream sstream;
size_t nPos = 0;
while (nPos < rssStr.size())
{
// Find the initial separator
size_t nSeparator = rssStr.find(cMarker, nPos);
sstream << rssStr.substr(nPos, nSeparator == std::string::npos ? nSeparator : nSeparator - nPos);
nPos = nSeparator;
if (nSeparator == std::string::npos) continue;
nPos++;
// Find the next separator.
nSeparator = rssStr.find(cMarker, nPos);
if (nSeparator == std::string::npos)
{
// Internal error: missing second separator during code building.
continue;
}
// Find the keyword in the keyword map (between the separator and the position).
CKeywordMap::const_iterator itKeyword = rmapKeywords.find(rssStr.substr(nPos, nSeparator - nPos));
if (itKeyword == rmapKeywords.end())
{
// Internal error: invalid keyword during building code.
nPos = nSeparator + 1;
continue;
}
sstream << itKeyword->second;
nPos = nSeparator + 1;
}
return sstream.str();
}

View File

@@ -0,0 +1,71 @@
#ifndef CODEGEN_BASE_H
#define CODEGEN_BASE_H
#include <map>
#include <string>
#include <sstream>
#include <cmath>
/**
* @brief Code generator base class.
*/
class CCodeGeneratorBase
{
protected:
/**
* @brief Keyword map for keyword replacement in a string.
*/
typedef std::map<std::string, std::string> CKeywordMap;
/**
* @brief Replace keywords in a string.
* @param[in] rssStr Reference to the string containing the keywords.
* @param[in] rmapKeywords Map with keywords to replace.
* @param[in] cMarker Character to identify the keyword with (placed before and after the keyword; e.g. %keyword%).
* @return Returns the string with replacements.
*/
static std::string ReplaceKeywords(const std::string& rssStr, const CKeywordMap& rmapKeywords, char cMarker = '%');
/**
* @brief Generator specific string generator. The std::to_string doesn't handle floating points very well.
* @tparam T Type of the variable to stringetize.
* @param[in] rtVar Reference to the variable.
* @return The generated string object.
*/
template <typename T>
static std::string to_string(const T& rtVar)
{
std::ostringstream sstream;
sstream << rtVar;
return sstream.str();
}
/**
* @brief Overloading for double.
* @param[in] rdVar Reference to the double variable.
* @return The generated string object.
*/
static std::string to_string(const double& rdVar)
{
std::ostringstream sstream;
sstream << rdVar;
if (std::round(rdVar) == rdVar) sstream << ".0";
return sstream.str();
}
/**
* @brief Overloading for float.
* @param[in] rfVar Reference to the float variable.
* @return The generated string object.
*/
static std::string to_string(const float& rfVar)
{
std::ostringstream sstream;
sstream << rfVar;
if (std::round(rfVar) == rfVar) sstream << ".0";
sstream << "f";
return sstream.str();
}
};
#endif // !defined CODEGEN_BASE_H

View File

@@ -0,0 +1,275 @@
#include "csv_file_reader.h"
CCSVFileReader::CCSVFileReader(const std::string& ssFileName, const bool bSilent, const bool bVerbose)
{
m_silent = bSilent;
m_verbose = bVerbose;
m_vdSignals.clear();
m_bsSignals.clear();
if (ssFileName.empty())
{
Help();
return;
}
else if (!ReadCSVVSSFile(ssFileName))
{
std::cout << "\nError: '" << ssFileName.c_str() << "' file could not be oppened or has no vss definitions." << std::endl;
Help();
return;
}
}
void CCSVFileReader::Help()
{
std::cout << std::endl;
std::cout << "-----------------------------------------------------------------------------------------------------------" << std::endl;
std::cout << "Required: An excel text file in csv format, the separator should be ';'" << std::endl;
std::cout << " [required] Cells must not contain spaces." << std::endl;
std::cout << " [required] Column 'Device Type' must be either 'VD' or 'BS'." << std::endl;
std::cout << " [required] Column 'vss' must contain a character '.' or can be empty." << std::endl;
std::cout << " [required] Column signal direction, either 'RX' or 'TX' or empty." << std::endl;
std::cout << " [required] Column signal value type must not be empty." << std::endl;
std::cout << " [required] Column 'CAN name' must contain a character '.' (for vehicle device signal)." << std::endl;
std::cout << " [required] Last column: in case of vehicle device it is 'CAN name'." << std::endl;
std::cout << " [required] Last column: in case of basic service it is avss from vehicle device." << std::endl;
std::cout << " [recommended] Cells may be empty. In that case either a default string is created or previous entry is used." << std::endl;
std::cout << " [recommended] Column Class name should start with uppercase character." << std::endl;
std::cout << " [recommended] Column Function name should start with uppercase character." << std::endl;
std::cout << " [recommended] Column Signal name should start with lowercase character." << std::endl;
std::cout << "Summary can be found in file 'summary.txt'." << std::endl;
std::cout << "Columns:" << std::endl;
std::cout << "Device Type ';' Class name ';' Function name ';' Signal name ';' Interface (vss) ';' Direction ';' Signal value type ';' 'CAN name' or Interface(vss)" << std::endl;
std::cout << std::endl;
std::cout << "e.g." << std::endl;
std::cout << "VD ';' FrontWheel ';' SetAverageAngle ';' averageAngle ';' Vehicle.Chassis.Axle.Row.Wheel.AverageAngle ';' RX ';' float ';' CANMsg.Angle" << std::endl;
std::cout << "BS ';' VehicleChassisAxle ';' SetAngleStatus ';' angleStatus ';' Vehicle.Chassis.Axle.Row.Wheel ';' TX ';' uint8_t ';' Vehicle.Chassis.Axle.Row.Wheel" << std::endl;
std::cout << "-----------------------------------------------------------------------------------------------------------" << std::endl;
}
bool CCSVFileReader::ReadCSVVSSFile(const std::string& ssFileName)
{
std::ifstream file(ssFileName);
if (!file.is_open())
{
std::cerr << "'" << ssFileName << "' could not be opened." << std::endl;
return false;
}
std::string line;
uint32_t index = 1;
while (std::getline(file, line))
{
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
ReadLine(line, index++, vssVDColumns::column_end);
}
file.close();
if ((m_vdSignals.size() == 0) && (m_bsSignals.size() == 0))
{
if (!m_silent)
{
std::cout << "No valid signal definitions found." << std::endl;
}
}
return true;
}
void CCSVFileReader::ReadLine(const std::string& ssLine, const uint32_t index, size_t endColumn)
{
std::stringstream ss(ssLine);
std::string item;
std::vector<std::string> parts;
while (std::getline(ss, item, ';'))
{
item = Trim(item);
auto cType = GetCTypeFromIDLType(item); // maybe its a IDL type
if (MustNotContainSpaces(item) || (cType.size() != 0))
{
parts.push_back(item);
}
else
{
if ((m_vdSignals.size() != 0) && (m_bsSignals.size() && !m_silent))
{
std::cout << "Invalid, contains spaces: '" << item << "'" << std::endl;
}
}
}
if (parts.size() >= endColumn)
{
ParseColumns(parts, index);
}
}
void CCSVFileReader::ParseColumns(const std::vector<std::string>& parts, const uint32_t index)
{
static std::string vss = "";
static sdv::core::ESignalDirection signalDirection = sdv::core::ESignalDirection::sigdir_rx;
if (parts.size() >= vssVDColumns::column_end)
{
if (parts[vssVDColumns::column_vssDefinition].size() != 0) // if vss is empty use previous one
{
vss = parts[vssVDColumns::column_vssDefinition];
}
if (!MustContainDotOrIsEmpty(vss, false)) // vss can be empty
{
if ((m_vdSignals.size() != 0) && (m_bsSignals.size() && !m_silent))
{
std::cout << "Invalid, contains no charatcer '.': '" << vss << "', line number " << std::to_string(index)<< std::endl;
}
return;
}
vss = ValidateVSSFormatNumbers(vss);
if (!parts[vssVDColumns::column_direction].compare("RX"))
signalDirection = sdv::core::ESignalDirection::sigdir_rx;
if (!parts[vssVDColumns::column_direction].compare("TX"))
signalDirection = sdv::core::ESignalDirection::sigdir_tx;
if (!parts[vssVDColumns::column_type].compare("VD"))
{
if (AddToExistingVDSignal(m_vdSignals, vss, signalDirection, parts, index))
{
return;
}
SSignalVDDefinition signal;
signal.vssDefinition = vss;
signal.signalDirection = signalDirection;
signal.className = GenerateDefaultIfEmpty(parts[vssVDColumns::column_className], "ClassName", index);
if (AddFunctionVDDefinition(signal, parts[vssVDColumns::column_functionName], parts[vssVDColumns::column_signalName],
parts[vssVDColumns::column_canSignalName], parts[vssVDColumns::column_signalCType], index))
{
ValidateVDCodeStyle(signal, m_verbose);
m_vdSignals.push_back(signal);
}
}
else
{
if (AddToExistingBSSignal(m_bsSignals, vss, signalDirection, parts, index))
{
return;
}
std::string vssOfVehicleDevice = parts[vssVDColumns::column_vdDefinition];
vssOfVehicleDevice = ValidateVSSFormatNumbers(vssOfVehicleDevice);
SSignalBSDefinition signal;
signal.vssDefinition = vss;
signal.signalDirection = signalDirection;
signal.className = GenerateDefaultIfEmpty(parts[vssVDColumns::column_className], "ClassName", index);
signal.vssVDDefinition = vssOfVehicleDevice;
if (AddFunctionBSDefinition(signal, parts[vssVDColumns::column_functionName], parts[vssVDColumns::column_signalName],
parts[vssVDColumns::column_canSignalName], parts[vssVDColumns::column_signalCType], index))
{
ValidateBSCodeStyle(signal, m_verbose);
m_bsSignals.push_back(signal);
}
}
}
}
bool CCSVFileReader::AddToExistingVDSignal(std::vector <SSignalVDDefinition>& signals, const std::string& vssDefinition,
const sdv::core::ESignalDirection& directionX, const std::vector<std::string>& parts, const uint32_t index)
{
for (auto& signal : signals)
{
if ((signal.vssDefinition.compare(vssDefinition) == 0) && (signal.signalDirection == directionX))
{
if ((signal.className != parts[vssVDColumns::column_className]) && !m_silent)
{
std::cout << "Signal already found, ignore class name '" << parts[vssVDColumns::column_className] << "', line number " << std::to_string(index) << std::endl;
}
AddFunctionVDDefinition(signal, parts[vssVDColumns::column_functionName], parts[vssVDColumns::column_signalName],
parts[vssVDColumns::column_canSignalName], parts[vssVDColumns::column_signalCType], index);
return true;
}
}
return false;
}
bool CCSVFileReader::AddToExistingBSSignal(std::vector <SSignalBSDefinition>& signals, const std::string& vssDefinition,
const sdv::core::ESignalDirection& directionX, const std::vector<std::string>& parts, const uint32_t index)
{
for (auto& signal : signals)
{
if ((signal.vssDefinition.compare(vssDefinition) == 0) && (signal.signalDirection == directionX))
{
if ((signal.className != parts[vssVDColumns::column_className]) && !m_silent)
{
std::cout << "Signal already found, ignore class name '" << parts[vssVDColumns::column_className] << "', line number " << std::to_string(index) << std::endl;
}
AddFunctionBSDefinition(signal, parts[vssVDColumns::column_functionName], parts[vssVDColumns::column_signalName],
parts[vssVDColumns::column_vdDefinition], parts[vssVDColumns::column_signalCType], index);
return true;
}
}
return false;
}
bool CCSVFileReader::AddFunctionVDDefinition(SSignalVDDefinition& signal, const std::string& functionName, const std::string& signalName,
const std::string& canSignalName, const std::string& idlType, const uint32_t index)
{
if (!MustContainDotOrIsEmpty(canSignalName, true)) // can signal must must not be empty
{
if ((m_vdSignals.size() != 0) && (m_bsSignals.size() && !m_silent))
{
std::cout << "Invalid, contains no charatcer '.' or is empty: '" << canSignalName << "', line number " << std::to_string(index) << std::endl;
}
return false;
}
auto cType = GetCTypeFromIDLType(idlType);
if ((cType.size() == 0) && !m_silent)
{
std::cout << "Invalid, idl type unknown: '" << idlType << "', line number " << std::to_string(index) << std::endl;
return false;
}
SFunctionVDDefinition func;
func.functionName = GenerateDefaultIfEmpty(functionName, "FunctionName", index);
func.signalName = GenerateDefaultIfEmpty(signalName, "variableName", index);
func.canSignalName = canSignalName;
func.idlType = idlType;
ValidateVDCodeStyle(func, m_verbose);
signal.vecFunctions.push_back(func);
return true;
}
bool CCSVFileReader::AddFunctionBSDefinition(SSignalBSDefinition& signal, const std::string& functionName, const std::string& signalName,
const std::string& canSignalName, const std::string& idlType, const uint32_t index)
{
if (!MustContainDotOrIsEmpty(canSignalName, true)) // can signal must must not be empty
{
if ((m_vdSignals.size() != 0) && (m_bsSignals.size() && !m_silent))
{
std::cout << "Invalid, contains no charatcer '.' or is empty: '" << canSignalName << "', line number " << std::to_string(index) << std::endl;
}
return false;
}
auto cType = GetCTypeFromIDLType(idlType);
if ((cType.size() == 0) && !m_silent)
{
std::cout << "Invalid, idl type unknown: '" << idlType << "', line number " << std::to_string(index) << std::endl;
return false;
}
SFunctionBSDefinition func;
func.functionName = GenerateDefaultIfEmpty(functionName, "FunctionName", index);
func.signalName = GenerateDefaultIfEmpty(signalName, "variableName", index);
func.idlType = idlType;
ValidateBSCodeStyle(func, m_verbose);
signal.vecFunctions.push_back(func);
return true;
}

View File

@@ -0,0 +1,145 @@
#ifndef CSV_FILE_READER_H
#define CSV_FILE_READER_H
#include <fstream>
#include "vss_helper.h"
/**
* @brief Reads the cvs file and parses the signal definitions.
*/
class CCSVFileReader : public CVSSHelper
{
public:
/**
* @brief Constructor
* @param[in] ssFileName Reference to the cvs file which contains the VSS definition
* @param[in] bSilent if true no console output on errors & warnings
* @param[in] bVerbose if true validates names and print out warnings in case of code style is not matched
*/
CCSVFileReader(const std::string& ssFileName, const bool bSilent, const bool bVerbose);
/**
* @brief Get signal definitions for vehicle devices
* @return Returns a reference to the variable containing the list of signals;
*/
const std::vector<SSignalVDDefinition>& GetVDSignals() const
{
return m_vdSignals;
}
/**
* @brief Get signal definitions for basic services
* @return Returns a reference to the variable containing the list of signals;
*/
const std::vector<SSignalBSDefinition>& GetBSSignals() const
{
return m_bsSignals;
}
private:
/**
* @brief Type definitions for the columns in the vehicle device sheets
*/
typedef enum vssVDColumns
{
column_type,
column_className,
column_functionName,
column_signalName,
column_vssDefinition,
column_direction,
column_signalCType,
column_canSignalName,
column_vdDefinition = column_canSignalName,
column_end
} vssVDColumns;
/**
* @brief prints help to the console
*/
void Help();
/**
* @brief read a csv excel file with ';' separator
* @param[in] ssFileName name of the cvs file to be read
* @return True if signals definitions could be read and are valid, otherwise false;
*/
bool ReadCSVVSSFile(const std::string& ssFileName);
/**
* @brief read and interprets a signal line of a cvs file
* @param[in] ssLine content of a complete line
* @param[in] index line number, may be used for default values
* @param[in] endColumn the maximum of columns
*/
void ReadLine(const std::string& ssLine, const uint32_t index, size_t endColumn);
/**
* @brief If a signal definition is found in the list for the vehicle devices add the function/signal to this definition
* @param[in] signals collection of vehicle device signals
* @param[in] vssDefinition definition to look for
* @param[in] direction signal direction, either rx or tx
* @param[in] parts Reference to the list of parts of a single line of the cvs file
* @param[in] index line number
* @return True if signal was found, otherwise false
*/
bool AddToExistingVDSignal(std::vector <SSignalVDDefinition>& signals, const std::string& vssDefinition,
const sdv::core::ESignalDirection& direction, const std::vector<std::string>& parts, const uint32_t index);
/**
* @brief If a signal definition is found in the list for the basic services add the function/signal to this definition
* @param[in] signals collection of basic service signals
* @param[in] vssDefinition definition to look for
* @param[in] direction signal direction, either rx or tx
* @param[in] parts Reference to the list of parts of a single line of the cvs file
* @param[in] index line number
* @return True if signal was found, otherwise false
*/
bool AddToExistingBSSignal(std::vector <SSignalBSDefinition>& signals, const std::string& vssDefinition,
const sdv::core::ESignalDirection& direction, const std::vector<std::string>& parts, const uint32_t index);
/**
* @brief parse the parts of a line of the vehicle device sheet to get the signal definitions
* @param[in] parts Reference to the list of parts of a single line of the cvs file
* @param[in] index line number
*/
void ParseColumns(const std::vector<std::string>& parts, const uint32_t index);
/**
* @brief add function definition to the container of an existing signal (vehicle device)
* @param[in] signal the function definition should be added
* @param[in] functionName functione name
* @param[in] signalName signal name
* @param[in] canSignalName can signal name
* @param[in] idlType idl type
* @param[in] index line number
* @return True if function definition was added, otherwise false
*/
bool AddFunctionVDDefinition(SSignalVDDefinition& signal, const std::string& functionName,
const std::string& signalName, const std::string& canSignalName, const std::string& idlType, const uint32_t index);
/**
* @brief add function definition to the container of an existing signal (basic service)
* @param[in] signal the function definition should be added
* @param[in] functionName functione name
* @param[in] signalName signal name
* @param[in] canSignalName can signal name
* @param[in] idlType idl type
* @param[in] index line number
* @return True if function definition was added, otherwise false
*/
bool AddFunctionBSDefinition(SSignalBSDefinition& signal, const std::string& functionName,
const std::string& signalName, const std::string& canSignalName, const std::string& idlType, const uint32_t index);
std::vector <SSignalVDDefinition> m_vdSignals; ///< all signals for vehicle devices
std::vector <SSignalBSDefinition> m_bsSignals; ///< all signals for basic services
bool m_verbose = false;
bool m_silent = false;
};
#endif // !defined CSV_FILE_READER_H

View File

@@ -0,0 +1,135 @@
#include <iostream>
#include <unordered_map>
#include "../../global/process_watchdog.h"
#include "../../global/cmdlnparser/cmdlnparser.cpp"
#include "../../global/dbcparser/dbcparser.cpp"
#include "../../global/localmemmgr.h"
#include "../error_msg.h"
#include <interfaces/core.h>
#include <interfaces/mem.h>
#include "csv_file_reader.h"
#include "vss_vd_generator.h"
#include "vss_bs_generator.h"
#include "vss_helper.h"
void makeSignalNamesUnique(std::vector< CVSSHelper::SSignalVDDefinition>& vdSignals)
{
std::unordered_map<std::string, int> nameCount;
std::vector<std::string> allUniqueNames;
auto process = [&](std::vector< CVSSHelper::SSignalVDDefinition>& signals)
{
for (auto& signal : signals)
{
for (auto& func : signal.vecFunctions)
{
std::string& name = func.signalName;
std::string originalName = name;
while (nameCount[name] > 0)
{
name = originalName + "_" + std::to_string(nameCount[originalName]);
nameCount[originalName]++;
}
nameCount[name]++;
allUniqueNames.push_back(name);
}
}
};
process(vdSignals);
}
#if defined(_WIN32) && defined(_UNICODE)
extern "C" int wmain(int iArgc, const wchar_t* rgszArgv[])
#else
extern "C" int main(int iArgc, const char* rgszArgv[])
#endif
{
// Workaround for GCC to make certain that POSIX thread library is loaded before the components are loaded.
// REASON: If the first call to a thread is done in a dynamic library, the application is already classified as single
// threaded and a termination is initiated.
// See: https://stackoverflow.com/questions/51209268/using-stdthread-in-a-library-loaded-with-dlopen-levds-to-a-sigsev
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
CProcessWatchdog watchdog;
// Suppress the warning supplied by ccpcheck about an unsused variable. The memory manager registers itself into the system and
// needs to stay in scope.
// cppcheck-suppress unusedVariable
CLocalMemMgr memmgr;
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
bool bHelp = false;
bool bError = false;
bool bSilent = false;
bool bVerbose = false;
bool bEnableComponents = false;
std::string ssVersion;
std::string ssPrefix;
std::string ssVSSFileName;
std::filesystem::path pathOutputDir;
try
{
auto& rArgHelpDef = cmdln.DefineOption("?", bHelp, "Show help");
rArgHelpDef.AddSubOptionName("help");
auto& rArgSilentDef = cmdln.DefineOption("s", bSilent, "Do not show any information on STDOUT. Not compatible with 'verbose'.");
rArgSilentDef.AddSubOptionName("silent");
auto& rArgVerboseDef = cmdln.DefineOption("v", bVerbose, "Provide verbose information. Not compatible with 'silent'.");
rArgVerboseDef.AddSubOptionName("verbose");
cmdln.DefineSubOption("prefix", ssPrefix, "prefix, used by cmake library and signal definition in signal_identifier.h file.");
cmdln.DefineSubOption("enable_components", bEnableComponents, "Creates additionally to the idl files the code for the components.");
cmdln.DefineSubOption("version", ssVersion, "Optional: version information of the dbc file.");
cmdln.DefineOption("O", pathOutputDir, "Set output directory (required).");
cmdln.DefineDefaultArgument(ssVSSFileName, "Excel file.");
cmdln.Parse(static_cast<size_t>(iArgc), rgszArgv);
} catch (const SArgumentParseException& rsExcept)
{
std::cout << "ERROR: " << rsExcept.what() << std::endl;
bHelp = true;
bError = true;
}
if (bSilent)
{
bVerbose = false;
}
if (!bSilent)
{
std::cout << "abtract device / basic services utility" << std::endl;
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
std::cout << "Author: Thomas Pfleiderer" << std::endl;
}
if (bHelp || (ssVSSFileName.empty() || pathOutputDir.empty() || ssPrefix.empty()))
{
if (!bSilent)
{
cmdln.PrintHelp(std::cout);
//CCSVFileReader csv("", bSilent, bVerbose);
}
return bError ? CMDLN_ARG_ERR : NO_ERROR;
}
CCSVFileReader csv(ssVSSFileName, bSilent, bVerbose);
auto vdSignals = csv.GetVDSignals();
auto bsSignals = csv.GetBSSignals();
if (!CVSSHelper::VehicleDeviceVSSDefinitionExists(bSilent, vdSignals, bsSignals))
{
return BASIC_SERVICE_DATA_ERROR;
}
if (vdSignals.size() > 0)
{
makeSignalNamesUnique(vdSignals);
CVSSVDGenerator vssVD(vdSignals, pathOutputDir, ssPrefix, ssVersion, bEnableComponents);
vssVD.GeneratedCode();
if (bsSignals.size() > 0)
{
CVSSBSGenerator vssBS(bsSignals, vdSignals, pathOutputDir, ssPrefix, ssVersion, bEnableComponents);
vssBS.GeneratedCode();
}
}
return NO_ERROR;
}

View File

@@ -0,0 +1,438 @@
#include "vss_bs_codingrx.h"
void CVSSBSCodingRX::GetKeyWordMap(const SSignalBSDefinition& signal, const SSignalVDDefinition& signalVD, CKeywordMap& mapKeywords) const
{
std::string vd_vssWithColons = ReplaceCharacters(signal.vssVDDefinition, ".", "::");
std::string vssWithColons = ReplaceCharacters(signal.vssDefinition, ".", "::");
//------------------------------------------------------- basic service header
std::stringstream sstreamIncludesVD;
std::string vssNoDot = ReplaceCharacters(signal.vssDefinition, ".", "");
std::transform(vssNoDot.begin(), vssNoDot.end(), vssNoDot.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
sstreamIncludesVD << Code_BS_RXIncludes(vssNoDot);
mapKeywords["rx_bs_includes_list"] = std::move(sstreamIncludesVD.str());
std::stringstream sstreamBSInterfaces;
for (uint32_t index = 0; index < signal.vecFunctions.size(); index++)
{
if (index >= signalVD.vecFunctions.size())
break;
auto func = signal.vecFunctions[index];
auto funcVD = signalVD.vecFunctions[index];
sstreamBSInterfaces << Code_BS_RXInterface(func.functionName, vssWithColons,
funcVD.functionName, vd_vssWithColons);
}
mapKeywords["rx_bs_interface_list"] = std::move(sstreamBSInterfaces.str());
std::stringstream sstreamBSInterfaceEntries;
for (const auto& func : signal.vecFunctions)
{
sstreamBSInterfaceEntries << Code_BS_RXInterfaceEntry(func.functionName, vssWithColons);
}
mapKeywords["rx_bs_interface_entry_list"] = std::move(sstreamBSInterfaceEntries.str());
std::stringstream sstreamBSRegisterEvents;
for (uint32_t index = 0; index < signal.vecFunctions.size(); index++)
{
if (index >= signalVD.vecFunctions.size())
break;
auto func = signal.vecFunctions[index];
auto funcVD = signalVD.vecFunctions[index];
sstreamBSRegisterEvents << Code_BS_RXReAndUnregisterEvent(vssWithColons, func, funcVD);
}
mapKeywords["rx_bs_register_events_list"] = std::move(sstreamBSRegisterEvents.str());
std::stringstream sstreamPrivateBSHeaderPart;
for (const auto& func : signal.vecFunctions)
{
sstreamPrivateBSHeaderPart << Code_BS_RXPrivateHeaderPart(func, vssWithColons);
}
mapKeywords["rx_bs_private_vd_header_part"] = std::move(sstreamPrivateBSHeaderPart.str());
////------------------------------------------------------- basic service cpp
std::stringstream sstreamBSConstructor;
for (uint32_t index = 0; index < signalVD.vecFunctions.size(); index++)
{
if (index >= signal.vecFunctions.size())
break;
auto func = signal.vecFunctions[index];
auto funcVD = signalVD.vecFunctions[index];
sstreamBSConstructor << Code_BS_RXConstructor(signalVD, vd_vssWithColons, funcVD, func);
}
mapKeywords["rx_bs_constructor"] = std::move(sstreamBSConstructor.str());
std::stringstream sstreamBSDeConstructor;
for (const auto& func : signalVD.vecFunctions)
{
sstreamBSDeConstructor << Code_BS_RXDestructor(signalVD, vd_vssWithColons, func);
}
mapKeywords["rx_bs_deconstructor"] = std::move(sstreamBSDeConstructor.str());
std::stringstream sstreamBSGetAndSetFunctions;
for (uint32_t index = 0; index < signal.vecFunctions.size(); index++)
{
if (index >= signalVD.vecFunctions.size())
break;
auto func = signal.vecFunctions[index];
auto funcVD = signalVD.vecFunctions[index];
sstreamBSGetAndSetFunctions << Code_BS_RXGetAndSetFunctions(signal.className, func, funcVD);
}
mapKeywords["rx_bs_getandsetfunctions"] = std::move(sstreamBSGetAndSetFunctions.str());
std::stringstream sstreamBSRegister;
for (const auto& func : signal.vecFunctions)
{
sstreamBSRegister << Code_BS_RXRegister(signal.className, func, vssWithColons);
}
mapKeywords["rx_bs_register"] = std::move(sstreamBSRegister.str());
}
std::string CVSSBSCodingRX::Code_RXIDLServiceList(const std::vector<std::string>& vssParts,
const std::vector <SFunctionBSDefinition>& vecFunctions) const
{
std::string vssWithColons = "";
int8_t loop = 1;
std::string nameSpace = "module vss\n{\n";
for (auto it = vssParts.begin(); it != vssParts.end(); ++it)
{
nameSpace.append(static_cast <int8_t>(4) * loop, ' ');
nameSpace.append("module ");
nameSpace.append(*it);
if (it == vssParts.end() - 1)
{
nameSpace.append("Service");
}
nameSpace.append("\n");
nameSpace.append(static_cast <int8_t>(4) * loop++, ' ');
nameSpace.append("{\n");
vssWithColons.append("::");
vssWithColons.append(*it);
}
nameSpace.append("%interfaces%");
loop--;
for (size_t i = 0; i < vssParts.size() + 1; i++)
{
nameSpace.append(static_cast <int8_t>(4) * loop--, ' ');
nameSpace.append("};\n");
}
std::string spaces = "";
spaces.append(static_cast <int8_t>(4) * (vssParts.size() + 1), ' ');
std::stringstream sstreamInterfaces;
for (auto func : vecFunctions)
{
sstreamInterfaces << Code_RXIDLServiceInterface(spaces, vssWithColons, func);
}
CKeywordMap mapKeywords;
mapKeywords["interfaces"] = std::move(sstreamInterfaces.str());
return ReplaceKeywords(nameSpace, mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXIncludes(const std::string& vssOriginalNoDot) const
{
CKeywordMap mapKeywords;
mapKeywords["vss_original_no_dot"] = vssOriginalNoDot;
return ReplaceKeywords(R"code(#include "../vss_%vss_original_no_dot%_bs_rx.h"
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_RXIDLServiceInterface(const std::string& spaces, const std::string& vssWithColons,
const SFunctionBSDefinition& function) const
{
auto signalStartWithUppercase = function.signalName;
if (!signalStartWithUppercase.empty())
{
signalStartWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(signalStartWithUppercase[0])));
}
std::string prefix = "Service";
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_start_with_uppercase"] = signalStartWithUppercase;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_idltype"] = function.idlType;
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
mapKeywords["prefix"] = prefix;
mapKeywords["multiple_spaces"] = spaces;
mapKeywords["vssWithColons"] = vssWithColons;
return ReplaceKeywords(R"code(%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_Set%function_name% event interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_Set%function_name%_Event
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Set %signal_name% signal
%multiple_spaces% * @param[in] value %signal_name%
%multiple_spaces% */
%multiple_spaces% void Set%function_name%(in %value_idltype% value);
%multiple_spaces%};
%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_Get%function_name% %prefix% interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_Get%function_name%
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Get %signal_name% signal
%multiple_spaces% * @return Returns the %signal_name%
%multiple_spaces% */
%multiple_spaces% %value_idltype% Get%function_name%() const;
%multiple_spaces% /**
%multiple_spaces% * @brief Register Callback on signal change
%multiple_spaces% * @param[in] callback function
%multiple_spaces% */
%multiple_spaces% void RegisterOnSignalChangeOf%signal_start_with_uppercase%(in vss%vssWithColons%Service::IVSS_Set%function_name%_Event callback);
%multiple_spaces% /**
%multiple_spaces% * @brief Unregister Callback
%multiple_spaces% * @param[in] callback function
%multiple_spaces% */
%multiple_spaces% void UnregisterOnSignalChangeOf%signal_start_with_uppercase%(in vss%vssWithColons%Service::IVSS_Set%function_name%_Event callback);
%multiple_spaces%};
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXInterface(const std::string& functionName, const std::string& vssWithColons,
const std::string& vd_functionName, const std::string& vd_vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vssWithColons"] = vssWithColons;
mapKeywords["vd_function_name"] = vd_functionName;
mapKeywords["vd_vssWithColons"] = vd_vssWithColons;
return ReplaceKeywords(R"code( , public vss::%vssWithColons%Service::IVSS_Get%function_name%
, public vss::%vssWithColons%Service::IVSS_Set%function_name%_Event
, public vss::%vd_vssWithColons%Device::IVSS_Write%vd_function_name%_Event
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vssWithColons"] = vssWithColons;
return ReplaceKeywords(R"code( SDV_INTERFACE_ENTRY(vss::%vssWithColons%Service::IVSS_Get%function_name%)
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXReAndUnregisterEvent(const std::string& vssWithColons,
const SFunctionBSDefinition& function, const SFunctionVDDefinition& functionVD) const
{
auto startWithUppercase = function.signalName;
if (!startWithUppercase.empty())
{
startWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(startWithUppercase[0])));
}
CKeywordMap mapKeywords;
mapKeywords["vssWithColons"] = vssWithColons;
mapKeywords["function_name"] = function.functionName;
mapKeywords["vd_function_name"] = functionVD.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["start_with_uppercase"] = startWithUppercase;
auto signalType = GetCTypeFromIDLType(function.idlType);
mapKeywords["casted_value_ctype"] = CastValueType(signalType);
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
return ReplaceKeywords(R"code(
/**
* @brief Set %signal_name% signal
* @param[in] value %signal_name%
*/
void Set%function_name%(%casted_value_ctype% value) override;
/**
* @brief Get %signal_name%
* @return Returns the %signal_name%
*/
%value_ctype% Get%function_name%() const override;
/**
* @brief Write %signal_name% signal
* @param[in] value %signal_name%
*/
void Write%vd_function_name%(%casted_value_ctype% value) override;
/**
* @brief Register CallBack function on signal change
* @param[in] callback function
*/
void RegisterOnSignalChangeOf%start_with_uppercase%(vss::%vssWithColons%Service::IVSS_Set%function_name%_Event* callback) override;
/**
* @brief Unregister CallBack function on signal change
* @param[in] callback function
*/
void UnregisterOnSignalChangeOf%start_with_uppercase%(vss::%vssWithColons%Service::IVSS_Set%function_name%_Event* callback) override;
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXPrivateHeaderPart(const SFunctionBSDefinition& function, const std::string& vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["vssWithColons"] = vssWithColons;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
return ReplaceKeywords(R"code(
%value_ctype% m_%signal_name% { 0 }; ///< %signal_name% signal
mutable std::mutex m_%signal_name%MutexCallbacks; ///< Mutex protecting m_%signal_name%Callbacks
std::set<vss::%vssWithColons%Service::IVSS_Set%function_name%_Event*> m_%signal_name%Callbacks; ///< collection of events to be called
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXConstructor(const SSignalVDDefinition& signalVD, const std::string& vd_vssWithColons,
const SFunctionVDDefinition& functionVD, const SFunctionBSDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["vd_vss_original"] = signalVD.vssDefinition;
mapKeywords["vd_vssWithColons"] = vd_vssWithColons;
mapKeywords["vd_function_name"] = functionVD.functionName;
mapKeywords["vd_class_name"] = signalVD.className;
mapKeywords["signal_name"] = function.signalName;
return ReplaceKeywords(R"code(
auto %signal_name%Device = sdv::core::GetObject("%vd_vss_original%_Device").GetInterface<vss::%vd_vssWithColons%Device::IVSS_%vd_function_name%>();
if (!%signal_name%Device)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_%vd_function_name%': [CBasicService%vd_class_name%]");
throw std::runtime_error("%vd_vss_original% mode device not found");
}
%signal_name%Device->Register%vd_function_name%Event(dynamic_cast<vss::%vd_vssWithColons%Device::IVSS_Write%vd_function_name%_Event*> (this));
SDV_LOG_TRACE("CBasicService%vd_class_name% created: [%vd_vss_original%_Device]");
m_%signal_name% = 0;
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXDestructor(const SSignalVDDefinition& signalVD, const std::string& vd_vssWithColons,
const SFunctionVDDefinition& functionVD) const
{
CKeywordMap mapKeywords;
mapKeywords["vd_signal_name"] = functionVD.signalName;
mapKeywords["vd_vss_original"] = signalVD.vssDefinition;
mapKeywords["vd_vssWithColons"] = vd_vssWithColons;
mapKeywords["vd_function_name"] = functionVD.functionName;
return ReplaceKeywords(R"code(
auto %vd_signal_name%Device = sdv::core::GetObject("%vd_vss_original%_Device").GetInterface<vss::%vd_vssWithColons%Device::IVSS_%vd_function_name%>();
if (%vd_signal_name%Device)
{
%vd_signal_name%Device->Unregister%vd_function_name%Event(dynamic_cast<vss::%vd_vssWithColons%Device::IVSS_Write%vd_function_name%_Event*> (this));
}
%vd_signal_name%Device = nullptr;
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXGetAndSetFunctions(const std::string& class_name, const SFunctionBSDefinition& function,
const SFunctionVDDefinition& functionVD) const
{
std::string class_name_lowercase = class_name;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["vd_function_name"] = functionVD.functionName;
mapKeywords["class_name"] = class_name;
mapKeywords["signal_name"] = function.signalName;
auto signalType = GetCTypeFromIDLType(function.idlType);
mapKeywords["casted_value_ctype"] = CastValueType(signalType);
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
/**
* @brief Set %signal_name%
* @param[in] value %signal_name%
*/
void CBasicService%class_name%::Set%function_name%(%casted_value_ctype% value)
{
m_%signal_name% = value;
std::lock_guard<std::mutex> lock(m_%signal_name%MutexCallbacks);
for (auto callback : m_%signal_name%Callbacks)
{
callback->Set%function_name%(value);
}
}
/**
* @brief Write %signal_name%
* @param[in] value %signal_name%
*/
void CBasicService%class_name%::Write%vd_function_name%(%casted_value_ctype% value)
{
Set%function_name%(value);
}
/**
* @brief Get %signal_name%
* @return Returns the %signal_name%
*/
%value_ctype% CBasicService%class_name%::Get%function_name%() const
{
return m_%signal_name%;
}
)code", mapKeywords);
}
std::string CVSSBSCodingRX::Code_BS_RXRegister(const std::string& class_name, const SFunctionBSDefinition& function,
const std::string& vssWithColons) const
{
auto startWithUppercase = function.signalName;
if (!startWithUppercase.empty())
{
startWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(startWithUppercase[0])));
}
std::string class_name_lowercase = class_name;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["start_with_uppercase"] = startWithUppercase;
mapKeywords["class_name"] = class_name;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["vssWithColons"] = vssWithColons;
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
/**
* @brief Register Callback on signal change
* @param[in] callback function
*/
void CBasicService%class_name%::RegisterOnSignalChangeOf%start_with_uppercase%(vss::%vssWithColons%Service::IVSS_Set%function_name%_Event* %signal_name%Callback)
{
if ( %signal_name%Callback)
{
std::lock_guard<std::mutex> lock(m_%signal_name%MutexCallbacks);
m_%signal_name%Callbacks.insert(%signal_name%Callback);
}
}
/**
* @brief Unregister Callback
* @param[in] callback function
*/
void CBasicService%class_name%::UnregisterOnSignalChangeOf%start_with_uppercase%(vss::%vssWithColons%Service::IVSS_Set%function_name%_Event* %signal_name%Callback)
{
if (%signal_name%Callback)
{
std::lock_guard<std::mutex> lock(m_%signal_name%MutexCallbacks);
m_%signal_name%Callbacks.erase(%signal_name%Callback);
}
}
)code", mapKeywords);
}

View File

@@ -0,0 +1,142 @@
#ifndef VSS_BS_CODING_RX_H
#define VSS_BS_CODING_RX_H
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <interfaces/dispatch.h>
#include "codegen_base.h"
#include "vss_helper.h"
#include "vss_rx_templates.h"
#include "vss_coding.h"
/**
* @brief VSS code generator coding class.
* Beside the definition of the basic service interface also information about the vehicle device is necessary
* These 2 definitions must match, there must be a corresponding 'signalVD' definition
* the function container of the basic service signal must match the function container if the 'signalVD'
* Creates the code out of templates
*/
class CVSSBSCodingRX : public CCodeGeneratorBase, CVSSHelper
{
public:
/**
* @brief create service content for the IDL file of a RX signal
* @param[in] vssParts Interface in vss style separated in parts
* @param[in] vecFunctions container of all functions of a single vss definition
* @return content of the Device part of a IDL Interface of a RX signal
*/
std::string Code_RXIDLServiceList(const std::vector<std::string>& vssParts, const std::vector <SFunctionBSDefinition>& vecFunctions) const;
/**
* @brief fill the KeyWordMap with all required strings
* @param[in] signal signal definition structure to fill the KeyWordMap
* @param[in] signalVD signal definition structure from vehicle device
* @param[in] mapKeywords KeyWordMap to be filled
*/
void GetKeyWordMap(const SSignalBSDefinition& signal, const SSignalVDDefinition& signalVD, CKeywordMap& mapKeywords) const;
protected:
/**
* @brief create single or multiple lines containing include files
* @param[in] vssOriginalNoDot vss string without points e.g. VehicleChassisSteeringWheelAngle
* @return content of a single interface
*/
std::string Code_BS_RXIncludes(const std::string& vssOriginalNoDot) const;
/**
* @brief create a single line containing a interface
* @param[in] functionName function which is part of the interface
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @param[in] vd_functionName function name (Vehicle Device)
* @param[in] vd_vssWithColons vss string (complete version) with colons as separator (Vehicle Device)
* @return content of a single interface
*/
std::string Code_BS_RXInterface(const std::string& functionName, const std::string& vssWithColons,
const std::string& vd_functionName, const std::string& vd_vssWithColons) const;
/**
* @brief create a single line containing a interface entry
* @param[in] functionName function which is part of the interface
* @param[in] vssWithColons vss string (short version) with colons as separator
* @return content of a single interface entry
*/
std::string Code_BS_RXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const;
/**
* @brief Get the register and unregister part for the RX VD header
* @param[in] vssWithColons vss string with colons as separator
* @param[in] function function definition structure (Basic Service)
* @param[in] functionVD function definition structure of vehicle device (Vehicle Device)
* @return content of a single register and unregister part.
*/
std::string Code_BS_RXReAndUnregisterEvent(const std::string& vssWithColons, const SFunctionBSDefinition& function,
const SFunctionVDDefinition& functionVD) const;
/**
* @brief Get the private header part of the basic service header
* @param[in] function function definition structure
* @param[in] vssWithColons vss string with colons as separator
* @return content of private header part of the basic service header
*/
std::string Code_BS_RXPrivateHeaderPart(const SFunctionBSDefinition& function, const std::string& vssWithColons) const;
/**
* @brief create service content for the IDL file of a RX signal
* @param[in] spaces string containing only space characters for aligning
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @param[in] function function definition structure
* @return content of the Device part of a IDL Interface of a RX signal
*/
std::string Code_RXIDLServiceInterface(const std::string& spaces, const std::string& vssWithColons,
const SFunctionBSDefinition& function) const;
/**
* @brief unregister signal Event
* @param[in] signalVD signal definition structure to fill the KeyWordMap (Vehicle Device)
* @param[in] vd_vssWithColons vss string (complete version) with colons as separator (Vehicle Device)
* @param[in] functionVD function definition structure (Vehicle Device)
* @param[in] function function definition structure (Basic Service)
* @return content of a unregister code
*/
std::string Code_BS_RXConstructor(const SSignalVDDefinition& signalVD, const std::string& vd_vssWithColons,
const SFunctionVDDefinition& functionVD, const SFunctionBSDefinition& function) const;
/**
* @brief unregister signal Event
* @param[in] signalVD signal definition structure to fill the KeyWordMap (Vehicle Device)
* @param[in] vd_vssWithColons vss string (complete version) with colons as separator (Vehicle Device)
* @param[in] functionVD function definition structure (Vehicle Device)
* @return content of a unregister code
*/
std::string Code_BS_RXDestructor(const SSignalVDDefinition& signalVD, const std::string& vd_vssWithColons,
const SFunctionVDDefinition& functionVD) const;
/**
* @brief set and get functions for basic service
* @param[in] class_name class name which is part of the interface (Basic Service)
* @param[in] function function definition structure (Basic Service)
* @param[in] functionVD function definition structure (Vehicle Device)
* @return content of a single set and get function code
*/
std::string Code_BS_RXGetAndSetFunctions(const std::string& class_name, const SFunctionBSDefinition& function,
const SFunctionVDDefinition& functionVD) const;
/**
* @brief create register/unregister code for basic service
* @param[in] class_name class name which is part of the interface
* @param[in] function function definition structure
* @param[in] vssWithColons vss string with colons as separator
* @return content of a single signal register/unregister code
*/
std::string Code_BS_RXRegister(const std::string& class_name, const SFunctionBSDefinition& function,
const std::string& vssWithColons) const;
};
#endif // !defined VSS_BS_CODING_RX_H

View File

@@ -0,0 +1,249 @@
#include "vss_bs_codingtx.h"
void CVSSBSCodingTX::GetKeyWordMap(const SSignalBSDefinition& signal, const SSignalVDDefinition& signalVD, CKeywordMap& mapKeywords) const
{
std::string vd_vssWithColons = ReplaceCharacters(signal.vssVDDefinition, ".", "::");
std::string vssWithColons = ReplaceCharacters(signal.vssDefinition, ".", "::");
//------------------------------------------------------- basic service header
std::stringstream sstreamIncludesBS;
std::string vd_vssNoDot = ReplaceCharacters(signal.vssVDDefinition, ".", "");
std::string vssNoDot = ReplaceCharacters(signal.vssDefinition, ".", "");
std::transform(vd_vssNoDot.begin(), vd_vssNoDot.end(), vd_vssNoDot.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
std::transform(vssNoDot.begin(), vssNoDot.end(), vssNoDot.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
sstreamIncludesBS << Code_BS_TXIncludes(vd_vssNoDot, vssNoDot);
mapKeywords["tx_bs_includes_list"] = std::move(sstreamIncludesBS.str());
std::stringstream sstreamInterfacesBS;
for (const auto& func : signal.vecFunctions)
{
sstreamInterfacesBS << Code_BS_TXInterface(func.functionName, vssWithColons);
}
mapKeywords["tx_bs_interface_list"] = std::move(sstreamInterfacesBS.str());
std::stringstream sstreamInterfaceEntriesBS;
for (const auto& func : signal.vecFunctions)
{
sstreamInterfaceEntriesBS << Code_BS_TXInterfaceEntry(func.functionName, vssWithColons);
}
mapKeywords["tx_bs_interface_entry_list"] = std::move(sstreamInterfaceEntriesBS.str());
std::stringstream sstreamFunctionsBS;
for (const auto& func : signal.vecFunctions)
{
sstreamFunctionsBS << Code_BS_TXFunction(func);
}
mapKeywords["tx_bs_function_list"] = std::move(sstreamFunctionsBS.str());
std::stringstream sstreamVariablePointers;
for (const auto& func : signalVD.vecFunctions)
{
sstreamVariablePointers << Code_BS_TXVariablePointerFromVD(func, vd_vssWithColons);
}
mapKeywords["tx_bs_variable_pointer_list"] = std::move(sstreamVariablePointers.str());
//------------------------------------------------------- basic service cpp
std::stringstream sstreamVariablePointerInitializations;
for (const auto& func : signalVD.vecFunctions)
{
sstreamVariablePointerInitializations << Code_BS_TXVariablePointerInitializationFromVD(func,
signal.className, signal.vssDefinition, vd_vssWithColons);
}
mapKeywords["tx_bs_variable_pointer_init_list"] = std::move(sstreamVariablePointerInitializations.str());
std::stringstream sstreamPointerFunctionImplementation;
for (uint32_t index = 0; index < signal.vecFunctions.size(); index++)
{
if (index >= signalVD.vecFunctions.size())
break;
auto func = signal.vecFunctions[index];
auto funcVD = signalVD.vecFunctions[index];
sstreamPointerFunctionImplementation << Code_BS_TXFunctionPointerImplementationFromVD(func, funcVD, signal.className);
}
mapKeywords["vd_tx_pointer_function_implementations"] = std::move(sstreamPointerFunctionImplementation.str());
}
std::string CVSSBSCodingTX::Code_BS_TXIDLList(const std::vector<std::string>& vssParts,
const std::vector <SFunctionBSDefinition>& vecFunctions) const
{
int8_t loop = 1;
std::string nameSpace = "module vss\n{\n";
for (auto it = vssParts.begin(); it != vssParts.end(); ++it)
{
nameSpace.append(static_cast <int8_t>(4) * loop, ' ');
nameSpace.append("module ");
nameSpace.append(*it);
if (it == vssParts.end() - 1)
{
nameSpace.append("Service");
}
nameSpace.append("\n");
nameSpace.append(static_cast <int8_t>(4) * loop++, ' ');
nameSpace.append("{\n");
}
nameSpace.append("%interfaces%");
loop--;
for (size_t i = 0; i < vssParts.size() + 1; i++)
{
nameSpace.append(static_cast <int8_t>(4) * loop--, ' ');
nameSpace.append("};\n");
}
bool newLine = false;
std::string spaces = "";
spaces.append(static_cast <int8_t>(4) * (vssParts.size() + 1), ' ');
std::stringstream sstreamInterfaces;
for (const auto& func : vecFunctions)
{
if (newLine)
sstreamInterfaces << "\n\n";
else
newLine = true;
sstreamInterfaces << Code_BS_TXIDLInterface(spaces, func);
}
CKeywordMap mapKeywords;
mapKeywords["interfaces"] = std::move(sstreamInterfaces.str());
return ReplaceKeywords(nameSpace, mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXIncludes(const std::string& vd_vssOriginalNoDot, const std::string& vssOriginalNoDot) const
{
CKeywordMap mapKeywords;
mapKeywords["vd_vss_original_no_dot"] = vd_vssOriginalNoDot;
mapKeywords["vss_original_no_dot"] = vssOriginalNoDot;
return ReplaceKeywords(R"code(#include "../vss_%vd_vss_original_no_dot%_vd_tx.h"
#include "../vss_%vss_original_no_dot%_bs_tx.h"
)code", mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXInterface(const std::string& functionName, const std::string& vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vss_with_colons"] = vssWithColons;
return ReplaceKeywords(R"code( , public vss::%vss_with_colons%Service::IVSS_Set%function_name%
)code", mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vss_with_colons"] = vssWithColons;
return ReplaceKeywords(R"code( SDV_INTERFACE_ENTRY(vss::%vss_with_colons%Service::IVSS_Set%function_name%)
)code", mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXIDLInterface(const std::string& spaces, const SFunctionBSDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_idltype"] = function.idlType;
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
mapKeywords["multiple_spaces"] = spaces;
return ReplaceKeywords(R"code(%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_Set%function_name% Service interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_Set%function_name%
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Set %signal_name% signal
%multiple_spaces% * @param[in] value
%multiple_spaces% * @return true on success otherwise false
%multiple_spaces% */
%multiple_spaces% boolean Set%function_name%(in %value_idltype% value);
%multiple_spaces%};
)code", mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXFunction(const SFunctionBSDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_idltype"] = function.idlType;
auto signalType = GetCTypeFromIDLType(function.idlType);
mapKeywords["value_ctype"] = CastValueType(signalType);
return ReplaceKeywords(R"code(
/**
* @brief Set %signal_name% signal
* @param[in] value
* @return true on success otherwise false
*/
bool Set%function_name%(%value_ctype% value) override;
)code", mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXVariablePointerFromVD(const SFunctionVDDefinition& functionVD,
const std::string& vd_vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["vd_function_name"] = functionVD.functionName;
mapKeywords["vd_vss_with_colons"] = vd_vssWithColons;
return ReplaceKeywords(R"code(
vss::%vd_vss_with_colons%Device::IVSS_Write%vd_function_name%* m_ptr%vd_function_name% = nullptr;)code", mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXFunctionPointerImplementationFromVD(const SFunctionBSDefinition& function,
const SFunctionVDDefinition& functionVD, const std::string& className) const
{
std::string class_name_lowercase = className;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["vd_function_name"] = functionVD.functionName;
mapKeywords["class_name"] = className;
mapKeywords["value_idltype"] = function.idlType;
auto signalType = GetCTypeFromIDLType(function.idlType);
mapKeywords["value_ctype"] = CastValueType(signalType);
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
/**
* @brief %function_name%
* @param[in] value
* @return true on success otherwise false
*/
bool CBasicService%class_name%::Set%function_name%(%value_ctype% value)
{
return m_ptr%vd_function_name%->Write%vd_function_name%(value);
}
)code", mapKeywords);
}
std::string CVSSBSCodingTX::Code_BS_TXVariablePointerInitializationFromVD(const SFunctionVDDefinition& functionVD,
const std::string& className, const std::string& vssOriginal, const std::string& vd_vssWithColons) const
{
std::string class_name_lowercase = className;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["vd_function_name"] = functionVD.functionName;
mapKeywords["class_name"] = className;
mapKeywords["vd_vss_original"] = vssOriginal;
mapKeywords["vd_vss_with_colons"] = vd_vssWithColons;
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
m_ptr%vd_function_name% = sdv::core::GetObject("%vd_vss_original%_Device").GetInterface<vss::%vd_vss_with_colons%Device::IVSS_Write%vd_function_name%>();
if (!m_ptr%vd_function_name%)
{
SDV_LOG_ERROR("Could not get interface 'IVSS_Write%vd_function_name%': [CBasicService%class_name%]");
throw std::runtime_error("%vd_function_name% device not found");
}
)code", mapKeywords);
}

View File

@@ -0,0 +1,114 @@
#ifndef VSS_BS_CODING_TX_H
#define VSS_BS_CODING_TX_H
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <interfaces/dispatch.h>
#include "codegen_base.h"
#include "vss_helper.h"
#include "vss_tx_templates.h"
#include "vss_coding.h"
/**
* @brief VSS code generator coding class.
* Beside the definition of the basic service interface also information about the vehicle device is necessary
* These 2 definitions must match, there must be a corresponding 'signalVD' definition
* the function container of the basic service signal must match the function container if the 'signalVD'
* Creates the code out of templates
*/
class CVSSBSCodingTX : public CCodeGeneratorBase, CVSSHelper
{
public:
/**
* @brief create basic service content for the IDL file of a TX signal
* @param[in] vssParts Interface in vss style separated in parts
* @param[in] vecFunctions container of all functions of a single (basic service) vss definition (basic service)
* @return content of the basic service part of a IDL Interface of a TX signal
*/
std::string Code_BS_TXIDLList(const std::vector<std::string>& vssParts, const std::vector <SFunctionBSDefinition>& vecFunctions) const;
/**
* @brief fill the KeyWordMap with all required strings
* @param[in] signal signal definition structure to fill the KeyWordMap
* @param[in] signalVD signal definition structure from vehicle device
* @param[in] mapKeywords KeyWordMap to be filled
*/
void GetKeyWordMap(const SSignalBSDefinition& signal, const SSignalVDDefinition& signalVD, CKeywordMap& mapKeywords) const;
protected:
/**
* @brief create single or multiple lines containing include files
* @param[in] vd_vssOriginalNoDot vss string without points of the corresponding vehicle device
* @param[in] vssOriginalNoDot vss string without points e.g. VehicleChassisSteeringWheelAngle
* @return content of a single interface
*/
std::string Code_BS_TXIncludes(const std::string& vd_vssOriginalNoDot, const std::string& vssOriginalNoDot) const;
/**
* @brief create a single line containing a interface for basic service
* @param[in] functionName function which is part of the interface
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @return content of a single interface
*/
std::string Code_BS_TXInterface(const std::string& functionName, const std::string& vssWithColons) const;
/**
* @brief create a single line containing a interface entry for basic service
* @param[in] functionName function which is part of the interface
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @return content of a single interface entry
*/
std::string Code_BS_TXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const;
/**
* @brief create list of interfaces (TX signals) for IDL file (Basic Service)
* @param[in] spaces string containing only space characters for aligning
* @param[in] function function definition structure
* @return content of a single interface entry
*/
std::string Code_BS_TXIDLInterface(const std::string& spaces, const SFunctionBSDefinition& function) const;
/**
* @brief create function definition part (TX signals) for basic service
* @param[in] function function definition structure
* @return content of a single function declaration
*/
std::string Code_BS_TXFunction(const SFunctionBSDefinition& function) const;
/**
* @brief create definition of a interface pointer (TX signals) for basic service header file
* @param[in] functionVD which is part of the interface (Vehicle Device)
* @param[in] vd_vssWithColons vss string (complete version) with colons as separator (Vehicle Device)
* @return content of a definition of a interface pointer
*/
std::string Code_BS_TXVariablePointerFromVD(const SFunctionVDDefinition& functionVD, const std::string& vd_vssWithColons) const;
/**
* @brief create function pointer implementation part (TX signals) for basic service cpp file
* @param[in] function function definition structure (Basic Service)
* @param[in] functionVD function definition structure from vehicle device (Vehicle Device)
* @param[in] className class name of the signal (Basic Service)
* @return content of a single function pointer implementation
*/
std::string Code_BS_TXFunctionPointerImplementationFromVD(const SFunctionBSDefinition& function,
const SFunctionVDDefinition& functionVD, const std::string& className) const;
/**
* @brief create check if a interface pointer is valid (TX signals) for IDL file
* @param[in] functionVD which is part of the interface (Vehicle Device)
* @param[in] className class name of the signal (Basic Service)
* @param[in] vssOriginal original vvs string (Basic Service)
* @param[in] vd_vssWithColons vss string (complete version) with colons as separator (Vehicle Device)
* @return content of a check if a interface pointer is valid
*/
std::string Code_BS_TXVariablePointerInitializationFromVD(const SFunctionVDDefinition& functionVD, const std::string& className,
const std::string& vssOriginal, const std::string& vd_vssWithColons) const;
};
#endif // !defined VSS_BS_CODING_TX_H

View File

@@ -0,0 +1,250 @@
#include "vss_bs_generator.h"
#include "vss_coding.h"
#include "vss_bs_codingrx.h"
#include "vss_bs_codingtx.h"
bool CVSSBSGenerator::GeneratedCode()
{
// Create project directory
if (!m_pathProject.empty())
{
m_pathProject /= "vss_files";
if (CreateFolder(m_pathProject, ""))
{
//CVSSCodingCommon coding(m_ssPrefix);
CreateFiles(m_ssVersion);
return true;
}
}
return false;
}
std::string CVSSBSGenerator::AppendExtension(const std::string& prefix, const std::string& filename,
const std::string& extension) const
{
return prefix + filename + extension;
}
void CVSSBSGenerator::CreateFiles(const std::string& ssVersion)
{
for (const SSignalBSDefinition& signal : m_signals)
{
if (signal.signalDirection == sdv::core::ESignalDirection::sigdir_rx)
m_RXsignals.push_back(signal);
else
m_TXsignals.push_back(signal);
}
CreateRXFiles(ssVersion);
CreateTXFiles(ssVersion);
}
void CVSSBSGenerator::CreateRXFiles(const std::string& ssVersion) const
{
for (const auto& rxSignal : m_RXsignals)
{
if (m_enableComponentCreation)
{
CreateBasicServiceFilesForRXSignal(rxSignal, ssVersion);
}
CreateIDLBasicServiceFileForRXSignal(rxSignal, ssVersion);
}
}
void CVSSBSGenerator::CreateBasicServiceFilesForRXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const
{
std::string folderName = "BS_";
folderName.append(signal.className);
std::transform(folderName.begin(), folderName.end(), folderName.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
if (!CreateFolder(m_pathProject, folderName))
{
return;
}
std::filesystem::path pathBSHeader = m_pathProject / folderName / AppendExtension("BS_", signal.className, ".h");
std::filesystem::path pathBSClass = m_pathProject / folderName / AppendExtension("BS_", signal.className, ".cpp");
std::filesystem::path pathCMakeLists = m_pathProject / folderName / "CMakeLists.txt";
std::ofstream fstreamBSHeader;
std::ofstream fstreamBSClass;
auto pathLowerCaseHeader = MakeLowercaseFilename(pathBSHeader);
auto pathLowerCaseClass = MakeLowercaseFilename(pathBSClass);
fstreamBSHeader.open(pathLowerCaseHeader, std::ios::out | std::ios::trunc);
fstreamBSClass.open(pathLowerCaseClass, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["bs_safeguard"] = coding.Code_SafeGuard(pathBSHeader.filename().generic_u8string());
mapKeywords["basic_service_h"] = pathLowerCaseHeader.filename().generic_u8string();
mapKeywords["basic_service_cpp"] = pathLowerCaseClass.filename().generic_u8string();
CVSSBSCodingRX codingRX;
auto signalVD = GetVDSignal(signal.vssVDDefinition);
if (!signalVD.vecFunctions.size())
{
mapKeywords["vss_from_vd_not_found"] = "// corresponding vehicle device interface not found";
}
codingRX.GetKeyWordMap(signal, signalVD, mapKeywords);
fstreamBSHeader << ReplaceKeywords(szRXBasicServiceHeaderTemplate, mapKeywords);
fstreamBSClass << ReplaceKeywords(szRXBasicServiceClassTemplate, mapKeywords);
fstreamBSHeader.close();
fstreamBSClass.close();
std::string classNameLowerCase = signal.className;
std::transform(classNameLowerCase.begin(), classNameLowerCase.end(), classNameLowerCase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
std::string libaryName = m_ssPrefix + "_bs_" + classNameLowerCase + "_rx";
auto cmakeContent = coding.Code_CMakeProject(libaryName, folderName);
CreateCMakeFile(pathCMakeLists, cmakeContent);
}
void CVSSBSGenerator::CreateIDLBasicServiceFileForRXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const
{
std::stringstream ss(signal.vssDefinition);
std::string item;
std::string filenameBS = "VSS_";
std::vector<std::string> parts;
while (std::getline(ss, item, '.'))
{
parts.push_back(item);
filenameBS.append(item);
}
filenameBS.append("_bs_rx");
DeleteHeaderFile(m_pathProject, filenameBS);
filenameBS.append(".idl");
std::filesystem::path pathBSRXIDL = m_pathProject / filenameBS;
std::ofstream fstreamBSRXIDL;
auto pathLowerCase = MakeLowercaseFilename(pathBSRXIDL);
fstreamBSRXIDL.open(pathLowerCase, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["_bs_idl_h"] = pathLowerCase.filename().generic_u8string();
CVSSBSCodingRX codingRX;
mapKeywords["vss_service"] = codingRX.Code_RXIDLServiceList(parts, signal.vecFunctions);
std::string vdIDLFileLowerCase = "vss_";
vdIDLFileLowerCase.append(ReplaceCharacters(signal.vssVDDefinition, ".", ""));
vdIDLFileLowerCase.append("_vd_rx.idl");
std::transform(vdIDLFileLowerCase.begin(), vdIDLFileLowerCase.end(), vdIDLFileLowerCase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
mapKeywords["vd_idl_file"] = vdIDLFileLowerCase;
auto signalVD = GetVDSignal(signal.vssVDDefinition);
if (signalVD.vecFunctions.size())
{
std::string vssNoDot = ReplaceCharacters(signal.vssVDDefinition, ".", "");
mapKeywords["vd_vss_original_no_dot"] = vssNoDot;
}
else
{
mapKeywords["vss_device"] = "// corresponding vehicle device interface not found";
}
fstreamBSRXIDL << ReplaceKeywords(szBSRXIDLTemplate, mapKeywords);
fstreamBSRXIDL.close();
}
void CVSSBSGenerator::CreateTXFiles(const std::string& ssVersion) const
{
for (const auto& txSignal : m_TXsignals)
{
if (m_enableComponentCreation)
{
CreateBasicServiceFilesForTXSignal(txSignal, ssVersion);
}
CreateIDLBasicServiceFileForTXSignal(txSignal, ssVersion);
}
}
void CVSSBSGenerator::CreateBasicServiceFilesForTXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const
{
std::string folderName = "BS_";
folderName.append(signal.className);
std::transform(folderName.begin(), folderName.end(), folderName.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
if (!CreateFolder(m_pathProject, folderName))
{
return;
}
std::filesystem::path pathBSHeader = m_pathProject / folderName / AppendExtension("BS_", signal.className, ".h");
std::filesystem::path pathBSClass = m_pathProject / folderName / AppendExtension("BS_", signal.className, ".cpp");
std::filesystem::path pathCMakeLists = m_pathProject / folderName / "CMakeLists.txt";
std::ofstream fstreamBSHeader;
std::ofstream fstreamBSClass;
auto pathLowerCaseHeader = MakeLowercaseFilename(pathBSHeader);
auto pathLowerCaseClass = MakeLowercaseFilename(pathBSClass);
fstreamBSHeader.open(pathLowerCaseHeader, std::ios::out | std::ios::trunc);
fstreamBSClass.open(pathLowerCaseClass, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["bs_safeguard"] = coding.Code_SafeGuard(pathBSHeader.filename().generic_u8string());
mapKeywords["basic_service_h"] = pathLowerCaseHeader.filename().generic_u8string();
mapKeywords["basic_service_cpp"] = pathLowerCaseClass.filename().generic_u8string();
CVSSBSCodingTX codingTX;
auto signalVD = GetVDSignal(signal.vssVDDefinition);
if (!signalVD.vecFunctions.size())
{
mapKeywords["vss_from_vd_not_found"] = "// corresponding vehicle device interface not found";
}
codingTX.GetKeyWordMap(signal, signalVD, mapKeywords);
mapKeywords["basic_service_h"] = pathBSHeader.filename().generic_u8string();
mapKeywords["basic_service_cpp"] = pathBSClass.filename().generic_u8string();
fstreamBSHeader << ReplaceKeywords(szTXBasicServiceHeaderTemplate, mapKeywords);
fstreamBSClass << ReplaceKeywords(szTXBasicServiceClassTemplate, mapKeywords);
fstreamBSHeader.close();
fstreamBSClass.close();
std::string classNameLowerCase = signal.className;
std::transform(classNameLowerCase.begin(), classNameLowerCase.end(), classNameLowerCase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
std::string libaryName = m_ssPrefix + "_bs_" + classNameLowerCase + "_tx";
auto cmakeContent = coding.Code_CMakeProject(libaryName, folderName);
CreateCMakeFile(pathCMakeLists, cmakeContent);
}
void CVSSBSGenerator::CreateIDLBasicServiceFileForTXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const
{
std::stringstream ss(signal.vssDefinition);
std::string item;
std::string filenameBS = "VSS_";
std::vector<std::string> parts;
while (std::getline(ss, item, '.'))
{
parts.push_back(item);
filenameBS.append(item);
}
filenameBS.append("_bs_tx");
DeleteHeaderFile(m_pathProject, filenameBS);
filenameBS.append(".idl");
std::filesystem::path pathBSTXIDL = m_pathProject / filenameBS;
std::ofstream fstreamBSTXIDL;
auto pathLowerCase = MakeLowercaseFilename(pathBSTXIDL);
fstreamBSTXIDL.open(pathLowerCase, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["_bs_idl_h"] = pathLowerCase.filename().generic_u8string();
CVSSBSCodingTX codingTX;
mapKeywords["vss_service"] = codingTX.Code_BS_TXIDLList(parts, signal.vecFunctions);
fstreamBSTXIDL << ReplaceKeywords(szBSTXIDLTemplate, mapKeywords);
fstreamBSTXIDL.close();
}

View File

@@ -0,0 +1,127 @@
#ifndef VSS_BS_GENERATOR_H
#define VSS_BS_GENERATOR_H
#include <fstream>
#include "codegen_base.h"
#include "vss_helper.h"
/**
* @brief Basic Service generator.
*/
class CVSSBSGenerator : public CCodeGeneratorBase, CVSSHelper
{
public:
/**
* @brief Constructor
* @param[in] signals Reference to a vector containing all signals (basic services)
* @param[in] signalsVD Reference to a vector containing all signals (vehicle device)
* @param[in] rpathOutputDir Reference to the outpur directory.
* @param[in] rsPrefix used by cmake library and signal definition in signal_identifier.h file
* @param[in] rsVersion optional version tag, will be wriiten in header of the files
* @param[in] enableComponentCreation optional version tag, will be wriiten in header of the files
*/
CVSSBSGenerator(const std::vector<SSignalBSDefinition>& signals, const std::vector<SSignalVDDefinition>& signalsVD, const std::filesystem::path& rpathOutputDir, const std::string& rsPrefix,
const std::string& rsVersion, const bool enableComponentCreation) :
m_enableComponentCreation(enableComponentCreation),
m_ssPrefix(rsPrefix),
m_ssVersion(rsVersion),
m_pathProject(rpathOutputDir),
m_signals(signals),
m_signalsVD(signalsVD)
{}
/**
* @brief Auto generate the Files
* @return true on success, otherwise false
*/
bool GeneratedCode();
private:
/**
* @brief create a file name including prefix and extension
* @param[in] prefix
* @param[in] filename
* @param[in] extension
* @return combined file name
*/
std::string AppendExtension(const std::string& prefix, const std::string& filename, const std::string& extension) const;
/**
* @brief create vehicle device and basic service .h an .cpp files
* create IDL files
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateFiles(const std::string& ssVersion);
/**
* @brief create IDL files and vehicle device and basic service files of RX signals
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateRXFiles(const std::string& ssVersion) const;
/**
* @brief create basic service files of a single RX signal
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateBasicServiceFilesForRXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const;
/**
* @brief create IDL file of a single RX signal (basic service)
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateIDLBasicServiceFileForRXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const;
/**
* @brief create IDL files and vehicle device and basic service files of TX signals
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateTXFiles(const std::string& ssVersion) const;
/**
* @brief create basic service files of a single TX signal
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateBasicServiceFilesForTXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const;
/**
* @brief create IDL file for a single TX signal (basic service)
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateIDLBasicServiceFileForTXSignal(const SSignalBSDefinition& signal, const std::string& ssVersion) const;
/**
* @brief find a vss definition in the signal list of the vehicle device collection and return the signal
* @param[in] vssDefinition vss name
* @return signal if a signal was found, otherwise a empty signal definition
*/
SSignalVDDefinition GetVDSignal(const std::string& vssDefinition) const
{
SSignalVDDefinition noSignal;
for (const auto& signal : m_signalsVD)
{
if (signal.vssDefinition.compare(vssDefinition) == 0)
{
return signal;
}
}
return noSignal;
}
bool m_enableComponentCreation; ///< if set, the code for the components are created, otherwise only idl files
std::string m_ssPrefix; ///< prefix, used by cmake library and signal definition in signal_identifier.h file.
std::string m_ssVersion; ///< optional version tag, will be wriiten in header of the files
std::filesystem::path m_pathProject; ///< Project file path
std::vector <SSignalBSDefinition> m_signals; ///< all signals
std::vector <SSignalVDDefinition> m_signalsVD; ///< all signals
std::vector <SSignalBSDefinition> m_TXsignals; ///< vector containing the RX signals
std::vector <SSignalBSDefinition> m_RXsignals; ///< vector containing the TX signals
};
#endif // !defined VSS_BS_GENERATOR_H

View File

@@ -0,0 +1,256 @@
#include "vss_coding.h"
void CVSSCodingCommon::GetCommonKeyWordMap(const SSignalVDDefinition& signal, CKeywordMap& mapKeywords, const std::string& rsVersion) const
{
CVSSCodingCommon coding(m_ssPrefix);
//---------------------------------------------------------------------------------------------- Common file
auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream sstreamDate;
sstreamDate << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
mapKeywords["creation_date"] = sstreamDate.str();
mapKeywords["version"] = coding.Code_VSSFileVersion(rsVersion);
//---------------------------------------------------------------------------------------------- Common
// original vss example: Vehicle.Chassis.SteeringWheel.Angle
// vssNoDot: VehicleChassisSteeringWheelAngle
// vssWithUnderscores: Vehicle_Chassis_SteeringWheel_Angle
// vssUppercase: VEHICLE_CHASSIS_STEERINGWHEEL_ANGLE
// vssWithColons: Vehicle::Chassis::SteeringWheel::Angle
// vssShorten: Vehicle.Chassis.SteeringWheel
// vssShortenNoDot: VehicleChassisSteeringWheel
// vssShortenWithColons: Vehicle::Chassis::SteeringWheel
mapKeywords["vss_original"] = signal.vssDefinition;
std::string vssNoDot = ReplaceCharacters(signal.vssDefinition, ".", "");
std::string vssWithUnderscores = ReplaceCharacters(signal.vssDefinition, ".", "_");
std::string vssUppercase = ToUpper(vssWithUnderscores);
std::string vssWithColons = ReplaceCharacters(signal.vssDefinition, ".", "::");
std::string vssShorten = ShortenVSSString(signal.vssDefinition);
std::string vssShortenNoDot = ReplaceCharacters(vssShorten, ".", "");
std::string vssShortenWithColons = ReplaceCharacters(vssShorten, ".", "::");
std::string class_name_lowercase = signal.className;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
mapKeywords["vss_original_no_dot"] = vssNoDot;
mapKeywords["vss_uppercase"] = vssUppercase;
mapKeywords["vss_with_colons"] = vssWithColons;
mapKeywords["vss_shorten"] = vssShorten;
mapKeywords["vss_shorten_no_dot"] = vssShortenNoDot;
mapKeywords["vss_shorten_with_colons"] = vssShortenWithColons;
mapKeywords["class_name"] = signal.className;
mapKeywords["class_name_lowercase"] = class_name_lowercase;
}
void CVSSCodingCommon::GetCommonKeyWordMap(const SSignalBSDefinition& signal, CKeywordMap& mapKeywords, const std::string& rsVersion) const
{
CVSSCodingCommon coding(m_ssPrefix);
//---------------------------------------------------------------------------------------------- Common file
auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream sstreamDate;
sstreamDate << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
mapKeywords["creation_date"] = sstreamDate.str();
mapKeywords["version"] = coding.Code_VSSFileVersion(rsVersion);
//---------------------------------------------------------------------------------------------- Common
// original vss example: Vehicle.Chassis.SteeringWheel.Angle
// vssNoDot: VehicleChassisSteeringWheelAngle
// vssWithUnderscores: Vehicle_Chassis_SteeringWheel_Angle
// vssUppercase: VEHICLE_CHASSIS_STEERINGWHEEL_ANGLE
// vssWithColons: Vehicle::Chassis::SteeringWheel::Angle
// vssShorten: Vehicle.Chassis.SteeringWheel
// vssShortenNoDot: VehicleChassisSteeringWheel
// vssShortenWithColons: Vehicle::Chassis::SteeringWheel
mapKeywords["vss_original"] = signal.vssDefinition;
std::string vssNoDot = ReplaceCharacters(signal.vssDefinition, ".", "");
std::string vssWithUnderscores = ReplaceCharacters(signal.vssDefinition, ".", "_");
std::string vssUppercase = ToUpper(vssWithUnderscores);
std::string vssWithColons = ReplaceCharacters(signal.vssDefinition, ".", "::");
std::string vssShorten = ShortenVSSString(signal.vssDefinition);
std::string vssShortenNoDot = ReplaceCharacters(vssShorten, ".", "");
std::string vssShortenWithColons = ReplaceCharacters(vssShorten, ".", "::");
std::string class_name_lowercase = signal.className;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
mapKeywords["vss_original_no_dot"] = vssNoDot;
mapKeywords["vss_uppercase"] = vssUppercase;
mapKeywords["vss_with_colons"] = vssWithColons;
mapKeywords["vss_shorten"] = vssShorten;
mapKeywords["vss_shorten_no_dot"] = vssShortenNoDot;
mapKeywords["vss_shorten_with_colons"] = vssShortenWithColons;
mapKeywords["class_name"] = signal.className;
mapKeywords["class_name_lowercase"] = class_name_lowercase;
}
std::string CVSSCodingCommon::Code_VSSFileVersion(const std::string& ssVersion) const
{
std::string version = ".";
CKeywordMap mapKeywords;
if (!ssVersion.empty())
{
version = "\n * VSS Version:" + ssVersion;
}
mapKeywords["version"] = version;
return ReplaceKeywords(R"code(File is auto generated from VSS utility%version%)code", mapKeywords);
}
std::string CVSSCodingCommon::Code_SafeGuard(const std::string& ssFileName) const
{
auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::string startWith = "__VSS_GENERATED__" + ssFileName + "_";
std::stringstream sstreamSafeguard;
sstreamSafeguard << ToUpper(ReplaceCharacters(startWith, ".", "_")); //"__DBC_GENERATED__CONFIG_H__";
sstreamSafeguard << std::put_time(std::localtime(&in_time_t), "%Y%m%d_%H%M%S") << "_";
sstreamSafeguard << std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
sstreamSafeguard << "__";
return sstreamSafeguard.str();
}
std::string CVSSCodingCommon::Code_SignalIdentifier(const std::vector <SSignalVDDefinition>& allSignals,
const std::string& ssFileName, const std::string& ssVersion) const
{
CKeywordMap mapKeywords;
if (allSignals.size() > 0)
{
std::string signalTitle = "signal names";
std::string canSignalTitle = "dbc variable names";
std::string cTypeTitle = "C-type";
std::string directionTitle = "RX/TX";
auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream sstreamDate;
sstreamDate << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
mapKeywords["creation_date"] = sstreamDate.str();
mapKeywords["version"] = Code_VSSFileVersion(ssVersion);
mapKeywords["file_name"] = ssFileName;
mapKeywords["safeguard"] = Code_SafeGuard(ssFileName);
mapKeywords["object_prefix"] = m_ssPrefix;
mapKeywords["signals"] = Code_AllSignalsIdentifierList(allSignals, signalTitle, canSignalTitle, cTypeTitle);
mapKeywords["spaces01"] = Align(signalTitle, GetMaxSignalName(allSignals, signalTitle) + 1);
mapKeywords["spaces02"] = Align(canSignalTitle, GetMaxCANSignalName(allSignals, canSignalTitle) + 1);
mapKeywords["spaces03"] = Align(cTypeTitle, GetMaxCTypeFromIDLType(allSignals, cTypeTitle));
mapKeywords["spaces04"] = Align(directionTitle, directionTitle.size() + 1);
}
return ReplaceKeywords(R"code(/**
* @file %file_name%
* @date %creation_date%
* %version%
*/
#ifndef %safeguard%
#define %safeguard%
namespace %object_prefix%
{
// Data Dispatch Service %spaces01%to %spaces02% %spaces03% %spaces04% vss name space
%signals%} // %object_prefix%
#endif // %safeguard%
)code", mapKeywords);
}
std::string CVSSCodingCommon::Code_AllSignalsIdentifierList(const std::vector <SSignalVDDefinition>& allSignals,
const std::string& signalTitle, const std::string& canSignalTitle, const std::string& cTypeTitle) const
{
CKeywordMap mapKeywords;
std::stringstream sstreamSignals;
for (const auto& signal : allSignals)
{
for (auto func : signal.vecFunctions)
{
sstreamSignals << Code_SignalIdentifierList(allSignals, signal, func, signalTitle, canSignalTitle, cTypeTitle);
}
}
mapKeywords["signals_list"] = std::move(sstreamSignals.str());
return ReplaceKeywords(R"code(%signals_list%)code", mapKeywords);
}
std::string CVSSCodingCommon::Code_SignalIdentifierList(const std::vector <SSignalVDDefinition>& allSignals, const SSignalVDDefinition& signal,
const SFunctionVDDefinition& func, const std::string& signalTitle, const std::string& canSignalTitle, const std::string& cTypeTitle) const
{
CKeywordMap mapKeywords;
auto startWithUppercase = Align(func.signalName, GetMaxSignalName(allSignals, "") + 1);
if (!startWithUppercase.empty())
{
startWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(startWithUppercase[0])));
}
mapKeywords["start_with_uppercase"] = Align(startWithUppercase, GetMaxSignalName(allSignals, signalTitle) + 1);
mapKeywords["can_signal_name"] = Align(AddQuotationMarks(func.canSignalName), GetMaxCANSignalName(allSignals, canSignalTitle) + 1);
mapKeywords["value_ctype"] = Align(GetCTypeFromIDLType(func.idlType), GetMaxCTypeFromIDLType(allSignals, cTypeTitle));
if (signal.signalDirection == sdv::core::ESignalDirection::sigdir_rx)
mapKeywords["signal_dir"] = "RX ";
else
mapKeywords["signal_dir"] = "TX ";
mapKeywords["vss"] = Align(signal.vssDefinition, GetMaxVSSDefinition(allSignals, ""));
return ReplaceKeywords(R"code( static std::string ds%start_with_uppercase%= %can_signal_name%; ///< %value_ctype% %signal_dir% %vss%
)code", mapKeywords);
}
std::string CVSSCodingCommon::Code_CMakeProject(const std::string& targetLibName, const std::string& targetComponentName) const
{
CKeywordMap mapKeywords;
mapKeywords["target_lib_name"] = targetLibName;
mapKeywords["component_file_name"] = targetComponentName;
return ReplaceKeywords(R"code(# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
# Define project
project(%target_lib_name% VERSION 1.0 LANGUAGES CXX)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Library symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set target name.
set(TARGET_NAME %target_lib_name%)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
# Set platform specific compile flags
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/W4 /WX /wd4996 /wd4100 /permissive- /Zc:rvalueCast)
else()
add_compile_options(-Werror -Wall -Wextra -Wshadow -Wpedantic -Wunreachable-code -fno-common)
endif()
# Add the dynamic library
add_library(${TARGET_NAME} SHARED
%component_file_name%.h
%component_file_name%.cpp)
# Set extension to .sdv
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".sdv")
# TODO: set target name.
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)
)code", mapKeywords);
}

View File

@@ -0,0 +1,106 @@
#ifndef VSS_CODING_H
#define VSS_CODING_H
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <interfaces/dispatch.h>
#include "codegen_base.h"
#include "vss_helper.h"
/**
* @brief VSS code generator coding class.
* Creates the code out of templates
*/
class CVSSCodingCommon : public CCodeGeneratorBase, CVSSHelper
{
public:
/**
* @brief Constructor
* @param[in] rsPrefix used by cmake library and signal definition in signal_identifier.h file
*/
CVSSCodingCommon(const std::string& rsPrefix) : m_ssPrefix(rsPrefix) {}
/**
* @brief fill the KeyWordMap with all required strings
* @param[in] signal signal definition structure to fill the KeyWordMap
* @param[in] mapKeywords KeyWordMap to be filled
* @param[in] rsVersion optional information will be placed in the header of the files
*/
void GetCommonKeyWordMap(const SSignalVDDefinition& signal, CKeywordMap& mapKeywords, const std::string& rsVersion) const;
/**
* @brief fill the KeyWordMap with all required strings
* @param[in] signal signal definition structure to fill the KeyWordMap
* @param[in] mapKeywords KeyWordMap to be filled
* @param[in] rsVersion optional information will be placed in the header of the files
*/
void GetCommonKeyWordMap(const SSignalBSDefinition& signal, CKeywordMap& mapKeywords, const std::string& rsVersion) const;
/**
* @brief create content of the signal_identifier.h file
* @param[in] allSignals container of all signal definitions
* @param[in] ssFileName file name of the signal_identifier.h file
* @param[in] ssVersion optional information will be placed in the header of the files
* @return content of the signal_identifier.h file
*/
std::string Code_SignalIdentifier(const std::vector <SSignalVDDefinition>& allSignals, const std::string& ssFileName,
const std::string& ssVersion) const;
/**
* @brief get the version line which will be added in the header of the files
* @param[in] ssVersion optional information will be placed in the header of the files
* @return line for the header of the files to know the file is auto generated
*/
std::string Code_VSSFileVersion(const std::string& ssVersion) const;
/**
* @brief generates the unique define to avoid duplicate loading of a header file
* @param[in] ssFileName file name which will be included in the unique define
* @return unique define string
*/
std::string Code_SafeGuard(const std::string& ssFileName) const;
/**
* @brief generates the cmakelist.txt file
* @param[in] targetLibName project cmake name
* @param[in] targetComponentName is the name of the header and cpp file
* @return content of the CMakeList.txt file
*/
std::string Code_CMakeProject(const std::string& targetLibName, const std::string& targetComponentName) const;
protected:
/**
* @brief create a signal line for the signal_identifier file
* @param[in] allSignals container of all signals for aligning of the string
* @param[in] signal single signal the function belongs to
* @param[in] func the function which should be returned in a line
* @param[in] signalTitle signal title string in file signal_identifier.h
* @param[in] canSignalTitle can signal title string in file signal_identifier.h
* @param[in] cTypeTitle c-type title string in file signal_identifier.h
* @return content of a single function for the signal_identifier file
*/
std::string Code_SignalIdentifierList(const std::vector <SSignalVDDefinition>& allSignals, const SSignalVDDefinition& signal,
const SFunctionVDDefinition& func, const std::string& signalTitle, const std::string& canSignalTitle, const std::string& cTypeTitle) const;
/**
* @brief create a list of all signals for the signal_identifier file
* @param[in] allSignals container of all signals
* @param[in] signalTitle signal title string in file signal_identifier.h
* @param[in] canSignalTitle can signal title string in file signal_identifier.h
* @param[in] cTypeTitle c-type title string in file signal_identifier.h
* @return content of list of all signals for the signal_identifier file
*/
std::string Code_AllSignalsIdentifierList(const std::vector <SSignalVDDefinition>& allSignals,
const std::string& signalTitle, const std::string& canSignalTitle, const std::string& cTypeTitle) const;
std::string m_ssPrefix; ///< prefix, used by cmake library and signal definition in signal_identifier.h file.
};
#endif // !defined VSS_CODING_H

View File

@@ -0,0 +1,535 @@
#include "vss_helper.h"
std::string CVSSHelper::MapDeclType2CType(const sdv::vss::EDeclType eDeclType) const
{
switch (eDeclType)
{
case sdv::vss::EDeclType::decltype_short: return "int16_t";
case sdv::vss::EDeclType::decltype_long: return "int32_t";
case sdv::vss::EDeclType::decltype_long_long: return "int64_t";
case sdv::vss::EDeclType::decltype_unsigned_short: return "uint16_t";
case sdv::vss::EDeclType::decltype_unsigned_long: return "uint32_t";
case sdv::vss::EDeclType::decltype_unsigned_long_long: return "uint64_t";
case sdv::vss::EDeclType::decltype_float: return "float";
case sdv::vss::EDeclType::decltype_double: return "double";
case sdv::vss::EDeclType::decltype_long_double: return "long double";
case sdv::vss::EDeclType::decltype_fixed: return "uint32_t"; // TODO: Not implemented!
case sdv::vss::EDeclType::decltype_char: return "char";
case sdv::vss::EDeclType::decltype_char16: return "char16_t";
case sdv::vss::EDeclType::decltype_char32: return "char32_t";
case sdv::vss::EDeclType::decltype_wchar: return "wchar_t";
case sdv::vss::EDeclType::decltype_boolean: return "bool";
case sdv::vss::EDeclType::decltype_native: return "size_t";
case sdv::vss::EDeclType::decltype_octet: return "uint8_t";
case sdv::vss::EDeclType::decltype_string: return "sdv::string";
case sdv::vss::EDeclType::decltype_u8string: return "sdv::u8string";
case sdv::vss::EDeclType::decltype_u16string: return "sdv::u16string";
case sdv::vss::EDeclType::decltype_u32string: return "sdv::u32string";
case sdv::vss::EDeclType::decltype_wstring: return "sdv::wstring";
case sdv::vss::EDeclType::decltype_enum: return "enum class";
case sdv::vss::EDeclType::decltype_struct: return "struct";
case sdv::vss::EDeclType::decltype_union: return "union";
case sdv::vss::EDeclType::decltype_module: return "namespace";
case sdv::vss::EDeclType::decltype_interface: return "interface";
case sdv::vss::EDeclType::decltype_exception: return "struct";
case sdv::vss::EDeclType::decltype_attribute: return "";
case sdv::vss::EDeclType::decltype_operation: return "";
case sdv::vss::EDeclType::decltype_parameter: return "";
case sdv::vss::EDeclType::decltype_enum_entry: return "";
case sdv::vss::EDeclType::decltype_case_entry: return "";
case sdv::vss::EDeclType::decltype_typedef: return "typedef";
case sdv::vss::EDeclType::decltype_sequence: return "sdv::sequence";
case sdv::vss::EDeclType::decltype_pointer: return "sdv::pointer";
case sdv::vss::EDeclType::decltype_map: return "uint32_t"; // TODO: Not implemented!
case sdv::vss::EDeclType::decltype_bitset: return "uint32_t"; // TODO: Not implemented!
case sdv::vss::EDeclType::decltype_bitfield: return "uint32_t"; // TODO: Not implemented!
case sdv::vss::EDeclType::decltype_bitmask: return "uint32_t"; // TODO: Not implemented!
case sdv::vss::EDeclType::decltype_any: return "sdv::any_t";
case sdv::vss::EDeclType::decltype_interface_id: return "sdv::interface_id";
case sdv::vss::EDeclType::decltype_interface_type: return "sdv::interface_t";
case sdv::vss::EDeclType::decltype_exception_id: return "sdv::exception_id";
case sdv::vss::EDeclType::decltype_void: return "void";
case sdv::vss::EDeclType::decltype_unknown:
default:
return "";
}
}
void CVSSHelper::CreateCMakeFile(const std::filesystem::path& filePath, const std::string& cmakeContent) const
{
try
{
// create/write CMakeLists.txt only if content has changed
std::string cmakeExisitingContent = "";
if (std::filesystem::exists(filePath))
{
std::ifstream stream;
stream.open(filePath);
if (stream.is_open())
{
std::stringstream sstream;
sstream << stream.rdbuf();
cmakeExisitingContent = std::move(sstream.str());
}
stream.close();
}
if (cmakeContent.compare(cmakeExisitingContent) != 0)
{
std::ofstream fstreamCMakeFile;
fstreamCMakeFile.open(filePath, std::ios::out | std::ios::trunc);
fstreamCMakeFile << cmakeContent;
fstreamCMakeFile.close();
}
}
catch (const std::filesystem::filesystem_error& e)
{
std::cout << "Filesystem error: " << e.what() << '\n';
}
catch (const std::exception& e)
{
std::cout << "Error: " << e.what() << '\n';
}
}
std::filesystem::path CVSSHelper::MakeLowercaseFilename(std::filesystem::path & fullPath) const
{
std::filesystem::path parentPath = fullPath.parent_path();
std::string filename = fullPath.filename().string();
std::transform(filename.begin(), filename.end(), filename.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
return parentPath / filename;
}
std::string CVSSHelper::Align(const std::string& ssInput, size_t size) const
{
auto alignedString = ssInput;
while (alignedString.size() < size)
{
alignedString.append(" ");
}
return alignedString.c_str();
}
size_t CVSSHelper::GetMaxClassName(const std::vector <SSignalVDDefinition>& signals, const std::string& ssTitle) const
{
size_t max = ssTitle.size();
for (const auto& signal : signals)
{
if (max < signal.className.size())
{
max = signal.className.size();
}
}
return max + 1;
}
size_t CVSSHelper::GetMaxIDLType(const std::vector <SSignalVDDefinition>& signals, const std::string& ssTitle) const
{
size_t max = ssTitle.size();
for (const auto& signal : signals)
{
for (auto func : signal.vecFunctions)
{
if (max < func.idlType.size())
{
max = func.idlType.size();
}
}
}
return max + 1;
}
size_t CVSSHelper::GetMaxCTypeFromIDLType(const std::vector <SSignalVDDefinition>& signals, const std::string& ssTitle) const
{
size_t max = ssTitle.size();
for (const auto& signal : signals)
{
for (auto func : signal.vecFunctions)
{
if (max < GetCTypeFromIDLType(func.idlType).size())
{
max = GetCTypeFromIDLType(func.idlType).size();
}
}
}
return max + 1;
}
size_t CVSSHelper::GetMaxSignalName(const std::vector <SSignalVDDefinition>& signals, const std::string& ssTitle) const
{
size_t max = ssTitle.size();
for (const auto& signal : signals)
{
for (auto func : signal.vecFunctions)
{
if (max < func.signalName.size())
{
max = func.signalName.size();
}
}
}
return max + 1;
}
size_t CVSSHelper::GetMaxCANSignalName(const std::vector <SSignalVDDefinition>& signals, const std::string& ssTitle) const
{
size_t max = ssTitle.size();
for (const auto& signal : signals)
{
for (auto func : signal.vecFunctions)
{
if (max < func.canSignalName.size())
{
max = func.canSignalName.size();
}
}
}
return max + 1;
}
size_t CVSSHelper::GetMaxFunctionName(const std::vector <SSignalVDDefinition>& signals, const std::string& ssTitle) const
{
size_t max = ssTitle.size();
for (const auto& signal : signals)
{
for (auto func : signal.vecFunctions)
{
if (max < func.functionName.size())
{
max = func.functionName.size();
}
}
}
return max + 1;
}
size_t CVSSHelper::GetMaxVSSDefinition(const std::vector <SSignalVDDefinition>& signals, const std::string& ssTitle) const
{
size_t max = ssTitle.size();
for (const auto& signal : signals)
{
if (max < signal.vssDefinition.size())
{
max = signal.vssDefinition.size();
}
}
return max + 1;
}
std::string CVSSHelper::GenerateDefaultIfEmpty(const std::string& ssInput, std::string ssDefaultString, const uint32_t& index) const
{
if (ssInput.size() > 0)
{
return ssInput;
}
if (index != 0)
{
ssDefaultString.append("_");
ssDefaultString.append(std::to_string(index));
}
return ssDefaultString;
}
std::string CVSSHelper::Trim(const std::string& ssInput) const
{
size_t first = ssInput.find_first_not_of(' ');
if (first == std::string::npos)
{
return ""; // No content
}
size_t last = ssInput.find_last_not_of(' ');
return ssInput.substr(first, (last - first + 1));
}
bool CVSSHelper::MustNotContainSpaces(const std::string& ssInput) const
{
if (ssInput.find(' ') != std::string::npos)
{
return false;
}
return true;
}
bool CVSSHelper::IsNumber(const std::string& ssInput) const
{
if (!ssInput.empty())
{
auto character = ssInput[0];
return std::isdigit(character);
}
return false;
}
std::string CVSSHelper::ValidateVSSFormatNumbers(const std::string& ssInput) const
{
std::stringstream ss(ssInput);
std::string part;
std::vector<std::string> parts;
while (std::getline(ss, part, '.'))
{
if (IsNumber(part))
{
parts.push_back("_" + part);
}
else {
parts.push_back(part);
}
}
if (!ssInput.empty() && ssInput.back() == '.')
{
parts.push_back("");
}
std::ostringstream result;
for (size_t i = 0; i < parts.size(); ++i)
{
if (i > 0)
{
result << ".";
}
result << parts[i];
}
return result.str();
}
bool CVSSHelper::MustContainDotOrIsEmpty(const std::string& ssInput, bool mustBeEmpty) const
{
if ((ssInput.size() == 0) && (mustBeEmpty)) // empty is not allowed
{
return false;
}
if (ssInput.size() == 0) // empty is allowed
{
return false;
}
if (ssInput.find('.') != std::string::npos)
{
return true;
}
return false;
}
std::string CVSSHelper::AddQuotationMarks(const std::string& value) const
{
std::string returnString = "\"";
returnString.append(value);
returnString.append("\"");
return returnString;
}
std::string CVSSHelper::ReplaceCharacters(const std::string& ssInput, const std::string& from, const std::string& to) const
{
std::string str = ssInput;
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // Move past the replacement
}
return str;
}
std::string CVSSHelper::ToUpper(const std::string& ssInput) const
{
std::stringstream sstreamToUpper;
for (char c : ssInput)
{
sstreamToUpper << static_cast<char>(std::toupper(c));
}
return sstreamToUpper.str();
}
std::string CVSSHelper::ShortenVSSString(const std::string& ssInput) const
{
size_t start_pos = ssInput.size();
start_pos = ssInput.rfind(".", start_pos);
if (start_pos != std::string::npos)
{
return ssInput.substr(0, start_pos);
}
return ssInput;
}
std::string CVSSHelper::CastValueType(const std::string& ssSignalType) const
{
std::vector<std::string> stringTypes = { "sdv::string", "sdv::u8string", "sdv::u16string", "sdv::u32string", "sdv::wstring" };
if (std::find(stringTypes.begin(), stringTypes.end(), ssSignalType) != stringTypes.end())
{
std::string type = "const " + ssSignalType + "&";
return type;
}
return ssSignalType;
}
std::string CVSSHelper::GetCTypeFromIDLType(const std::string& ssIDLType) const
{
for (const auto& type : m_vecDeclTypes)
{
if (ssIDLType == type.first)
{
auto s = type.second;
return MapDeclType2CType(s);
}
}
return "";
}
bool CVSSHelper::ValidateIDLTypes(const std::vector<std::string>& vecTypes, const bool silent) const
{
for (const auto& type : vecTypes)
{
if (GetCTypeFromIDLType(type).empty())
{
if (!silent)
{
std::cout << "ERROR! Invalid IDL type: '" << type << "'" << std::endl;
}
return false;
}
}
return true;
}
void CVSSHelper::ValidateVDCodeStyle(const SSignalVDDefinition& signal, const bool verbose) const
{
if (verbose)
{
if (!std::isupper(static_cast<unsigned char>(signal.className[0])))
{
std::cout << "Class name should start with upper case: '" << signal.className << "'" <<std::endl;
}
}
}
void CVSSHelper::ValidateBSCodeStyle(const SSignalBSDefinition& signal, const bool verbose) const
{
if (verbose)
{
if (!std::isupper(static_cast<unsigned char>(signal.className[0])))
{
std::cout << "Class name should start with upper case: '" << signal.className << "'" << std::endl;
}
}
}
void CVSSHelper::ValidateVDCodeStyle(const SFunctionVDDefinition& function, const bool verbose) const
{
if (verbose)
{
if (std::isupper(static_cast<unsigned char>(function.signalName[0])))
{
std::cout << "Signal name should start with lower case: '" << function.signalName << "'" << std::endl;
}
if (!std::isupper(static_cast<unsigned char>(function.functionName[0])))
{
std::cout << "Function name should start with upper case: '" << function.functionName << "'" << std::endl;
}
}
}
void CVSSHelper::ValidateBSCodeStyle(const SFunctionBSDefinition& function, const bool verbose) const
{
if (verbose)
{
if (std::isupper(static_cast<unsigned char>(function.signalName[0])))
{
std::cout << "Signal name should start with lower case: '" << function.signalName << "'" << std::endl;
}
if (!std::isupper(static_cast<unsigned char>(function.functionName[0])))
{
std::cout << "Function name should start with upper case: '" << function.functionName << "'" << std::endl;
}
}
}
bool CVSSHelper::CreateFolder(const std::filesystem::path& rootPath, const std::string& subfolder) const
{
auto path = rootPath;
if (!subfolder.empty())
{
path = rootPath / subfolder;
}
try
{
for (size_t nCnt = 0; nCnt < 5; nCnt++)
{
if (!std::filesystem::exists(path))
{
std::filesystem::create_directories(path);
}
else
break;
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
}
catch (const std::filesystem::filesystem_error& e)
{
std::cout << "catch (const std::filesystem::filesystem_error& e)" << std::endl;
std::cout << "Error removing directory: " << e.what() << '\n';
}
return std::filesystem::exists(path);
}
void CVSSHelper::DeleteHeaderFile(const std::filesystem::path& path, const std::string& fileNameNoExtension) const
{
auto headerFile = fileNameNoExtension;
headerFile.append(".h");
auto file = path / headerFile;
try
{
if (!std::filesystem::is_directory(file))
{
std::filesystem::remove(file);
}
}
catch (const std::filesystem::filesystem_error& e)
{
std::cout << "catch (const std::filesystem::filesystem_error& e)" << std::endl;
std::cout << "Error removing directory: " << e.what() << '\n';
}
}
bool CVSSHelper::VehicleDeviceVSSDefinitionExists(bool bSilent, const std::vector <SSignalVDDefinition>& vdSignals,
const std::vector <SSignalBSDefinition>& bsSignals)
{
if (bsSignals.size())
{
std::unordered_set<std::string> vssVDDefinitions;
for (const auto& vssDefinition : vdSignals)
{
vssVDDefinitions.insert(vssDefinition.vssDefinition);
}
for (const auto& vssDefinition : bsSignals)
{
if (vssVDDefinitions.find(vssDefinition.vssVDDefinition) == vssVDDefinitions.end())
{
if (!bSilent)
{
std::cout << vssDefinition.vssVDDefinition << " cannot be found, requested by " << vssDefinition.vssDefinition << std::endl;
}
return false;
}
}
}
return true;
}

View File

@@ -0,0 +1,487 @@
#ifndef VSS_HELPER_H
#define VSS_HELPER_H
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <string>
#include <sstream>
#include <fstream>
#include <thread>
#include <chrono>
//#include <algorithm>
#include <interfaces/dispatch.h>
namespace sdv
{
/**
* @brief vss namespace
*/
namespace vss
{
/**
* @brief The entity declaration type.
*/
enum class EDeclType : uint32_t
{
/// Unknown type
decltype_unknown,
/// Integer type (int16_t)
decltype_short,
/// Integer type (int32_t)
decltype_long,
/// Integer type (int64_t)
decltype_long_long,
/// Octet type (uint8_t)
decltype_octet,
/// Integer type (uint16_t)
decltype_unsigned_short,
/// Integer type (uint32)
decltype_unsigned_long,
/// Integer type (uint64_t)
decltype_unsigned_long_long,
/// Floating point type
decltype_float,
/// Floating point type
decltype_double,
/// Floating point type
decltype_long_double,
/// Fixed point templated type
decltype_fixed,
/// Character type (int8_t)
decltype_char,
/// UTF-16 character
decltype_char16,
/// UTF-32 character
decltype_char32,
/// Character type
decltype_wchar,
/// Boolean type
decltype_boolean,
/// Native type
decltype_native,
/// ASCII templated string type
decltype_string,
/// UTF-8 templated string type
decltype_u8string,
/// UTF-16 templated string type
decltype_u16string,
/// UTF-32 templated string type
decltype_u32string,
/// Wide templated string type
decltype_wstring,
/// Enum type
decltype_enum,
/// Struct type
decltype_struct,
/// Union type
decltype_union,
/// Module type
decltype_module,
/// Interface type (not used in declarations)
decltype_interface,
/// Interface type (not used in declarations)
decltype_exception,
/// Attribute type (not used in declarations)
decltype_attribute,
/// Operation type (not used in declarations)
decltype_operation,
/// Parameter type (only for operations)
decltype_parameter,
/// Enum entry type (only for enums)
decltype_enum_entry,
/// Case entry type (only for unions)
decltype_case_entry,
/// Typedef type
decltype_typedef,
/// Void type (only for operations)
decltype_void,
/// Meta data type
decltype_meta,
/// Pointer templated data type
decltype_pointer,
/// Sequence templated data type
decltype_sequence,
/// Map templated data type
decltype_map,
/// Bitset data type
decltype_bitset,
/// Bitfield templated data type
decltype_bitfield,
/// Bitmask data type
decltype_bitmask,
/// Any composite data type
decltype_any,
/// Interface ID data type
decltype_interface_id,
/// Interface data type
decltype_interface_type,
/// Exception ID data type
decltype_exception_id,
};
}
}
/**
* @brief VSS code generator helper class.
*/
class CVSSHelper
{
public:
/**
* @brief Signal definition structure (vehicle device) with a single function/value combination
*/
struct SFunctionVDDefinition
{
std::string idlType; ///< signal value type (IDL: boolean, float, uint8, ...)
std::string functionName; ///< signal value set function name
std::string signalName; ///< signal name
std::string canSignalName; ///< can signal name (combination of signak messages and signal name)
};
/**
* @brief Signal definition structure (basic service) with a single function/value combination
*/
struct SFunctionBSDefinition
{
std::string idlType; ///< signal value type (IDL: boolean, float, uint8, ...)
std::string functionName; ///< signal value set function name
std::string signalName; ///< signal name
};
/**
* @brief Signal definition structure (vehicle device) with a single function/value combination
*/
struct SSignalVDDefinition
{
std::string vssDefinition; ///< vss interface string
std::string className; ///< class name
sdv::core::ESignalDirection signalDirection = sdv::core::ESignalDirection::sigdir_rx; ///< signal direction, either rx or tx
std::vector<SFunctionVDDefinition> vecFunctions; ///< list of functions of the vss interface
};
/**
* @brief Signal definition structure (basic service) with a single function/value combination
*/
struct SSignalBSDefinition
{
std::string vssDefinition; ///< vss interface string
std::string vssVDDefinition; ///< vss interface string
std::string className; ///< class name
sdv::core::ESignalDirection signalDirection = sdv::core::ESignalDirection::sigdir_rx; ///< signal direction, either rx or tx
std::vector<SFunctionBSDefinition> vecFunctions; ///< list of functions of the vss interface
};
/**
* @brief Check if all required VD definitions are found required by the BS signals
* @param[in] bSilent if true do not print error to console.
* @param[in] vdSignals containing all signals definitions of the vehicle devices.
* @param[in] bsSignals containing all signals definitions of the basic services.
* @return Returns true on success when all definitions are found, otherwise false.
*/
static bool VehicleDeviceVSSDefinitionExists(bool bSilent, const std::vector<SSignalVDDefinition>& vdSignals,
const std::vector<SSignalBSDefinition>& bsSignals);
protected:
/**
* @brief Create the cmake if not exists and if content has changed
* @param[in] filePath full path to the file
* @param[in] cmakeContent content of the cmake file
*/
void CreateCMakeFile(const std::filesystem::path& filePath, const std::string& cmakeContent) const;
/**
* @brief Converts the filename of a full path to lowercase
* @param[in] fullPath full path
* @return Returns full path but the filename is lowercase
*/
std::filesystem::path MakeLowercaseFilename(std::filesystem::path& fullPath) const;
/**
* @brief Add multiple space characters to increase the input string to a certain size.
* @param[in] ssInput Reference to the input string.
* @param[in] size of the final string.
* @return Returns the string increased by space characters.
*/
std::string Align(const std::string& ssInput, size_t size) const;
/**
* @brief trim spaces from begin of the string and end of the string
* @param[in] ssInput Reference to the input string to be checked.
* @return Returns string without the spaces at front and at the end
*/
std::string Trim(const std::string& ssInput) const;
/**
* @brief check for space characters in the string.
* @param[in] ssInput Reference to the input string to be checked.
* @return Returns true if string contains no space character, otherwise false.
*/
bool MustNotContainSpaces(const std::string& ssInput) const;
/**
* @brief Get the maximal string size of all class names in the vector container.
* @param[in] signals containing all signals definitions which have to be checked.
* @param[in] ssTitle Reference to the title string. Is minimum of the return value.
* @return Returns the string size of the largest class name string.
*/
size_t GetMaxClassName(const std::vector<SSignalVDDefinition>& signals, const std::string& ssTitle) const;
/**
* @brief Get the maximal string size of all IDL type strings in the vector container.
* @param[in] signals containing all signals definitions which have to be checked.
* @param[in] ssTitle Reference to the title string. Is minimum of the return value.
* @return Returns the string size of the largest IDL type string.
*/
size_t GetMaxIDLType(const std::vector<SSignalVDDefinition>& signals, const std::string& ssTitle) const;
/**
* @brief Get the maximal string size of all ctype strings in the vector container.
* @param[in] signals containing all signals definitions which have to be checked.
* @param[in] ssTitle Reference to the title string. Is minimum of the return value.
* @return Returns the string size of the largest ctype string.
*/
size_t GetMaxCTypeFromIDLType(const std::vector<SSignalVDDefinition>& signals, const std::string& ssTitle) const;
/**
* @brief Get the maximal string size of all signal name strings in the vector container.
* @param[in] signals containing all signals definitions which have to be checked.
* @param[in] ssTitle Reference to the title string. Is minimum of the return value.
* @return Returns the string size of the largest signal names string.
*/
size_t GetMaxSignalName(const std::vector<SSignalVDDefinition>& signals, const std::string& ssTitle) const;
/**
* @brief Get the maximal string size of all CAN signal name strings in the vector container.
* @param[in] signals containing all signals definitions which have to be checked.
* @param[in] ssTitle Reference to the title string. Is minimum of the return value.
* @return Returns the string size of the largest signal names string.
*/
size_t GetMaxCANSignalName(const std::vector<SSignalVDDefinition>& signals, const std::string& ssTitle) const;
/**
* @brief Get the maximal string size of all function name strings in the vector container.
* @param[in] signals containing all signals definitions which have to be checked.
* @param[in] ssTitle Reference to the title string. Is minimum of the return value.
* @return Returns the string size of the largest function names string.
*/
size_t GetMaxFunctionName(const std::vector<SSignalVDDefinition>& signals, const std::string& ssTitle) const;
/**
* @brief Get the maximal string size of all vss strings in the vector container.
* @param[in] signals containing all signals definitions which have to be checked.
* @param[in] ssTitle Reference to the title string. Is minimum of the return value.
* @return Returns the string size of the largest vss string.
*/
size_t GetMaxVSSDefinition(const std::vector<SSignalVDDefinition>& signals, const std::string& ssTitle) const;
/**
* @brief check for '.' characters in the string.
* @param[in] ssInput Reference to the input string to be checked.
* @param[in] mustBeEmpty If true input string must not be empty
* @return Returns true if string contains '.' or is empty depending on mustBeEmpty, otherwise false.
*/
bool MustContainDotOrIsEmpty(const std::string& ssInput, bool mustBeEmpty) const;
/**
* @brief check if vss parts are string and no number. If number add '_'
* for vehicle.chassis.axel.01.left return vehicle.chassis.axel._01.left
* @param[in] ssInput Reference to the input string to be checked.
* @return Returns valid vss string.
*/
std::string ValidateVSSFormatNumbers(const std::string& ssInput) const;
/**
* @brief check if string is a number
* @param[in] ssInput Reference to the input string to be checked.
* @return Returns false if it is a number, otherwise true.
*/
bool IsNumber(const std::string& ssInput) const;
/**
* @brief Returns input string or if empty, returns default string.
* @param[in] ssInput string
* @param[in] ssDefaultString string used as default if input string is empty
* @param[in] index number will be added to the default string.
* @return Returns input string or if empty returns default string added by the number.
*/
std::string GenerateDefaultIfEmpty(const std::string& ssInput, std::string ssDefaultString, const uint32_t& index) const;
/**
* @brief Returns input string but starts and ends with "'".
* @param[in] ssInput string
* @return Returns the input string with "'" added at the frond and the end.
*/
std::string AddQuotationMarks(const std::string& ssInput) const;
/**
* @brief Replaces some characters of the input string.
* @param[in] ssInput string.
* @param[in] from character to be replaced
* @param[in] to replacement character.
* @return Returns the string with replacements.
*/
std::string ReplaceCharacters(const std::string& ssInput, const std::string& from, const std::string& to) const;
/**
* @brief turn the input string to upper case
* @param[in] ssInput string.
* @return Returns the input string but all characters are upper case
*/
std::string ToUpper(const std::string& ssInput) const;
/**
* @brief remove the last part of the vss string
* @param[in] ssInput vss string
* @return Returns the string but removed the last part after charatcer '.'.
*/
std::string ShortenVSSString(const std::string& ssInput) const;
/**
* @brief add to the type a cast, for example for 'std::string' it adds "const std::string&'
* @param[in]ssSignalType the string representing the type
* @return Returns either original string or 'const' and '&' added.
*/
std::string CastValueType(const std::string& ssSignalType) const;
/**
* @brief find IDL type and return CType
* @param[in] ssIDLType string representing IDL type
* @return CType string if IDL type found, otherwise empty string
*/
std::string GetCTypeFromIDLType(const std::string& ssIDLType) const;
/**
* @brief validate if all IDL type are valid
* @param[in] vecTypes container of the IDL types
* @param[in] silent information to console if not silent
* @return True if IDL types are valid, otherwise false
*/
bool ValidateIDLTypes(const std::vector<std::string>& vecTypes, const bool silent) const;
/**
* @brief Create folder or sub folder
* @param[in] rootPath complete root path
* @param[in] subfolder in case this parameter is empty only root path is created otherwise rootPath + subfolder
* @return true if directory exists or is created successfully, otherwise false
*/
bool CreateFolder(const std::filesystem::path& rootPath, const std::string& subfolder) const;
/**
* @brief deletes a header file
* @param[in] path full path to a folder
* @param[in] fileNameNoExtension a file name without the extension
*/
void DeleteHeaderFile(const std::filesystem::path& path, const std::string& fileNameNoExtension) const;
/**
* @brief Validates the code style (signal name starts with lower case, function name upper case ...
* @param[in] function function definition structure
* @param[in] verbose print information to console only if true
*/
void ValidateVDCodeStyle(const SFunctionVDDefinition& function, const bool verbose) const;
/**
* @brief Validates the code style (signal name starts with lower case, function name upper case ...
* @param[in] function function definition structure
* @param[in] verbose print information to console only if true
*/
void ValidateBSCodeStyle(const SFunctionBSDefinition& function, const bool verbose) const;
/**
* @brief Validates the code style (signal name starts with lower case, function name upper case ...
* @param[in] signal signal definition structure
* @param[in] verbose print information to console only if true
*/
void ValidateVDCodeStyle(const SSignalVDDefinition& signal, const bool verbose) const;
/**
* @brief Validates the code style (signal name starts with lower case, function name upper case ...
* @param[in] signal signal definition structure
* @param[in] verbose print information to console only if true
*/
void ValidateBSCodeStyle(const SSignalBSDefinition& signal, const bool verbose) const;
private:
/**
* @brief Declaration type name association.
*/
using TDeclTypeAssoc = std::pair<std::string, sdv::vss::EDeclType>;
/**
* @brief change EDeclType to cType string
* @param[in] eDeclType EDeclTyp type
* @return Returns cType stringif available, otherwise empty string
*/
std::string MapDeclType2CType(const sdv::vss::EDeclType eDeclType) const;
/**
* @brief Mapping between declaration type and string name.
* @attention Some types have multiple string representatives (e.g. sdv::vss::EDeclType::decltype_short vs. 'short' and
* 'int16').
* @attention Based on the provided extensions on the command line, the types might be extended by: char16, char32, u8string,
* u16string, u32string, pointer, interface_id, interface_t and exception_id
*/
const std::vector<TDeclTypeAssoc> m_vecDeclTypes = {
{"short", sdv::vss::EDeclType::decltype_short},
{"unsigned short", sdv::vss::EDeclType::decltype_unsigned_short},
{"long", sdv::vss::EDeclType::decltype_long},
{"unsigned long", sdv::vss::EDeclType::decltype_unsigned_long},
{"long long", sdv::vss::EDeclType::decltype_long_long},
{"unsigned long long", sdv::vss::EDeclType::decltype_unsigned_long_long},
{"fixed", sdv::vss::EDeclType::decltype_fixed},
{"float", sdv::vss::EDeclType::decltype_float},
{"double", sdv::vss::EDeclType::decltype_double},
{"long double", sdv::vss::EDeclType::decltype_long_double},
{"char", sdv::vss::EDeclType::decltype_char},
{"wchar", sdv::vss::EDeclType::decltype_wchar},
{"int8", sdv::vss::EDeclType::decltype_char},
{"int16", sdv::vss::EDeclType::decltype_short},
{"int32", sdv::vss::EDeclType::decltype_long},
{"int64", sdv::vss::EDeclType::decltype_long_long},
{"int", sdv::vss::EDeclType::decltype_long},
{"uint8", sdv::vss::EDeclType::decltype_octet},
{"uint16", sdv::vss::EDeclType::decltype_unsigned_short},
{"uint32", sdv::vss::EDeclType::decltype_unsigned_long},
{"uint64", sdv::vss::EDeclType::decltype_unsigned_long_long},
{"uint", sdv::vss::EDeclType::decltype_unsigned_long},
{"boolean", sdv::vss::EDeclType::decltype_boolean},
{"native", sdv::vss::EDeclType::decltype_native},
{"octet", sdv::vss::EDeclType::decltype_octet},
{"byte", sdv::vss::EDeclType::decltype_octet},
{"string", sdv::vss::EDeclType::decltype_string},
{"wstring", sdv::vss::EDeclType::decltype_wstring},
{"enum", sdv::vss::EDeclType::decltype_enum},
{"struct", sdv::vss::EDeclType::decltype_struct},
{"union", sdv::vss::EDeclType::decltype_union},
{"operation", sdv::vss::EDeclType::decltype_operation},
{"attribute", sdv::vss::EDeclType::decltype_parameter},
{"enum_entry", sdv::vss::EDeclType::decltype_enum_entry},
{"case_entry", sdv::vss::EDeclType::decltype_case_entry},
{"typedef", sdv::vss::EDeclType::decltype_typedef},
{"sequence", sdv::vss::EDeclType::decltype_sequence},
{"map", sdv::vss::EDeclType::decltype_map},
{"bitset", sdv::vss::EDeclType::decltype_bitset},
{"bitfield", sdv::vss::EDeclType::decltype_bitfield},
{"bitmask", sdv::vss::EDeclType::decltype_bitmask},
{"any", sdv::vss::EDeclType::decltype_any},
{"void", sdv::vss::EDeclType::decltype_void},
// Add additional types based on enabled extensions
{"interface_id", sdv::vss::EDeclType::decltype_interface_id},
{"interface_t", sdv::vss::EDeclType::decltype_interface_type},
{"exception_id", sdv::vss::EDeclType::decltype_exception_id},
{"pointer", sdv::vss::EDeclType::decltype_pointer},
{"char16", sdv::vss::EDeclType::decltype_char16},
{"char32", sdv::vss::EDeclType::decltype_char32},
{"u8string", sdv::vss::EDeclType::decltype_u8string},
{"u16string", sdv::vss::EDeclType::decltype_u16string},
{"u32string", sdv::vss::EDeclType::decltype_u32string}
};
};
#endif // !defined VSS_HELPER_H

View File

@@ -0,0 +1,248 @@
/**
* @brief file template for the RX signals (device header)
*/
const char szRXVehicleDeviceHeaderTemplate[] = R"code(/**
* @file %abstract_device_h%
* @date %creation_date%
* %version%
*/
#ifndef %vd_safeguard%
#define %vd_safeguard%
#include <iostream>
#include <set>
#include <support/component_impl.h>
#include <support/signal_support.h>
%rx_vd_includes_list%
#include "../signal_identifier.h"
/**
* @brief Vehicle device %vss_original%
*/
class CVehicleDevice%class_name%
: public sdv::CSdvObject
, public sdv::IObjectControl
%rx_vd_interface_list%{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
%rx_vd_interface_entry_list% END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("%vss_original%_Device")
/**
* @brief Constructor
*/
CVehicleDevice%class_name%();
/**
* @brief initialize device to get the object name or use the default.
* @param[in] objectConfig Configuration containing the object name
*/
void Initialize(const sdv::u8string& objectConfig) override;
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
sdv::EObjectStatus GetStatus() const override;
/**
* @brief Set the component operation mode. Overlovd of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(/*in*/ sdv::EOperationMode eMode) override;
/**
* @brief Shutdown function is to shutdown the execution of request thread
*/
void Shutdown() override;
%rx_vd_register_events_list%
private:
%rx_vd_private_vd_header_part%
std::atomic<sdv::EObjectStatus> m_status = { sdv::EObjectStatus::initialization_pending }; ///< To update the object status when it changes.
};
DEFINE_SDV_OBJECT(CVehicleDevice%class_name%)
#endif // !define %vd_safeguard%
)code";
/**
* @brief file template for the RX signals (device cpp file)
*/
const char szRXVehicleDeviceClassTemplate[] = R"code(/**
* @file %abstract_device_cpp%
* @date %creation_date%
* %version%
*/
#include <iostream>
#include "vd_%class_name_lowercase%.h"
/**
* @brief Constructor
*/
CVehicleDevice%class_name%::CVehicleDevice%class_name%()
{
}
/**
* @brief initialize device to get the object name or use the default.
* @param[in] objectConfig Configuration containing the object name
*/
void CVehicleDevice%class_name%::Initialize(const sdv::u8string&)
{
if (m_status != sdv::EObjectStatus::initialization_pending)
{
return;
}
sdv::core::CDispatchService dispatch;
%rx_vd_subscribe_signals%
%rx_check_subscriptions%
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
sdv::EObjectStatus CVehicleDevice%class_name%::GetStatus() const
{
return m_status;
}
/**
* @brief Set the component operation mode. Overlovd of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void CVehicleDevice%class_name%::SetOperationMode(/*in*/ sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
m_status = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
m_status = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown function is to shutdown the execution of request thread
*/
void CVehicleDevice%class_name%::Shutdown()
{
%rx_reset_signals%
m_status = sdv::EObjectStatus::destruction_pending;
}
%rx_vd_register%
)code";
/**
* @brief file template for the RX signals (service header)
*/
const char szRXBasicServiceHeaderTemplate[] = R"code(/**
* @file %basic_service_h%
* @date %creation_date%
* %version%
*/
#ifndef %bs_safeguard%
#define %bs_safeguard%
#include <iostream>
#include <set>
#include <support/component_impl.h>
#include <support/signal_support.h>
%rx_bs_includes_list%
/**
* @brief Basic Service %vss_original%
*/
class CBasicService%class_name%
: public sdv::CSdvObject
%rx_bs_interface_list%{
public:
BEGIN_SDV_INTERFACE_MAP()
%rx_bs_interface_entry_list% END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("%vss_original%_Service")
/**
* @brief Constructor
*/
CBasicService%class_name%();
/**
* @brief User-Defined Destructor
*/
~CBasicService%class_name%();
%rx_bs_register_events_list%
private:
%rx_bs_private_vd_header_part%
};
DEFINE_SDV_OBJECT(CBasicService%class_name%)
#endif // !define %bs_safeguard%
)code";
/**
* @brief file template for the RX signals (service cpp file)
*/
const char szRXBasicServiceClassTemplate[] = R"code(/**
* @file %basic_service_cpp%
* @date %creation_date%
* %version%
*/
#include <iostream>
#include "bs_%class_name_lowercase%.h"
%vss_from_vd_not_found%
/**
* @brief Constructor
*/
CBasicService%class_name%::CBasicService%class_name%()
{%rx_bs_constructor%}
/**
* @brief User-Defined Destructor
*/
CBasicService%class_name%::~CBasicService%class_name%()
{%rx_bs_deconstructor%}
%rx_bs_getandsetfunctions%%rx_bs_register%
)code";
/**
* @brief file template for the RX signals (Vehicle Device IDL files)
*/
const char szVDRXIDLTemplate[] = R"code(
/**
* @file %_vd_idl_h%
* @date %creation_date%
* %version%
*/
#include "interfaces/core.idl"
%vss_device%
)code";
/**
* @brief file template for the RX signals (Basic Service IDL files)
*/
const char szBSRXIDLTemplate[] = R"code(
/**
* @file %_bs_idl_h%
* @date %creation_date%
* %version%
*/
#include "interfaces/core.idl"
#include "%vd_idl_file%"
%vss_device%
%vss_service%
)code";

View File

@@ -0,0 +1,239 @@
/**
* @brief file template for the TX signals (device header)
*/
const char szTXVehicleDeviceHeaderTemplate[] = R"code(/**
* @file %abstract_device_h%
* @date %creation_date%
* %version%
*/
#ifndef %vd_safeguard%
#define %vd_safeguard%
#include <iostream>
#include <support/component_impl.h>
#include <support/signal_support.h>
%tx_vd_includes_list%
#include "../signal_identifier.h"
/**
* @brief Vehicle device %vss_shorten_no_dot%
*/
class CVehicleDevice%class_name%
: public sdv::CSdvObject
, public sdv::IObjectControl
%tx_vd_interface_list%{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
%tx_vd_interface_entry_list% END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::Device)
DECLARE_OBJECT_CLASS_NAME("%vss_original%_Device")
/**
* @brief Constructor
*/
CVehicleDevice%class_name%();
/**
* @brief initialize device to get the object name or use the default.
* @param[in] objectConfig Configuration containing the object name
*/
void Initialize(const sdv::u8string& objectConfig) override;
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
sdv::EObjectStatus GetStatus() const override;
/**
* @brief Set the component operation mode. Overlovd of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(/*in*/ sdv::EOperationMode eMode) override;
/**
* @brief Shutdown function is to shutdown the execution of request thread
*/
void Shutdown() override;
%tx_vd_function_list%
private:
%tx_variable_list%
std::atomic<sdv::EObjectStatus> m_status = { sdv::EObjectStatus::initialization_pending }; ///< To update the object status when it changes.
};
DEFINE_SDV_OBJECT(CVehicleDevice%class_name%)
#endif // !define %vd_safeguard%
)code";
/**
* @brief file template for the TX signals (device cpp file)
*/
const char szTXVehicleDeviceClassTemplate[] = R"code(/**
* @file %abstract_device_cpp%
* @date %creation_date%
* %version%
*/
#include <iostream>
#include "vd_%class_name_lowercase%.h"
/**
* @brief Constructor
*/
CVehicleDevice%class_name%::CVehicleDevice%class_name%()
{
}
/**
* @brief initialize device to get the object name or use the default.
* @param[in] objectConfig Configuration containing the object name
*/
void CVehicleDevice%class_name%::Initialize(const sdv::u8string&)
{
if (m_status != sdv::EObjectStatus::initialization_pending)
{
return;
}
sdv::core::CDispatchService dispatch;
%tx_variable_init_list%
%tx_variable_check_list%
}
/**
* @brief Gets the current status of the object
* @return EObjectStatus The current status of the object
*/
sdv::EObjectStatus CVehicleDevice%class_name%::GetStatus() const
{
return m_status;
}
/**
* @brief Set the component operation mode. Overlovd of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void CVehicleDevice%class_name%::SetOperationMode(/*in*/ sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_status == sdv::EObjectStatus::running || m_status == sdv::EObjectStatus::initialized)
m_status = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_status == sdv::EObjectStatus::configuring || m_status == sdv::EObjectStatus::initialized)
m_status = sdv::EObjectStatus::running;
break;
default:
break;
}
}
/**
* @brief Shutdown function is to shutdown the execution of request thread
*/
void CVehicleDevice%class_name%::Shutdown()
{
%tx_reset_signals%
m_status = sdv::EObjectStatus::destruction_pending;
}
%tx_function_implementations%
)code";
/**
* @brief file template for the TX signals (service header)
*/
const char szTXBasicServiceHeaderTemplate[] = R"code(/**
* @file %basic_service_h%
* @date %creation_date%
* %version%
*/
#ifndef %bs_safeguard%
#define %bs_safeguard%
#include <iostream>
#include <support/component_impl.h>
%tx_bs_includes_list%
/**
* @brief basic service %class_name%
*/
class CBasicService%class_name%
: public sdv::CSdvObject
%tx_bs_interface_list%{
public:
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::CSdvObject)
%tx_bs_interface_entry_list% END_SDV_INTERFACE_MAP()
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::BasicService)
DECLARE_OBJECT_CLASS_NAME("%vss_original%_Service")
/**
* @brief Constructor
*/
CBasicService%class_name%();
%tx_bs_function_list%
private:
%tx_bs_variable_pointer_list%
};
DEFINE_SDV_OBJECT(CBasicService%class_name%)
#endif // !define %bs_safeguard%
)code";
/**
* @brief file template for the TX signals (service cpp file)
*/
const char szTXBasicServiceClassTemplate[] = R"code(/**
* @file %basic_service_cpp%
* @date %creation_date%
* %version%
*/
#include <iostream>
#include "bs_%class_name_lowercase%.h"
%vss_from_vd_not_found%
/**
* @brief Constructor
*/
CBasicService%class_name%::CBasicService%class_name%()
{%tx_bs_variable_pointer_init_list%
SDV_LOG_TRACE("CBasicService%class_name% created.");
}
%vd_tx_pointer_function_implementations%
)code";
/**
* @brief file template for the TX signals (Vehicle Device IDL files)
*/
const char szVDTXIDLTemplate[] = R"code(/**
* @file %_vd_idl_h%
* @date %creation_date%
* %version%
*/
#include <interfaces/core.idl>
%vss_device%
)code";
/**
* @brief file template for the TX signals (Basic service IDL files)
*/
const char szBSTXIDLTemplate[] = R"code(/**
* @file %_bs_idl_h%
* @date %creation_date%
* %version%
*/
#include <interfaces/core.idl>
%vss_service%
)code";

View File

@@ -0,0 +1,469 @@
#include "vss_vd_codingrx.h"
void CVSSVDCodingRX::GetKeyWordMap(const SSignalVDDefinition& signal, CKeywordMap& mapKeywords) const
{
std::string vssWithColons = ReplaceCharacters(signal.vssDefinition, ".", "::");
//------------------------------------------------------- vehicle device header
std::stringstream sstreamIncludesVD;
std::string vssNoDot = ReplaceCharacters(signal.vssDefinition, ".", "");
std::transform(vssNoDot.begin(), vssNoDot.end(), vssNoDot.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
sstreamIncludesVD << Code_VD_RXIncludes(vssNoDot);
mapKeywords["rx_vd_includes_list"] = std::move(sstreamIncludesVD.str());
std::stringstream sstreamInterfaces;
for (const auto& func : signal.vecFunctions)
{
sstreamInterfaces << Code_VD_RXInterface(func.functionName, vssWithColons);
}
mapKeywords["rx_vd_interface_list"] = std::move(sstreamInterfaces.str());
std::stringstream sstreamVDInterfaceEntries;
for (const auto& func : signal.vecFunctions)
{
sstreamVDInterfaceEntries << Code_VD_RXInterfaceEntry(func.functionName, vssWithColons);
}
mapKeywords["rx_vd_interface_entry_list"] = std::move(sstreamVDInterfaceEntries.str());
std::stringstream sstreamVDRegisterEvents;
for (const auto& func : signal.vecFunctions)
{
sstreamVDRegisterEvents << Code_VD_RXReAndUnregisterEvent(vssWithColons, func);
}
mapKeywords["rx_vd_register_events_list"] = std::move(sstreamVDRegisterEvents.str());
std::stringstream sstreamPrivateVDHeaderPart;
for (const auto& func : signal.vecFunctions)
{
sstreamPrivateVDHeaderPart << Code_VD_RXPrivateHeaderPart(func, vssWithColons, signal.className);
}
mapKeywords["rx_vd_private_vd_header_part"] = std::move(sstreamPrivateVDHeaderPart.str());
//------------------------------------------------------- vehicle device cpp
std::stringstream sstreamVDSubscribe;
for (const auto& func : signal.vecFunctions)
{
sstreamVDSubscribe << Code_VD_RXSubscribeSignal(signal.className, func);
}
mapKeywords["rx_vd_subscribe_signals"] = std::move(sstreamVDSubscribe.str());
if (signal.vecFunctions.size() > 0)
{
mapKeywords["rx_check_subscriptions"] = Code_VD_RXCheckSignalSubscribtions(signal.vecFunctions);
}
std::stringstream sstreamVDResetSignal;
for (const auto& func : signal.vecFunctions)
{
sstreamVDResetSignal << Code_VD_RXResetSignal(func);
}
mapKeywords["rx_reset_signals"] = std::move(sstreamVDResetSignal.str());
std::stringstream sstreamVDRegister;
for (const auto& func : signal.vecFunctions)
{
sstreamVDRegister << Code_VD_RXRegister(signal.className, func, vssWithColons);
}
mapKeywords["rx_vd_register"] = std::move(sstreamVDRegister.str());
}
std::string CVSSVDCodingRX::Code_RXIDLDeviceList(const std::vector<std::string>& vssParts,
const std::vector <SFunctionVDDefinition>& vecFunctions) const
{
std::string prefix = "Device";
int8_t loop = 1;
std::string nameSpace = "module vss\n{\n";
for (auto it = vssParts.begin(); it != vssParts.end(); ++it)
{
nameSpace.append(static_cast <int8_t>(4) * loop, ' ');
nameSpace.append("module ");
nameSpace.append(*it);
if (it == vssParts.end() - 1)
{
nameSpace.append(prefix);
}
nameSpace.append("\n");
nameSpace.append(static_cast <int8_t>(4) * loop++, ' ');
nameSpace.append("{\n");
}
nameSpace.append("%interfaces%");
loop--;
for (size_t i = 0; i < vssParts.size() + 1; i++)
{
nameSpace.append(static_cast <int8_t>(4) * loop--, ' ');
nameSpace.append("};\n");
}
std::string spaces = "";
spaces.append(static_cast <int8_t>(4) * (vssParts.size() + 1), ' ');
std::stringstream sstreamInterfaces;
for (const auto& func : vecFunctions)
{
sstreamInterfaces << Code_RXIDLDeviceInterface(spaces, func);
}
CKeywordMap mapKeywords;
mapKeywords["interfaces"] = std::move(sstreamInterfaces.str());
return ReplaceKeywords(nameSpace, mapKeywords);
}
std::string CVSSVDCodingRX::Code_RXIDLServiceList(const std::vector<std::string>& vssParts,
const std::vector <SFunctionVDDefinition>& vecFunctions) const
{
std::string vssWithColons = "";
int8_t loop = 1;
std::string nameSpace = "module vss\n{\n";
for (auto it = vssParts.begin(); it != vssParts.end(); ++it)
{
nameSpace.append(static_cast <int8_t>(4) * loop, ' ');
nameSpace.append("module ");
nameSpace.append(*it);
if (it == vssParts.end() - 1)
{
nameSpace.append("Service");
}
nameSpace.append("\n");
nameSpace.append(static_cast <int8_t>(4) * loop++, ' ');
nameSpace.append("{\n");
vssWithColons.append("::");
vssWithColons.append(*it);
}
nameSpace.append("%interfaces%");
loop--;
for (size_t i = 0; i < vssParts.size() + 1; i++)
{
nameSpace.append(static_cast <int8_t>(4) * loop--, ' ');
nameSpace.append("};\n");
}
std::string spaces = "";
spaces.append(static_cast <int8_t>(4) * (vssParts.size() + 1), ' ');
std::stringstream sstreamInterfaces;
for (const auto& func : vecFunctions)
{
sstreamInterfaces << Code_RXIDLServiceInterface(spaces, vssWithColons, func);
}
CKeywordMap mapKeywords;
mapKeywords["interfaces"] = std::move(sstreamInterfaces.str());
return ReplaceKeywords(nameSpace, mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXIncludes(const std::string& vssOriginalNoDot) const
{
CKeywordMap mapKeywords;
mapKeywords["vss_original_no_dot"] = vssOriginalNoDot;
return ReplaceKeywords(R"code(#include "../vss_%vss_original_no_dot%_vd_rx.h")code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_RXIDLDeviceInterface(const std::string& spaces, const SFunctionVDDefinition& function) const
{
std::string prefix = "Device";
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_idltype"] = function.idlType;
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
mapKeywords["prefix"] = prefix;
mapKeywords["multiple_spaces"] = spaces;
return ReplaceKeywords(R"code(%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_Write%function_name% event interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_Write%function_name%_Event
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Write %signal_name% signal
%multiple_spaces% * @param[in] value %signal_name%
%multiple_spaces% */
%multiple_spaces% void Write%function_name%(in %value_idltype% value);
%multiple_spaces%};
%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_%function_name% abstract %prefix% interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_%function_name%
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Register Write%function_name% event on signal change
%multiple_spaces% * Register all events and call them on signal change
%multiple_spaces% * @param[in] event function
%multiple_spaces% */
%multiple_spaces% void Register%function_name%Event(in IVSS_Write%function_name%_Event event);
%multiple_spaces% /**
%multiple_spaces% * @brief Unregister %function_name% event
%multiple_spaces% * @param[in] event function
%multiple_spaces% */
%multiple_spaces% void Unregister%function_name%Event(in IVSS_Write%function_name%_Event event);
%multiple_spaces%};
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_RXIDLServiceInterface(const std::string& spaces, const std::string& vssWithColons,
const SFunctionVDDefinition& function) const
{
auto signalStartWithUppercase = function.signalName;
if (!signalStartWithUppercase.empty())
{
signalStartWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(signalStartWithUppercase[0])));
}
std::string prefix = "Service";
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_start_with_uppercase"] = signalStartWithUppercase;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_idltype"] = function.idlType;
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
mapKeywords["prefix"] = prefix;
mapKeywords["multiple_spaces"] = spaces;
mapKeywords["vssWithColons"] = vssWithColons;
return ReplaceKeywords(R"code(%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_Set%function_name% event interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_Set%function_name%_Event
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Set %signal_name% signal
%multiple_spaces% * @param[in] value %signal_name%
%multiple_spaces% */
%multiple_spaces% void Set%function_name%(in %value_idltype% value);
%multiple_spaces%};
%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_Get%function_name% %prefix% interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_Get%function_name%
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Get %signal_name% signal
%multiple_spaces% * @return Returns the %signal_name%
%multiple_spaces% */
%multiple_spaces% %value_idltype% Get%function_name%() const;
%multiple_spaces% /**
%multiple_spaces% * @brief Register Callback on signal change
%multiple_spaces% * @param[in] callback function
%multiple_spaces% */
%multiple_spaces% void RegisterOnSignalChangeOf%signal_start_with_uppercase%(in vss%vssWithColons%Service::IVSS_Set%function_name%_Event callback);
%multiple_spaces% /**
%multiple_spaces% * @brief Unregister Callback
%multiple_spaces% * @param[in] callback function
%multiple_spaces% */
%multiple_spaces% void UnregisterOnSignalChangeOf%signal_start_with_uppercase%(in vss%vssWithColons%Service::IVSS_Set%function_name%_Event callback);
%multiple_spaces%};
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXInterface(const std::string & functionName, const std::string& vssShortenWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vss_shorten_with_colons"] = vssShortenWithColons;
return ReplaceKeywords(R"code( , public vss::%vss_shorten_with_colons%Device::IVSS_%function_name%
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vssWithColons"] = vssWithColons;
return ReplaceKeywords(R"code( SDV_INTERFACE_ENTRY(vss::%vssWithColons%Device::IVSS_%function_name%)
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXReAndUnregisterEvent( const std::string& vssWithColons, const SFunctionVDDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["vssWithColons"] = vssWithColons;
mapKeywords["function_name"] = function.functionName;
return ReplaceKeywords(R"code(
/**
* @brief Register IVSS_Write%function_name%_Event on signal change
* Collect all events and call them on signal change
* @param[in] event function
*/
void Register%function_name%Event(vss::%vssWithColons%Device::IVSS_Write%function_name%_Event* event) override;
/**
* @brief Unregister IVSS_%function_name%_Event
* @param[in] event function
*/
void Unregister%function_name%Event(vss::%vssWithColons%Device::IVSS_Write%function_name%_Event* event) override;
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXPrivateHeaderPart(const SFunctionVDDefinition& function,
const std::string& vssWithColons, const std::string& class_name) const
{
auto startWithUppercase = function.signalName;
if (!startWithUppercase.empty())
{
startWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(startWithUppercase[0])));
}
std::string class_name_lowercase = class_name;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["vssWithColons"] = vssWithColons;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["start_with_uppercase"] = startWithUppercase;
mapKeywords["class_name"] = class_name;
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
/**
* @brief Execute all callbacks
*/
void ExecuteAllCallBacksFor%start_with_uppercase%(sdv::any_t value);
sdv::core::CSignal m_%signal_name%Signal; ///< Signal of the vehicle device
mutable std::mutex m_%signal_name%MutexCallbacks; ///< Mutex protecting m_%signal_name%Callbacks
std::set<vss::%vssWithColons%Device::IVSS_Write%function_name%_Event*> m_%signal_name%Callbacks; ///< collection of events to be called
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXSubscribeSignal(const std::string& class_name, const SFunctionVDDefinition& function) const
{
auto startWithUppercase = function.signalName;
if (!startWithUppercase.empty())
{
startWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(startWithUppercase[0])));
}
std::string class_name_lowercase = class_name;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["object_prefix"] = m_ssPrefix;
mapKeywords["start_with_uppercase"] = startWithUppercase;
mapKeywords["class_name"] = class_name;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
m_%signal_name%Signal = dispatch.Subscribe(%object_prefix%::ds%start_with_uppercase%, [&](sdv::any_t value) { ExecuteAllCallBacksFor%start_with_uppercase%( value ); });
if (!m_%signal_name%Signal)
{
SDV_LOG_ERROR("Could not get signal: ", %object_prefix%::ds%start_with_uppercase%, " [CVehicleDevice%class_name%]");
}
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXCheckSignalSubscribtions(const std::vector <SFunctionVDDefinition>& vecFunctions) const
{
uint32_t count{ 0 };
std::stringstream sstreamFunctions;
sstreamFunctions << " if (!";
for (const auto& func : vecFunctions)
{
count++;
sstreamFunctions << "m_" << func.signalName << "Signal";
if (count != vecFunctions.size())
{
sstreamFunctions << " || !";
}
}
sstreamFunctions << ")" << std::endl;
sstreamFunctions << " {" << std::endl;
sstreamFunctions << " m_status = sdv::EObjectStatus::initialization_failure;" << std::endl;
sstreamFunctions << " return;" << std::endl;
sstreamFunctions << " }" << std::endl;
sstreamFunctions << " m_status = sdv::EObjectStatus::initialized;";
return sstreamFunctions.str();
}
std::string CVSSVDCodingRX::Code_VD_RXResetSignal(const SFunctionVDDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["signal_name"] = function.signalName;
return ReplaceKeywords(R"code( m_%signal_name%Signal.Reset();
)code", mapKeywords);
}
std::string CVSSVDCodingRX::Code_VD_RXRegister( const std::string& class_name, const SFunctionVDDefinition& function,
const std::string& vssWithColons) const
{
auto startWithUppercase = function.signalName;
if (!startWithUppercase.empty())
{
startWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(startWithUppercase[0])));
}
std::string class_name_lowercase = class_name;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["vssWithColons"] = vssWithColons;
mapKeywords["function_name"] = function.functionName;
mapKeywords["start_with_uppercase"] = startWithUppercase;
mapKeywords["class_name"] = class_name;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
/**
* @brief Register %function_name% event on signal change
* Collect all events and call them on signal change
* @param[in] event function
*/
void CVehicleDevice%class_name%::Register%function_name%Event(vss::%vssWithColons%Device::IVSS_Write%function_name%_Event* event)
{
if (event)
{
std::lock_guard<std::mutex> lock(m_%signal_name%MutexCallbacks);
m_%signal_name%Callbacks.insert(event);
}
}
/**
* @brief Unregister %function_name% event
* @param[in] event function
*/
void CVehicleDevice%class_name%::Unregister%function_name%Event(vss::%vssWithColons%Device::IVSS_Write%function_name%_Event* event)
{
if (event)
{
std::lock_guard<std::mutex> lock(m_%signal_name%MutexCallbacks);
m_%signal_name%Callbacks.erase(event);
}
}
/**
* @brief Execute all callbacks
*/
void CVehicleDevice%class_name%::ExecuteAllCallBacksFor%start_with_uppercase%(sdv::any_t value)
{
%value_ctype% %signal_name% = value.get<%value_ctype%>();
//
// TODO:
// Convert vehicle specific value to abstract unit/range
//
std::lock_guard<std::mutex> lock(m_%signal_name%MutexCallbacks);
for (const auto& callback : m_%signal_name%Callbacks)
{
callback->Write%function_name%(%signal_name%);
}
}
)code", mapKeywords);
}

View File

@@ -0,0 +1,150 @@
#ifndef VSS_VD_CODING_RX_H
#define VSS_VD_CODING_RX_H
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <interfaces/dispatch.h>
#include "codegen_base.h"
#include "vss_helper.h"
#include "vss_rx_templates.h"
#include "vss_coding.h"
/**
* @brief VSS code generator coding class for vehicle devices.
* Creates the code out of templates
*/
class CVSSVDCodingRX : public CCodeGeneratorBase, CVSSHelper
{
public:
/**
* @brief Constructor
* @param[in] rsPrefix used by cmake library and signal definition in signal_identifier.h file
*/
CVSSVDCodingRX(const std::string& rsPrefix) : m_ssPrefix(rsPrefix) {}
/**
* @brief create device content for the IDL file of a RX signal
* @param[in] vssParts Interface in vss style separated in parts
* @param[in] vecFunctions container of all functions of a single vss definition
* @return content of the Device part of a IDL Interface of a RX signal
*/
std::string Code_RXIDLDeviceList(const std::vector<std::string>& vssParts, const std::vector <SFunctionVDDefinition>& vecFunctions) const;
/**
* @brief create service content for the IDL file of a RX signal
* @param[in] vssParts Interface in vss style separated in parts
* @param[in] vecFunctions container of all functions of a single vss definition
* @return content of the Device part of a IDL Interface of a RX signal
*/
std::string Code_RXIDLServiceList(const std::vector<std::string>& vssParts, const std::vector <SFunctionVDDefinition>& vecFunctions) const;
/**
* @brief fill the KeyWordMap with all required strings
* @param[in] signal signal definition structure to fill the KeyWordMap
* @param[in] mapKeywords KeyWordMap to be filled
*/
void GetKeyWordMap(const SSignalVDDefinition& signal, CKeywordMap& mapKeywords) const;
protected:
/**
* @brief create single or multiple lines containing include files
* @param[in] vssOriginalNoDot vss string without points e.g. VehicleChassisSteeringWheelAngle
* @return content of a single interface
*/
std::string Code_VD_RXIncludes(const std::string& vssOriginalNoDot) const;
/**
* @brief create a single line containing a interface
* @param[in] functionName function which is part of the interface
* @param[in] vssShortenWithColons vss string (short version) with colons as separator
* @return content of a single interface
*/
std::string Code_VD_RXInterface(const std::string& functionName, const std::string& vssShortenWithColons) const;
/**
* @brief create a single line containing a interface entry
* @param[in] functionName function which is part of the interface
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @return content of a single interface entry
*/
std::string Code_VD_RXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const;
/**
* @brief Get the register and unregister part for the RX VD header
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @param[in] function function definition structure
* @return content of a single register and unregister part.
*/
std::string Code_VD_RXReAndUnregisterEvent(const std::string& vssWithColons, const SFunctionVDDefinition& function) const;
/**
* @brief Get the private header part of the vehicle device header
* @param[in] function function definition structure
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @param[in] class_name class name which is part of the interface
* @return content of private header part of the vehicle device header
*/
std::string Code_VD_RXPrivateHeaderPart(const SFunctionVDDefinition& function, const std::string& vssWithColons,
const std::string& class_name) const;
/**
* @brief create device content for the IDL file of a RX signal
* @param[in] spaces string containing only space characters for aligning
* @param[in] function function definition structure
* @return content of the Device part of a IDL Interface of a RX signal
*/
std::string Code_RXIDLDeviceInterface(const std::string& spaces, const SFunctionVDDefinition& function) const;
/**
* @brief create service content for the IDL file of a RX signal
* @param[in] spaces string containing only space characters for aligning
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @param[in] function function definition structure
* @return content of the Device part of a IDL Interface of a RX signal
*/
std::string Code_RXIDLServiceInterface(const std::string& spaces, const std::string& vssWithColons,
const SFunctionVDDefinition& function) const;
/**
* @brief subscribe signals (RX type) for vehicle device
* @param[in] class_name class name which is part of the interface
* @param[in] function function definition structure
* @return content of a initializing code
*/
std::string Code_VD_RXSubscribeSignal(const std::string& class_name, const SFunctionVDDefinition& function) const;
/**
* @brief subscribe signals (RX type) for vehicle device
* @param[in] vecFunctions list of functions of the vss interface
* @return content of a initializing code
*/
std::string Code_VD_RXCheckSignalSubscribtions(const std::vector <SFunctionVDDefinition>& vecFunctions) const;
/**
* @brief Rest signal (RX signals) for vehicle device cpp file
* @param[in] function function definition structure
* @return content of a single signal reset implementation
*/
std::string Code_VD_RXResetSignal(const SFunctionVDDefinition& function) const;
/**
* @brief create register/unregister and callback function code for vehicle device
* @param[in] class_name class name which is part of the interface
* @param[in] function function definition structure
* @param[in] vssWithColons vss string with colons as separator
* @return content of a single signal register/unregister and callback code
*/
std::string Code_VD_RXRegister(const std::string& class_name, const SFunctionVDDefinition& function,
const std::string& vssWithColons) const;
std::string m_ssPrefix; ///< prefix, used by cmake library and signal definition in signal_identifier.h file.
};
#endif // !defined VSS_VD_CODING_RX_H

View File

@@ -0,0 +1,286 @@
#include "vss_vd_codingtx.h"
void CVSSVDCodingTX::GetKeyWordMap(const SSignalVDDefinition& signal, CKeywordMap& mapKeywords) const
{
std::string vssWithColons = ReplaceCharacters(signal.vssDefinition, ".", "::");
//------------------------------------------------------- vehicle device header
std::stringstream sstreamIncludesVD;
std::string vssNoDot = ReplaceCharacters(signal.vssDefinition, ".", "");
std::transform(vssNoDot.begin(), vssNoDot.end(), vssNoDot.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
sstreamIncludesVD << Code_VD_TXIncludes(vssNoDot);
mapKeywords["tx_vd_includes_list"] = std::move(sstreamIncludesVD.str());
std::stringstream sstreamInterfacesVD;
for (const auto& func : signal.vecFunctions)
{
sstreamInterfacesVD << Code_VD_TXInterface(func.functionName, vssWithColons);
}
mapKeywords["tx_vd_interface_list"] = std::move(sstreamInterfacesVD.str());
std::stringstream sstreamInterfaceEntriesVD;
for (const auto& func : signal.vecFunctions)
{
sstreamInterfaceEntriesVD << Code_VD_TXInterfaceEntry(func.functionName, vssWithColons);
}
mapKeywords["tx_vd_interface_entry_list"] = std::move(sstreamInterfaceEntriesVD.str());
std::stringstream sstreamFunctionsVD;
for (const auto& func : signal.vecFunctions)
{
sstreamFunctionsVD << Code_VD_TXFunction(func);
}
mapKeywords["tx_vd_function_list"] = std::move(sstreamFunctionsVD.str());
std::stringstream sstreamVariables;
for (const auto& func : signal.vecFunctions)
{
sstreamVariables << Code_VD_TXVariable(func.signalName);
}
mapKeywords["tx_variable_list"] = std::move(sstreamVariables.str());
//------------------------------------------------------- vehicle device cpp
std::stringstream sstreamVariableInitializations;
for (const auto& func : signal.vecFunctions)
{
sstreamVariableInitializations << Code_VD_TXVariableInitialization(func);
}
mapKeywords["tx_variable_init_list"] = std::move(sstreamVariableInitializations.str());
if (signal.vecFunctions.size() > 0)
{
mapKeywords["tx_variable_check_list"] = Code_VD_TXVariableCheckInitialization(signal.vecFunctions);
}
std::stringstream sstreamResetSignal;
for (const auto& func : signal.vecFunctions)
{
sstreamResetSignal << Code_VD_TXResetSignal(func);
}
mapKeywords["tx_reset_signals"] = std::move(sstreamResetSignal.str());
std::stringstream sstreamFunctionImplementation;
for (const auto& func : signal.vecFunctions)
{
sstreamFunctionImplementation << Code_VD_TXFunctionImplementation(func, signal.className);
}
mapKeywords["tx_function_implementations"] = std::move(sstreamFunctionImplementation.str());
}
std::string CVSSVDCodingTX::Code_VD_TXIDLList(const std::vector<std::string>& vssParts,
const std::vector <SFunctionVDDefinition>& vecFunctions) const
{
int8_t loop = 1;
std::string nameSpace = "module vss\n{\n";
for (auto it = vssParts.begin(); it != vssParts.end(); ++it)
{
nameSpace.append(static_cast <int8_t>(4) * loop, ' ');
nameSpace.append("module ");
nameSpace.append(*it);
if (it == vssParts.end() - 1)
{
nameSpace.append("Device");
}
nameSpace.append("\n");
nameSpace.append(static_cast <int8_t>(4) * loop++, ' ');
nameSpace.append("{\n");
}
nameSpace.append("%interfaces%");
loop--;
for (size_t i = 0; i < vssParts.size() + 1; i++)
{
nameSpace.append(static_cast <int8_t>(4) * loop--, ' ');
nameSpace.append("};\n");
}
bool newLine = false;
std::string spaces = "";
spaces.append(static_cast <int8_t>(4) * (vssParts.size() + 1), ' ');
std::stringstream sstreamInterfaces;
for (auto func : vecFunctions)
{
if (newLine)
sstreamInterfaces << "\n\n";
else
newLine = true;
sstreamInterfaces << Code_VD_TXIDLInterface(spaces, func);
}
CKeywordMap mapKeywords;
mapKeywords["interfaces"] = std::move(sstreamInterfaces.str());
return ReplaceKeywords(nameSpace, mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXIncludes(const std::string& vssOriginalNoDot) const
{
CKeywordMap mapKeywords;
mapKeywords["vss_original_no_dot"] = vssOriginalNoDot;
return ReplaceKeywords(R"code(#include "../vss_%vss_original_no_dot%_vd_tx.h")code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXInterface(const std::string& functionName, const std::string& vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vss_with_colons"] = vssWithColons;
return ReplaceKeywords(R"code( , public vss::%vss_with_colons%Device::IVSS_Write%function_name%
)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = functionName;
mapKeywords["vss_with_colons"] = vssWithColons;
return ReplaceKeywords(R"code( SDV_INTERFACE_ENTRY(vss::%vss_with_colons%Device::IVSS_Write%function_name%)
)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXIDLInterface(const std::string& spaces, const SFunctionVDDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_idltype"] = function.idlType;
mapKeywords["value_ctype"] = GetCTypeFromIDLType(function.idlType);
mapKeywords["multiple_spaces"] = spaces;
return ReplaceKeywords(R"code(%multiple_spaces%/**
%multiple_spaces%* @brief IVSS_Write%function_name% Device interface
%multiple_spaces%*/
%multiple_spaces%interface IVSS_Write%function_name%
%multiple_spaces%{
%multiple_spaces% /**
%multiple_spaces% * @brief Write %signal_name% signal
%multiple_spaces% * @param[in] value
%multiple_spaces% * @return true on success otherwise false
%multiple_spaces% */
%multiple_spaces% boolean Write%function_name%(in %value_idltype% value);
%multiple_spaces%};
)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXFunction(const SFunctionVDDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["value_idltype"] = function.idlType;
auto signalType = GetCTypeFromIDLType(function.idlType);
mapKeywords["value_ctype"] = CastValueType(signalType);
return ReplaceKeywords(R"code(
/**
* @brief Set %signal_name% signal
* @param[in] value
* @return true on success otherwise false
*/
bool Write%function_name%(%value_ctype% value) override;
)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXResetSignal(const SFunctionVDDefinition& function) const
{
CKeywordMap mapKeywords;
mapKeywords["signal_name"] = function.signalName;
return ReplaceKeywords(R"code( m_%signal_name%.Reset();
)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXFunctionImplementation(const SFunctionVDDefinition& function, const std::string& className) const
{
std::string class_name_lowercase = className;
std::transform(class_name_lowercase.begin(), class_name_lowercase.end(), class_name_lowercase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
CKeywordMap mapKeywords;
mapKeywords["function_name"] = function.functionName;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["class_name"] = className;
auto signalType = GetCTypeFromIDLType(function.idlType);
mapKeywords["value_ctype"] = CastValueType(signalType);
mapKeywords["class_name_lowercase"] = class_name_lowercase;
return ReplaceKeywords(R"code(
/**
* @brief %function_name%
* @param[in] value
* @return true on success otherwise false
*/
bool CVehicleDevice%class_name%::Write%function_name%(%value_ctype% value)
{
if (m_%signal_name%)
{
//
// TODO:
// Convert abstract value to vehicle specific unit/range
//
m_%signal_name%.Write(value);
return true;
}
return false;
}
)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXVariable(const std::string& signalName) const
{
CKeywordMap mapKeywords;
mapKeywords["signal_name"] = signalName;
return ReplaceKeywords(R"code(
sdv::core::CSignal m_%signal_name%; ///< %signal_name% signal)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXVariableInitialization(const SFunctionVDDefinition& function) const
{
CKeywordMap mapKeywords;
auto startWithUppercase = function.signalName;
if (!startWithUppercase.empty())
{
startWithUppercase[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(startWithUppercase[0])));
}
mapKeywords["start_with_uppercase"] = startWithUppercase;
mapKeywords["signal_name"] = function.signalName;
mapKeywords["object_prefix"] = m_ssPrefix;
return ReplaceKeywords(R"code(
m_%signal_name% = dispatch.AddPublisher(%object_prefix%::ds%start_with_uppercase%);
if (!m_%signal_name%)
{
SDV_LOG_ERROR("Could not get signal: ", %object_prefix%::ds%start_with_uppercase%, " [CVehicleDevice%class_name%]");
}
)code", mapKeywords);
}
std::string CVSSVDCodingTX::Code_VD_TXVariableCheckInitialization(const std::vector <SFunctionVDDefinition>& vecFunctions) const
{
uint32_t count { 0 };
std::stringstream sstreamFunctions;
sstreamFunctions << " if (!";
for (auto func : vecFunctions)
{
count++;
sstreamFunctions << "m_" << func.signalName;
if (count != vecFunctions.size())
{
sstreamFunctions << " || !";
}
}
sstreamFunctions << ")" << std::endl;
sstreamFunctions << " {" << std::endl;
sstreamFunctions << " m_status = sdv::EObjectStatus::initialization_failure;" << std::endl;
sstreamFunctions << " return;" << std::endl;
sstreamFunctions << " }" << std::endl;
sstreamFunctions << " m_status = sdv::EObjectStatus::initialized;";
return sstreamFunctions.str();
}

View File

@@ -0,0 +1,125 @@
#ifndef VSS_CODING_TX_H
#define VSS_CODING_TX_H
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <interfaces/dispatch.h>
#include "codegen_base.h"
#include "vss_helper.h"
#include "vss_tx_templates.h"
#include "vss_coding.h"
/**
* @brief VSS code generator coding class.
* Creates the code out of templates
*/
class CVSSVDCodingTX : public CCodeGeneratorBase, CVSSHelper
{
public:
/**
* @brief Constructor
* @param[in] rsPrefix used by cmake library and signal definition in signal_identifier.h file
*/
CVSSVDCodingTX(const std::string& rsPrefix) : m_ssPrefix(rsPrefix) {}
/**
* @brief create vehicle device content for the IDL file of a TX signal
* @param[in] vssParts Interface in vss style separated in parts
* @param[in] vecFunctions container of all functions of a single vss definition
* @return content of the vehicle device part of a IDL Interface of a TX signal
*/
std::string Code_VD_TXIDLList(const std::vector<std::string>& vssParts,
const std::vector <SFunctionVDDefinition>& vecFunctions) const;
/**
* @brief fill the KeyWordMap with all required strings
* @param[in] signal signal definition structure to fill the KeyWordMap
* @param[in] mapKeywords KeyWordMap to be filled
*/
void GetKeyWordMap(const SSignalVDDefinition& signal, CKeywordMap& mapKeywords) const;
protected:
/**
* @brief create single or multiple lines containing include files
* @param[in] vssOriginalNoDot vss string without points e.g. VehicleChassisSteeringWheelAngle
* @return content of a single interface
*/
std::string Code_VD_TXIncludes(const std::string& vssOriginalNoDot) const;
/**
* @brief create a single line containing a interface for vehicle device
* @param[in] functionName function which is part of the interface
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @return content of a single interface
*/
std::string Code_VD_TXInterface(const std::string& functionName, const std::string& vssWithColons) const;
/**
* @brief create a single line containing a interface entry for vehicle device
* @param[in] functionName function which is part of the interface
* @param[in] vssWithColons vss string (complete version) with colons as separator
* @return content of a single interface entry
*/
std::string Code_VD_TXInterfaceEntry(const std::string& functionName, const std::string& vssWithColons) const;
/**
* @brief create list of interfaces (TX signals) for IDL file (Vehicle Device)
* @param[in] spaces string containing only space characters for aligning
* @param[in] function function definition structure
* @return content of a single interface entry
*/
std::string Code_VD_TXIDLInterface(const std::string& spaces, const SFunctionVDDefinition& function) const;
/**
* @brief create function definition part (TX signals) for vehicle device
* @param[in] function function definition structure
* @return content of a single function declaration
*/
std::string Code_VD_TXFunction(const SFunctionVDDefinition& function) const;
/**
* @brief Rest signal (TX signals) for vehicle device cpp file
* @param[in] function function definition structure
* @return content of a single signal reset implementation
*/
std::string Code_VD_TXResetSignal(const SFunctionVDDefinition& function) const;
/**
* @brief create function implementation part (TX signals) for vehicle device cpp file
* @param[in] function function definition structure
* @param[in] className class name of the signal
* @return content of a single function implementation
*/
std::string Code_VD_TXFunctionImplementation(const SFunctionVDDefinition& function, const std::string& className) const;
/**
* @brief create single variable definition (TX signals) for vehicle device header
* @param[in] signalName name of the signal
* @return content of a single variable definition
*/
std::string Code_VD_TXVariable(const std::string& signalName) const;
/**
* @brief create single variable initialization (TX signals) for vehicle device cpp file
* @param[in] function which is part of the interface
* @return content of a single variable initialization
*/
std::string Code_VD_TXVariableInitialization(const SFunctionVDDefinition& function) const;
/**
* @brief create check if all interfaces are valid (TX signals) for vehicle device cpp file
* @param[in] vecFunctions container of all functions of a single vss definition
* @return content to check if all interfaces are valid
*/
std::string Code_VD_TXVariableCheckInitialization(const std::vector <SFunctionVDDefinition>& vecFunctions) const;
std::string m_ssPrefix; ///< prefix, used by cmake library and signal definition in signal_identifier.h file.
};
#endif // !defined VSS_CODING_TX_H

View File

@@ -0,0 +1,287 @@
#include "vss_vd_generator.h"
#include "vss_coding.h"
#include "vss_vd_codingrx.h"
#include "vss_vd_codingtx.h"
bool CVSSVDGenerator::GeneratedCode()
{
// Create project directory
if (!m_pathProject.empty())
{
m_pathProject /= "vss_files";
if (CreateFolder(m_pathProject, ""))
{
std::filesystem::path pathSummary = m_pathProject / "summary.txt";
std::filesystem::path pathSignalIds = m_pathProject / "signal_identifier.h";
CVSSCodingCommon coding(m_ssPrefix);
CreateFiles(m_ssVersion);
std::ofstream fstreamSummary; ///< Build description summery.txt file
fstreamSummary.open(pathSummary, std::ios::out | std::ios::trunc);
fstreamSummary << SummaryTextFile();
fstreamSummary.close();
std::ofstream fstreamSignalIds; ///< Build description SignalIdetifier.h file
fstreamSignalIds.open(pathSignalIds, std::ios::out | std::ios::trunc);
fstreamSignalIds << coding.Code_SignalIdentifier(m_signals, pathSignalIds.filename().generic_u8string(), m_ssVersion);
fstreamSignalIds.close();
return true;
}
}
return false;
}
std::string CVSSVDGenerator::SummaryTextFile() const
{
//std::string titlePrefix ="Object prefix";
std::string titleClassName = "Class name";
std::string titleSignalName = "Signal name";
std::string titleCANSignalName = "CAN Signal name";
std::string titleFunctionname = "Function name";
std::string titleIDLType = "IDL-Type";
std::string titleCType = "C-Type";
std::string titleVSS = "vss Definition";
bool addTitle = true;
std::stringstream sstream;
for (const auto& signal : m_signals)
{
if (addTitle)
{
addTitle = false;
sstream << "\n";
sstream << Align(titleClassName, GetMaxClassName(m_signals, titleClassName)) << "\t";
sstream << Align(titleSignalName, GetMaxSignalName(m_signals, titleSignalName)) << "\t";
sstream << Align(titleCANSignalName, GetMaxCANSignalName(m_signals, titleCANSignalName)) << "\t";
sstream << Align(titleFunctionname, GetMaxFunctionName(m_signals, titleFunctionname)) << "\t";
sstream << Align("RX/TX ", 6) << "\t";
sstream << Align(titleIDLType, GetMaxIDLType(m_signals, titleIDLType)) << "\t";
sstream << Align(titleCType, GetMaxCTypeFromIDLType(m_signals, titleCType)) << "\t";
sstream << Align(titleVSS, GetMaxVSSDefinition(m_signals, titleVSS)) << "\t";
sstream << "\n\n";
}
for (const auto& func : signal.vecFunctions)
{
sstream << Align(signal.className, GetMaxClassName(m_signals, titleClassName)) << "\t";
sstream << Align(func.signalName, GetMaxSignalName(m_signals, titleSignalName)) << "\t";
sstream << Align(func.canSignalName, GetMaxCANSignalName(m_signals, titleCANSignalName)) << "\t";
sstream << Align(func.functionName, GetMaxFunctionName(m_signals, titleFunctionname)) << "\t";
if (signal.signalDirection == sdv::core::ESignalDirection::sigdir_rx)
sstream << "'RX' " << "\t";
else
sstream << "'TX' " << "\t";
sstream << Align(func.idlType, GetMaxIDLType(m_signals, titleIDLType)) << "\t";
sstream << Align(GetCTypeFromIDLType(func.idlType), GetMaxCTypeFromIDLType(m_signals, titleCType)) << "\t";
sstream << Align(signal.vssDefinition, GetMaxVSSDefinition(m_signals, titleVSS)) << "\t\n";
}
}
return sstream.str();
}
std::string CVSSVDGenerator::AppendExtension(const std::string& prefix, const std::string& filename,
const std::string& extension) const
{
return prefix + filename + extension;
}
void CVSSVDGenerator::CreateFiles(const std::string& ssVersion)
{
for (const SSignalVDDefinition& signal : m_signals)
{
if (signal.signalDirection == sdv::core::ESignalDirection::sigdir_rx)
m_RXsignals.push_back(signal);
else
m_TXsignals.push_back(signal);
}
CreateRXFiles(ssVersion);
CreateTXFiles(ssVersion);
}
void CVSSVDGenerator::CreateRXFiles(const std::string& ssVersion) const
{
for (const auto& rxSignal : m_RXsignals)
{
if (m_enableComponentCreation)
{
CreateVehicleDeviceFilesForRXSignal(rxSignal, ssVersion);
}
CreateIDLVehicleDeviceFileForRXSignal(rxSignal, ssVersion);
}
}
void CVSSVDGenerator::CreateVehicleDeviceFilesForRXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const
{
std::string folderName = "VD_";
folderName.append(signal.className);
std::transform(folderName.begin(), folderName.end(), folderName.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
if (!CreateFolder(m_pathProject, folderName))
{
return;
}
std::filesystem::path pathVDHeader = m_pathProject / folderName / AppendExtension("VD_", signal.className, ".h");
std::filesystem::path pathVDClass = m_pathProject / folderName / AppendExtension("VD_", signal.className, ".cpp");
std::filesystem::path pathCMakeLists = m_pathProject / folderName / "CMakeLists.txt";
std::ofstream fstreamVDHeader;
std::ofstream fstreamVDClass;
auto pathLowerCaseHeader = MakeLowercaseFilename(pathVDHeader);
auto pathLowerCaseClass = MakeLowercaseFilename(pathVDClass);
fstreamVDHeader.open(pathLowerCaseHeader, std::ios::out | std::ios::trunc);
fstreamVDClass.open(pathLowerCaseClass, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["vd_safeguard"] = coding.Code_SafeGuard(pathVDHeader.filename().generic_u8string());
mapKeywords["abstract_device_h"] = pathLowerCaseHeader.filename().generic_u8string();
mapKeywords["abstract_device_cpp"] = pathLowerCaseClass.filename().generic_u8string();
CVSSVDCodingRX codingRX(m_ssPrefix);
codingRX.GetKeyWordMap(signal, mapKeywords);
fstreamVDHeader << ReplaceKeywords(szRXVehicleDeviceHeaderTemplate, mapKeywords);
fstreamVDClass << ReplaceKeywords(szRXVehicleDeviceClassTemplate, mapKeywords);
fstreamVDHeader.close();
fstreamVDClass.close();
// create/write CMakeLists.txt only if content has changed
std::string libaryName = m_ssPrefix;
libaryName.append("_vd_");
std::string classNameLowerCase = signal.className;
std::transform(classNameLowerCase.begin(), classNameLowerCase.end(), classNameLowerCase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
libaryName.append(classNameLowerCase);
libaryName.append("_rx");
auto cmakeContent = coding.Code_CMakeProject(libaryName, folderName);
CreateCMakeFile(pathCMakeLists, cmakeContent);
}
void CVSSVDGenerator::CreateIDLVehicleDeviceFileForRXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const
{
std::stringstream ss(signal.vssDefinition);
std::string item;
std::string filenameVD = "VSS_";
std::vector<std::string> parts;
while (std::getline(ss, item, '.'))
{
parts.push_back(item);
filenameVD.append(item);
}
filenameVD.append("_vd_rx");
DeleteHeaderFile(m_pathProject, filenameVD);
filenameVD.append(".idl");
std::filesystem::path pathVDRXIDL = m_pathProject / filenameVD;
std::ofstream fstreamVDRXIDL;
auto pathLowerCase = MakeLowercaseFilename(pathVDRXIDL);
fstreamVDRXIDL.open(pathLowerCase, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["_vd_idl_h"] = pathLowerCase.filename().generic_u8string();
CVSSVDCodingRX codingRX(m_ssPrefix);
mapKeywords["vss_device"] = codingRX.Code_RXIDLDeviceList(parts, signal.vecFunctions);
mapKeywords["vss_service"] = codingRX.Code_RXIDLServiceList(parts, signal.vecFunctions);
fstreamVDRXIDL << ReplaceKeywords(szVDRXIDLTemplate, mapKeywords);
fstreamVDRXIDL.close();
}
void CVSSVDGenerator::CreateTXFiles(const std::string& ssVersion) const
{
for (const auto& txSignal : m_TXsignals)
{
if (m_enableComponentCreation)
{
CreateVehicleDeviceFilesForTXSignal(txSignal, ssVersion);
}
CreateIDLVehicleDeviceFileForTXSignal(txSignal, ssVersion);
}
}
void CVSSVDGenerator::CreateVehicleDeviceFilesForTXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const
{
std::string folderName = "VD_";
folderName.append(signal.className);
std::transform(folderName.begin(), folderName.end(), folderName.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
if (!CreateFolder(m_pathProject, folderName))
{
return;
}
std::filesystem::path pathVDHeader = m_pathProject / folderName / AppendExtension("VD_", signal.className, ".h");
std::filesystem::path pathVDClass = m_pathProject / folderName / AppendExtension("VD_", signal.className, ".cpp");
std::filesystem::path pathCMakeLists = m_pathProject / folderName / "CMakeLists.txt";
std::ofstream fstreamVDHeader;
std::ofstream fstreamVDClass;
auto pathLowerCaseHeader = MakeLowercaseFilename(pathVDHeader);
auto pathLowerCaseClass = MakeLowercaseFilename(pathVDClass);
fstreamVDHeader.open(pathLowerCaseHeader, std::ios::out | std::ios::trunc);
fstreamVDClass.open(pathLowerCaseClass, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["vd_safeguard"] = coding.Code_SafeGuard(pathVDHeader.filename().generic_u8string());
mapKeywords["abstract_device_h"] = pathLowerCaseHeader.filename().generic_u8string();
mapKeywords["abstract_device_cpp"] = pathLowerCaseClass.filename().generic_u8string();
CVSSVDCodingTX codingTX(m_ssPrefix);
codingTX.GetKeyWordMap(signal, mapKeywords);
mapKeywords["abstract_device_h"] = pathVDHeader.filename().generic_u8string();
mapKeywords["abstract_device_cpp"] = pathVDClass.filename().generic_u8string();
fstreamVDHeader << ReplaceKeywords(szTXVehicleDeviceHeaderTemplate, mapKeywords);
fstreamVDClass << ReplaceKeywords(szTXVehicleDeviceClassTemplate, mapKeywords);
fstreamVDHeader.close();
fstreamVDClass.close();
std::string classNameLowerCase = signal.className;
std::transform(classNameLowerCase.begin(), classNameLowerCase.end(), classNameLowerCase.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
std::string libaryName = m_ssPrefix + "_vd_" + classNameLowerCase + "_tx";
auto cmakeContent = coding.Code_CMakeProject(libaryName, folderName);
CreateCMakeFile(pathCMakeLists, cmakeContent);
}
void CVSSVDGenerator::CreateIDLVehicleDeviceFileForTXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const
{
std::stringstream ss(signal.vssDefinition);
std::string item;
std::string filenameVD = "VSS_";
std::vector<std::string> parts;
while (std::getline(ss, item, '.'))
{
parts.push_back(item);
filenameVD.append(item);
}
filenameVD.append("_vd_tx");
DeleteHeaderFile(m_pathProject, filenameVD);
filenameVD.append(".idl");
std::filesystem::path pathVDTXIDL = m_pathProject / filenameVD;
std::ofstream fstreamVDTXIDL;
auto pathLowerCase = MakeLowercaseFilename(pathVDTXIDL);
fstreamVDTXIDL.open(pathLowerCase, std::ios::out | std::ios::trunc);
CKeywordMap mapKeywords;
CVSSCodingCommon coding(m_ssPrefix);
coding.GetCommonKeyWordMap(signal, mapKeywords, ssVersion);
mapKeywords["_vd_idl_h"] = pathLowerCase.filename().generic_u8string();
CVSSVDCodingTX codingTX(m_ssPrefix);
mapKeywords["vss_device"] = codingTX.Code_VD_TXIDLList(parts, signal.vecFunctions);
fstreamVDTXIDL << ReplaceKeywords(szVDTXIDLTemplate, mapKeywords);
fstreamVDTXIDL.close();
}

View File

@@ -0,0 +1,109 @@
#ifndef VSS_VD_GENERATOR_H
#define VSS_VD_GENERATOR_H
#include <fstream>
#include "codegen_base.h"
#include "vss_helper.h"
/**
* @brief Basic Service generator.
*/
class CVSSVDGenerator : public CCodeGeneratorBase, CVSSHelper
{
public:
/**
* @brief Constructor
* @param[in] signals Reference to a vector containing all signals
* @param[in] rpathOutputDir Reference to the outpur directory.
* @param[in] rsPrefix used by cmake library and signal definition in signal_identifier.h file
* @param[in] rsVersion optional version tag, will be wriiten in header of the files
* @param[in] enableComponentCreation optional version tag, will be wriiten in header of the files
*/
CVSSVDGenerator(const std::vector<SSignalVDDefinition>& signals, const std::filesystem::path& rpathOutputDir, const std::string& rsPrefix, const std::string& rsVersion, const bool enableComponentCreation) :
m_enableComponentCreation(enableComponentCreation),
m_ssPrefix(rsPrefix),
m_ssVersion(rsVersion),
m_pathProject(rpathOutputDir),
m_signals(signals)
{}
/**
* @brief Auto generate the Files
* @return true on success, otherwise false
*/
bool GeneratedCode();
private:
/**
* @brief create content of the summary tect file
* @return string containing the complete content of the summary text file;
*/
std::string SummaryTextFile() const;
/**
* @brief create a file name including prefix and extension
* @param[in] prefix
* @param[in] filename
* @param[in] extension
* @return combined file name
*/
std::string AppendExtension(const std::string& prefix, const std::string& filename, const std::string& extension) const;
/**
* @brief create vehicle device and basic service .h an .cpp files
* create IDL files
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateFiles(const std::string& ssVersion);
/**
* @brief create IDL files and vehicle device and basic service files of RX signals
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateRXFiles(const std::string& ssVersion) const;
/**
* @brief create vehicle device files of a single RX signal
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateVehicleDeviceFilesForRXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const;
/**
* @brief create IDL file of a single RX signal (vehicle device)
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateIDLVehicleDeviceFileForRXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const;
/**
* @brief create IDL files and vehicle device and basic service files of TX signals
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateTXFiles(const std::string& ssVersion) const;
/**
* @brief create vehicle device files of a single TX signal
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateVehicleDeviceFilesForTXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const;
/**
* @brief create IDL file for a single TX signal (vehicle device)
* @param[in] signal single signal definition
* @param[in] ssVersion optional information will be placed in the header of the files
*/
void CreateIDLVehicleDeviceFileForTXSignal(const SSignalVDDefinition& signal, const std::string& ssVersion) const;
bool m_enableComponentCreation; ///< if set, the code for the components are created, otherwise only idl files
std::string m_ssPrefix; ///< prefix, used by cmake library and signal definition in signal_identifier.h file.
std::string m_ssVersion; ///< optional version tag, will be wriiten in header of the files
std::filesystem::path m_pathProject; ///< Project file path
std::vector <SSignalVDDefinition> m_signals; ///< all signals
std::vector <SSignalVDDefinition> m_TXsignals; ///< vector containing the RX signals
std::vector <SSignalVDDefinition> m_RXsignals; ///< vector containing the TX signals
};
#endif // !defined VSS_VD_GENERATOR_H