#ifndef SENSORDEVICESPEC_H #define SENSORDEVICESPEC_H #include #include #include #include #include #include namespace smo { namespace device { 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 && qualeIfaceApi == other.qualeIfaceApi && stimBuffApi == other.stimBuffApi && provider == other.provider && deviceSelector == other.deviceSelector; } public: std::string deviceIdentifier; char sensorType; std::string qualeIfaceApi; std::vector> qualeIfaceApiParams; std::string stimBuffApi; std::vector> stimBuffApiParams; std::string provider; std::vector> providerParams; std::string deviceSelector; std::string stringify() const { std::ostringstream os; os << "Device Identifier: " << deviceIdentifier << ", Sensor Type: " << sensorType << ", 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>& params, const std::string& paramName ) { auto it = std::find_if( params.begin(), params.end(), [¶mName](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 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 Synonyms are tried in reverse order; lattermost synonym wins if multiple are present */ static int parseOptionalParamAsIntWithSynonyms( const std::vector>& params, const std::vector& synonymNames, int defaultValue ) { // Loop through synonyms in reverse order; lattermost synonym wins. for (auto synIt = synonymNames.rbegin(); synIt != synonymNames.rend(); ++synIt) { const auto& paramName = *synIt; try { return parseRequiredParamAsInt(params, paramName); } catch (const std::exception&) { // Parameter not found or parse error, continue to next synonym continue; } } return defaultValue; } }; class InteroceptorDevAttachmentSpec : public DeviceAttachmentSpec { }; class ExtrospectorDevAttachmentSpec : public DeviceAttachmentSpec { }; } // namespace device } // namespace smo #endif // SENSORDEVICESPEC_H