122 lines
2.6 KiB
C++
122 lines
2.6 KiB
C++
#include <selectorParse.h>
|
|
#include <stdexcept>
|
|
#include <cctype>
|
|
|
|
namespace lcamera_dev {
|
|
|
|
namespace {
|
|
|
|
SelectorCriterionKind parseCriterionKind(const std::string& prefixToken)
|
|
{
|
|
if (prefixToken == "lcamera-id") {
|
|
return SelectorCriterionKind::LibcameraId;
|
|
}
|
|
if (prefixToken == "index") {
|
|
return SelectorCriterionKind::Index;
|
|
}
|
|
if (prefixToken == "model-substr") {
|
|
return SelectorCriterionKind::ModelSubstr;
|
|
}
|
|
if (prefixToken == "model") {
|
|
return SelectorCriterionKind::Model;
|
|
}
|
|
if (prefixToken == "location") {
|
|
return SelectorCriterionKind::Location;
|
|
}
|
|
|
|
throw std::runtime_error(
|
|
"Unknown deviceSelector prefix: " + prefixToken);
|
|
}
|
|
|
|
SelectorCriterion parseCriterionClause(const std::string& clause)
|
|
{
|
|
const std::string trimmedClause = trimWhitespace(clause);
|
|
if (trimmedClause.empty()) {
|
|
throw std::runtime_error("Empty deviceSelector clause");
|
|
}
|
|
|
|
const size_t colonPos = trimmedClause.find(':');
|
|
if (colonPos == std::string::npos)
|
|
{
|
|
return SelectorCriterion{
|
|
SelectorCriterionKind::LibcameraId,
|
|
trimmedClause
|
|
};
|
|
}
|
|
|
|
const std::string prefixToken = trimWhitespace(
|
|
trimmedClause.substr(0, colonPos));
|
|
const std::string value = trimWhitespace(
|
|
trimmedClause.substr(colonPos + 1));
|
|
|
|
if (value.empty())
|
|
{
|
|
throw std::runtime_error(
|
|
"deviceSelector clause has empty value for prefix "
|
|
+ prefixToken);
|
|
}
|
|
|
|
return SelectorCriterion{
|
|
parseCriterionKind(prefixToken),
|
|
value
|
|
};
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::string trimWhitespace(const std::string& text)
|
|
{
|
|
size_t start = 0;
|
|
while (start < text.size() && std::isspace(static_cast<unsigned char>(text[start]))) {
|
|
++start;
|
|
}
|
|
|
|
size_t end = text.size();
|
|
while (end > start
|
|
&& std::isspace(static_cast<unsigned char>(text[end - 1])))
|
|
{
|
|
--end;
|
|
}
|
|
|
|
return text.substr(start, end - start);
|
|
}
|
|
|
|
std::vector<SelectorCriterion> parseDeviceSelector(
|
|
const std::string& deviceSelector)
|
|
{
|
|
const std::string trimmedSelector = trimWhitespace(deviceSelector);
|
|
if (trimmedSelector.empty()) {
|
|
throw std::runtime_error("deviceSelector is empty");
|
|
}
|
|
|
|
std::vector<SelectorCriterion> criteria;
|
|
std::string currentClause;
|
|
currentClause.reserve(trimmedSelector.size());
|
|
|
|
for (size_t i = 0; i < trimmedSelector.size(); ++i)
|
|
{
|
|
const char ch = trimmedSelector[i];
|
|
if (ch == '\\' && i + 1 < trimmedSelector.size()
|
|
&& trimmedSelector[i + 1] == ';')
|
|
{
|
|
currentClause.push_back(';');
|
|
++i;
|
|
continue;
|
|
}
|
|
|
|
if (ch == ';')
|
|
{
|
|
criteria.push_back(parseCriterionClause(currentClause));
|
|
currentClause.clear();
|
|
continue;
|
|
}
|
|
|
|
currentClause.push_back(ch);
|
|
}
|
|
|
|
criteria.push_back(parseCriterionClause(currentClause));
|
|
return criteria;
|
|
}
|
|
|
|
} // namespace lcamera_dev
|