9#include <boost/algorithm/string.hpp>
10#include <boost/algorithm/string/predicate.hpp>
11#include <boost/filesystem.hpp>
24 size_t count = std::count(theString.begin(), theString.end(), delimiter);
31 size_t signatureLen = 6;
32 if(theString.length() < signatureLen)
return false;
33 if(theString.substr(0, 6) !=
"sdm://")
return false;
40 boost::trim(theString);
41 if(theString.length() < 3)
return false;
42 if(theString.substr(0, 1) !=
"(")
return false;
43 if(theString.substr(theString.length() - 1, 1) !=
")")
return false;
54 boost::trim(cddString);
57 if(cddString.length() < 3) {
60 if(cddString.substr(0, 1) !=
"(") {
61 throw ChimeraTK::logic_error(
"Invalid ChimeraTK device descriptor (missing opening parenthesis): " + cddString);
63 if(cddString.substr(cddString.length() - 1, 1) !=
")") {
64 throw ChimeraTK::logic_error(
"Invalid ChimeraTK device descriptor (missing opening parenthesis): " + cddString);
68 size_t parenthesesLevel = 0;
69 enum class tokenType { backendType, address, parameters };
70 tokenType currentTokenType = tokenType::backendType;
71 bool escapeNext =
false;
73 size_t positionPlusOne = 0;
74 for(
auto& c : cddString) {
77 if(parenthesesLevel == 1) {
80 if(c ==
' ' || c ==
'?' || c ==
'&' || c ==
'(' || c ==
')' || c ==
'\\') {
94 else if(currentTokenType == tokenType::backendType && (c ==
':' || c ==
'?' || c ==
')')) {
97 if(token.length() == 0) {
99 "(backend type must be non-empty): " +
102 if(!boost::all(token, boost::is_alnum())) {
104 "(backend type must be alphanumeric): " +
112 currentTokenType = tokenType::address;
115 currentTokenType = tokenType::parameters;
118 else if(currentTokenType == tokenType::address && (c ==
'?' || c ==
')')) {
123 currentTokenType = tokenType::parameters;
125 else if(currentTokenType == tokenType::parameters && (c ==
'&' || c ==
')')) {
128 if(token.length() > 0) {
129 auto equalSign = token.find_first_of(
'=');
130 if(equalSign == std::string::npos) {
132 "specified as key=value pairs): " +
135 auto key = token.substr(0, equalSign);
136 auto value = token.substr(equalSign + 1);
138 if(key.length() == 0) {
143 if(!boost::all(key, boost::is_alnum())) {
146 "alphanumeric characters): " +
152 "' specified multiple times): " + cddString);
162 else if(parenthesesLevel > 1) {
171 if(parenthesesLevel == 0 && positionPlusOne != cddString.length()) {
174 "last closing parenthesis): " +
181 if(parenthesesLevel != 0) {
182 throw ChimeraTK::logic_error(
"Invalid ChimeraTK device descriptor (unmatched parenthesis): " + cddString);
193 size_t signatureLen = 6;
198 std::size_t found = sdmString.find_first_of(
'/', pos);
200 if(found != std::string::npos) {
201 sdmInfo.
host = sdmString.substr(pos, found - pos);
206 if(sdmString.length() < found + 1)
return sdmInfo;
207 subUri = sdmString.substr(found + 1);
221 std::vector<std::string> tokens;
222 boost::split(tokens, subUri, boost::is_any_of(
":;="));
223 size_t numOfTokens = tokens.size();
224 if(numOfTokens < 1)
return sdmInfo;
228 if(counter < numOfTokens) {
230 found = sdmString.find_first_of(
':', pos);
231 if(found != std::string::npos) {
236 if(counter < numOfTokens) {
238 found = sdmString.find_first_of(
';', pos);
239 if(found != std::string::npos) {
244 if(counter < numOfTokens) {
246 found = sdmString.find_first_of(
'=', pos);
247 if(found != std::string::npos) {
248 std::string parameters = tokens[counter];
249 std::vector<std::string> paramterTokens;
250 boost::split(paramterTokens, parameters, boost::is_any_of(
","));
251 for(
auto& paramterToken : paramterTokens) {
264 if(deviceString.substr(0, 5) ==
"/dev/") {
266 if(deviceString.length() > 5) {
267 sdmInfo.
instance = deviceString.substr(5);
270 else if((boost::ends_with(deviceString,
".map")) || (boost::ends_with(deviceString,
".mapp"))) {
291 deviceInfoPointer->getDeviceInfo(aliasName, deviceInfo);
299 if(dmapFileName.empty()) {
306 std::vector<std::string> listOfDeviceAliases;
307 listOfDeviceAliases.reserve(deviceInfoMap->getSize());
309 for(
auto&& deviceInfo : *deviceInfoMap) {
310 listOfDeviceAliases.push_back(deviceInfo.deviceName);
313 return listOfDeviceAliases;
316 std::cout << e.
what() << std::endl;
338 int i, trace_size = 0;
340 trace_size = backtrace(trace, 16);
341 messages = backtrace_symbols(trace, trace_size);
342 printf(
"[bt] Execution path:\n");
343 for(i = 0; i < trace_size; ++i) {
344 std::string msg(messages[i]);
345 size_t a = msg.find_first_of(
'(');
346 size_t b = msg.find_first_of(
'+');
347 std::string functionName = boost::core::demangle(msg.substr(a + 1, b - a - 1).c_str());
348 std::cout <<
"[bt] #" << i <<
" " << functionName << std::endl;
355 const std::string& address,
const std::map<std::string, std::string>& parameters) {
357 std::string str = address;
358 for(
const auto& e : parameters) {
359 str += e.first +
"=" + e.second +
";";
361 return std::hash<std::string>{}(str);
367 std::size_t instanceIdHash,
const std::string& mapFileName,
const std::string& userName) {
369 boost::filesystem::path absPathToMapFile = boost::filesystem::absolute(mapFileName);
371 std::string mapFileHash{
std::to_string(std::hash<std::string>{}(absPathToMapFile.string()))};
372 std::string userHash{
std::to_string(std::hash<std::string>{}(userName))};
374 return "ChimeraTK_SharedDummy_" +
std::to_string(instanceIdHash) +
"_" + mapFileHash +
"_" + userHash;
static BackendFactory & getInstance()
Static function to get an instance of factory.
void setDMapFilePath(std::string dMapFilePath)
This function sets the _DMapFilePath.
static DeviceInfoMapPointer parse(const std::string &file_name)
Performs parsing of specified DMAP file.
Stores information about one device.
Exception thrown when a logic error has occured.
Exception thrown when a runtime error has occured.
const char * what() const noexcept override
Return the message describing what exactly went wrong.
DeviceDescriptor parseDeviceDesciptor(std::string cddString)
Parse a ChimeraTK device descriptor (CDD) and return the information in the DeviceDescriptor struct.
std::vector< std::string > getAliasList()
Returns the list of device aliases from the DMap file set using BackendFactory::setDMapFilePath.
void printStackTrace()
Print a call stack trace (but continue executing the process normally).
DeviceInfoMap::DeviceInfo aliasLookUp(const std::string &aliasName, const std::string &dmapFilePath)
Search for an alias in a given DMap file and return the DeviceInfo entry.
std::size_t shmDummyInstanceIdHash(const std::string &address, const std::map< std::string, std::string > ¶meters)
Generates shm dummy instanceId hash from address and parameter map, Intended for use with parseDevice...
bool isSdm(const std::string &theString)
Check wehter the given string seems to be an SDM.
size_t countOccurence(std::string theString, char delimiter)
Check if the given string only contains alphanumeric characters.
Sdm parseDeviceString(const std::string &deviceString)
Parse an old-style device string (either path to device node or map file name for dummies)
Sdm parseSdm(const std::string &sdmString)
Parse an SDM URI and return the device information in the Sdm struct.
std::string createShmName(std::size_t instanceIdHash, const std::string &mapFileName, const std::string &userName)
Generates shm dummy name from parameter hashes.
bool isDeviceDescriptor(std::string theString)
Check whether the given string seems to be a CDD.
std::string getDMapFilePath()
Returns the dmap file name which the library currently uses for looking up device(alias) names.
void setDMapFilePath(std::string dmapFilePath)
Set the location of the dmap file.
std::string to_string(const std::string &v)
This structure holds the information of an ChimeraTK device descriptor.
std::map< std::string, std::string > parameters
This structure holds the information of an SDM.
std::list< std::string > parameters