Files
salmanoff/include/user/deviceAttachmentSpec.h
T
hayodea 27a5d48451 Lg1: Implement both light|darkAmbience stimBuffs & their production
We now produce both light and dark ambience stimframes into
stimbuffs for the LivoxGen1 lidar devices.
2026-04-18 14:54:14 -04:00

239 lines
7.5 KiB
C++

#ifndef SENSORDEVICESPEC_H
#define SENSORDEVICESPEC_H
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <stdexcept>
namespace smo {
namespace device {
/* Carrier used by the DAP spec parser to pass one parenthesized segment
* (e.g. postrin(interest-pc=85) or pcloudLightAmbience(...)) up the reduction
* stack; the spec_body reduction classifies segments and populates the
* DeviceAttachmentSpec. Defined here so both the parser header and consumers
* of the generated header see the type.
*/
struct DapSegment
{
std::string name;
std::vector<std::pair<std::string, std::string>> params;
};
class DeviceAttachmentSpec
{
public:
friend std::ostream& operator<<(
std::ostream& os, const DeviceAttachmentSpec& spec)
{
os << spec.stringify();
return os;
}
bool operator==(const DeviceAttachmentSpec& other) const
{
return deviceIdentifier == other.deviceIdentifier &&
sensorType == other.sensorType &&
postrin == other.postrin &&
negtrin == other.negtrin &&
qualeIfaceApi == other.qualeIfaceApi &&
stimBuffApi == other.stimBuffApi &&
provider == other.provider &&
deviceSelector == other.deviceSelector;
}
public:
std::string deviceIdentifier;
char sensorType;
/* postrin/negtrin hold the literal segment name ("postrin" /
* "negtrin") when present, empty string when the DAP spec omits the
* corresponding intrin specifier. Params vectors carry the params from
* within the postrin(...)/negtrin(...) segment.
*/
std::string postrin;
std::vector<std::pair<std::string,std::string>> postrinParams;
std::string negtrin;
std::vector<std::pair<std::string,std::string>> negtrinParams;
std::string qualeIfaceApi;
std::vector<std::pair<std::string,std::string>> qualeIfaceApiParams;
std::string stimBuffApi;
std::vector<std::pair<std::string,std::string>> stimBuffApiParams;
std::string provider;
std::vector<std::pair<std::string,std::string>> providerParams;
std::string deviceSelector;
static void stringifyParams(
std::ostream& os,
const std::vector<std::pair<std::string,std::string>>& params)
{
for (const auto& param : params)
{
os << param.first;
if (!param.second.empty()) {
os << "=" << param.second;
}
os << " ";
}
}
std::string stringify() const
{
std::ostringstream os;
os << "Device Identifier: " << deviceIdentifier
<< ", Sensor Type: " << sensorType;
if (!postrin.empty())
{
os << ", Postrin Params: (";
stringifyParams(os, postrinParams);
os << ")";
}
if (!negtrin.empty())
{
os << ", Negtrin Params: (";
stringifyParams(os, negtrinParams);
os << ")";
}
os << ", QualeIface API: " << qualeIfaceApi << ", QualeIface API Params: (";
for (const auto& param : qualeIfaceApiParams)
{
os << param.first;
if (!param.second.empty()) {
os << "=" << param.second;
}
os << " ";
}
os << "), StimBuff API: " << stimBuffApi
<< ", StimBuff API Params: (";
for (const auto& param : stimBuffApiParams)
{
os << param.first;
if (!param.second.empty()) {
os << "=" << param.second;
}
os << " ";
}
os << "), Provider: " << provider << ", Provider Params: (";
for (const auto& param : providerParams)
{
os << param.first;
if (!param.second.empty()) {
os << "=" << param.second;
}
os << " ";
}
os << "), Device Selector: " << deviceSelector << std::endl;
return os.str();
}
/**
* @brief Parse a required integer parameter from a parameter list
* @param params The parameter vector to search in
* @param paramName The name of the parameter to parse
* @return The parsed integer value
* @throws std::runtime_error if parameter is not found or cannot be parsed
*/
static int parseRequiredParamAsInt(
const std::vector<std::pair<std::string,std::string>>& params,
const std::string& paramName
)
{
auto it = std::find_if(
params.begin(),
params.end(),
[&paramName](const auto& param) {
return param.first == paramName;
}
);
if (it == params.end())
{
throw std::runtime_error(
"No " + paramName + " specified in params");
}
try {
return std::stoi(it->second);
} catch (const std::exception& e) {
throw std::runtime_error(
"Failed to parse '" + paramName + "' param value '"
+ it->second + "' as integer: " + e.what());
}
}
/**
* @brief Parse an optional integer parameter from a parameter list
* @param params The parameter vector to search in
* @param paramName The name of the parameter to parse
* @param defaultValue The default value to return if no parameter is found
* @return The parsed integer value, or defaultValue if none found
* @note The lattermost supplied matching param wins if multiple are present
*/
static int parseOptionalParamAsInt(
const std::vector<std::pair<std::string,std::string>>& params,
const std::string& paramName,
int defaultValue
)
{
const std::string paramNames[] = {paramName};
return parseOptionalParamAsIntWithSynonyms(
params, paramNames, defaultValue);
}
/**
* @brief Parse an optional integer parameter from a parameter list using synonyms
* @param params The parameter vector to search in
* @param synonymNames The collection of synonymous parameter names to try
* @param defaultValue The default value to return if no parameter is found
* @return The parsed integer value, or defaultValue if none found
* @note The lattermost supplied matching param wins if multiple are present
*/
template <typename SynonymCollectionT>
static int parseOptionalParamAsIntWithSynonyms(
const std::vector<std::pair<std::string,std::string>>& params,
const SynonymCollectionT& synonymNames,
int defaultValue
)
{
// Loop through params in reverse order; lattermost supplied param wins.
for (auto paramIt = params.rbegin(); paramIt != params.rend(); ++paramIt)
{
const auto& [paramName, paramValue] = *paramIt;
auto synonymIt = std::find(
std::begin(synonymNames), std::end(synonymNames), paramName);
if (synonymIt == std::end(synonymNames))
{ continue; }
try {
return std::stoi(paramValue);
} catch (const std::exception& e) {
throw std::runtime_error(
"Failed to parse '" + paramName + "' param value '"
+ paramValue + "' as integer: " + e.what());
}
}
return defaultValue;
}
};
class InteroceptorDevAttachmentSpec : public DeviceAttachmentSpec
{
};
class ExtrospectorDevAttachmentSpec : public DeviceAttachmentSpec
{
};
} // namespace device
} // namespace smo
#endif // SENSORDEVICESPEC_H