std::string Variables::evaluate(const std::string &expr) const { std::size_t opPos; std::string result = expr; opPos = expr.find_first_of("+-"); if (opPos != std::string::npos) { long op1, op2, value; try { op1 = std::stol(expr.substr(0, opPos)); } catch (...) { throw TemplateException("Non-numeric operand 1 found in expression '" + expr + "'", false); } try { op2 = std::stol(expr.substr(opPos+1)); } catch (...) { throw TemplateException("Non-numeric operand 2 found in expression '" + expr + "'", false); } if (expr[opPos] == '-') value = op1 - op2; else value = op1 + op2; if (value < 0) { throw TemplateException("Result of expression '" + expr + "' is negative, only >0 results allowed", false); } result = std::to_string(value); } return result; }
std::string Variable::getValue(size_t idx) const { // // If no value assigned yet, throw an exception if (m_values.empty()) { std::string msg = "Attempt to get value of uninitialized input '" + m_name + "'"; throw TemplateException(msg, false); } // // If there is only one value, then it's a single value input, so just return the first index regardless if (m_values.size() == 1) { idx = 0; } // // Otherwise, make sure the requested index is in range else if (idx >= m_values.size()) { std::string msg = "Attempt to get value out of range (" + std::to_string(idx) + "), size = " + std::to_string(m_values.size()) + " for '" + m_name +"'"; throw TemplateException(msg, false); } return m_values[idx]; }
std::shared_ptr<Variable> variableFactory(const std::string &type, const std::string &name) { std::shared_ptr<Variable> pInput; if (type == "string") { pInput = std::make_shared<Variable>(name); } else if (type == "iprange") { pInput = std::make_shared<IPAddressRangeVariable>(name); } else if (type == "ipaddress") { pInput = std::make_shared<IPAddressVariable>(name); } else if (type == "hostname") { pInput = std::make_shared<HostNameVariable>(name); } else { throw TemplateException("Invalid input type '" + type + "'"); } return pInput; }
std::shared_ptr<Variable> Variables::getVariable(const std::string &name, bool throwIfNotFound) const { std::shared_ptr<Variable> pRetVar; std::string varName = name; // // Accept both a regular string or a {{name}} string for the input name std::size_t bracesStartPos = name.find("{{"); if (bracesStartPos != std::string::npos) { std::size_t bracesEndPos = findClosingDelimiter(name, bracesStartPos,"{{", "}}"); varName = name.substr(bracesStartPos + 2, bracesEndPos - bracesStartPos - 2); } for (auto &pVar: m_variables) { if (pVar->getName() == varName) { pRetVar = pVar; break; } } if (!pRetVar && throwIfNotFound) { throw TemplateException("Unable to find variable, name = '" + name + "'."); } return pRetVar; }
TokenFor::TokenFor(wstring expr) { std::vector<wstring> elements ; boost::split(elements, expr, boost::is_space()) ; if (elements.size() != 4u) { throw TemplateException("Invalid syntax in for statement") ; } m_val = elements[1] ; m_key = elements[3] ; }
void Variables::add(const std::shared_ptr<Variable> pVariable) { for (auto &pVar: m_variables) { if (pVar->getName() == pVariable->getName()) { throw TemplateException("Variable '" + pVariable->getName() + "' is a duplicate.", true); } } m_variables.emplace_back(pVariable); }
void HostNameVariable::addValue(const std::string &value) { std::string hostname = trim(value); bool isValid = true; if (hostname.empty()) { throw TemplateException("Hostname is empty", false); } m_values.emplace_back(hostname); }
std::size_t Variables::findClosingDelimiter(const std::string &input, std::size_t startPos, const std::string &openDelim, const std::string &closeDelim) const { std::size_t curPos = startPos + openDelim.length(); std::size_t openPos, closePos; unsigned depth = 1; do { closePos = input.find(closeDelim, curPos); openPos = input.find(openDelim, curPos); if (closePos == std::string::npos) { throw TemplateException("Missing closing delimiter '" + closeDelim + "' string = '" + input + "'", false); } if (openPos != std::string::npos && closePos > openPos) { ++depth; curPos = openPos + openDelim.length(); } else { if (--depth > 0) { if (openPos != std::string::npos) { ++depth; curPos = openPos + openDelim.length(); } else { curPos = closePos + closeDelim.length(); } } } } while (depth > 0); return closePos; }
void IPAddressVariable::addValue(const std::string &value) { std::string ipAddr = trim(value); bool isValid = true; // // Figure out what this def entails. Look at the number of parts. If one part, just // save it. std::vector<std::string> addressParts = splitString(ipAddr, "."); if (addressParts.size() == 4) { for (unsigned i = 0; i < 4 && isValid; ++i) { try { int num = std::stoi(addressParts[i]); if (num <= 0 || num > 255) { isValid = false; } } catch (...) { isValid = false; } } } else { isValid = false; } if (!isValid) { throw TemplateException("Invalid IP address '" + ipAddr + "' specified", false); } m_values.emplace_back(ipAddr); }
////////////////////////////////////////////////////////////////////////// // Data classes ////////////////////////////////////////////////////////////////////////// wstring Data::getvalue() { throw TemplateException("Data item is not a value") ; }
token_vector & Token::get_children() { throw TemplateException("This token type cannot have children") ; }
void Token::set_children( token_vector &children ) { throw TemplateException("This token type cannot have children") ; }
data_map& Data::getmap() { throw TemplateException("Data item is not a dictionary") ; }
data_list& Data::getlist() { throw TemplateException("Data item is not a list") ; }
void TokenEnd::gettext( std::wostream &, data_map &) { throw TemplateException("End-of-control statements have no associated text") ; }
std::string Variables::doValueSubstitution(const std::string &value) const { // // A value has the form {{name}}[{{index}}] where name and index can be simple strings and the index is optional // Or {{name}}.size which will return the size of the variable name (number of entries) std::string varName, result = value; std::size_t index; std::size_t bracesStartPos = result.find("{{"); bool done = bracesStartPos == std::string::npos; while (!done) { index = m_curIndex; std::size_t bracesEndPos = findClosingDelimiter(result, bracesStartPos,"{{", "}}"); varName = result.substr(bracesStartPos + 2, bracesEndPos - bracesStartPos - 2); // // If there is an index defined, evaluate it and update the index to be used for the final value std::size_t bracketStartPos = result.find('['); std::size_t sizePos = result.find(".size"); if (bracketStartPos != std::string::npos && sizePos != std::string::npos) { throw TemplateException("Both [] and .size may not appear in a variable"); } if (bracketStartPos != std::string::npos) { std::size_t bracketEndPos = findClosingDelimiter(result, bracketStartPos, "[", "]"); // result.find(']'); std::string indexStr = result.substr(bracketStartPos+1, bracketEndPos - bracketStartPos - 1); varName = result.substr(bracesStartPos + 2, bracketStartPos - bracesStartPos - 2); try { index = std::stoul(evaluate(doValueSubstitution(indexStr))); } catch (...) { throw TemplateException("Non-numeric count found for index value", false); } } if (sizePos != std::string::npos) { result = std::to_string(getVariable(varName, true)->getNumValues()); } else { std::string substitueValue = doValueSubstitution(getVariable(varName, true)->getValue(index)); std::string newResult = result.substr(0, bracesStartPos); newResult += substitueValue; newResult += result.substr(bracesEndPos + 2); result = newResult; } bracesStartPos = result.find("{{"); done = bracesStartPos == std::string::npos; } // // This should NOT have a [] in it return evaluate(result); }