summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/base/scan_name.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/base/scan_name.cpp')
-rw-r--r--comm/third_party/botan/src/lib/base/scan_name.cpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/base/scan_name.cpp b/comm/third_party/botan/src/lib/base/scan_name.cpp
new file mode 100644
index 0000000000..f79866ba61
--- /dev/null
+++ b/comm/third_party/botan/src/lib/base/scan_name.cpp
@@ -0,0 +1,149 @@
+/*
+* SCAN Name Abstraction
+* (C) 2008-2009,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/scan_name.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace {
+
+std::string make_arg(const std::vector<std::pair<size_t, std::string>>& name, size_t start)
+ {
+ std::string output = name[start].second;
+ size_t level = name[start].first;
+
+ size_t paren_depth = 0;
+
+ for(size_t i = start + 1; i != name.size(); ++i)
+ {
+ if(name[i].first <= name[start].first)
+ break;
+
+ if(name[i].first > level)
+ {
+ output += "(" + name[i].second;
+ ++paren_depth;
+ }
+ else if(name[i].first < level)
+ {
+ for (size_t j = name[i].first; j < level; j++) {
+ output += ")";
+ --paren_depth;
+ }
+ output += "," + name[i].second;
+ }
+ else
+ {
+ if(output[output.size() - 1] != '(')
+ output += ",";
+ output += name[i].second;
+ }
+
+ level = name[i].first;
+ }
+
+ for(size_t i = 0; i != paren_depth; ++i)
+ output += ")";
+
+ return output;
+ }
+
+}
+
+SCAN_Name::SCAN_Name(const char* algo_spec) : SCAN_Name(std::string(algo_spec))
+ {
+ }
+
+SCAN_Name::SCAN_Name(std::string algo_spec) : m_orig_algo_spec(algo_spec), m_alg_name(), m_args(), m_mode_info()
+ {
+ if(algo_spec.size() == 0)
+ throw Invalid_Argument("Expected algorithm name, got empty string");
+
+ std::vector<std::pair<size_t, std::string>> name;
+ size_t level = 0;
+ std::pair<size_t, std::string> accum = std::make_pair(level, "");
+
+ const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
+
+ for(size_t i = 0; i != algo_spec.size(); ++i)
+ {
+ char c = algo_spec[i];
+
+ if(c == '/' || c == ',' || c == '(' || c == ')')
+ {
+ if(c == '(')
+ ++level;
+ else if(c == ')')
+ {
+ if(level == 0)
+ throw Decoding_Error(decoding_error + "Mismatched parens");
+ --level;
+ }
+
+ if(c == '/' && level > 0)
+ accum.second.push_back(c);
+ else
+ {
+ if(accum.second != "")
+ name.push_back(accum);
+ accum = std::make_pair(level, "");
+ }
+ }
+ else
+ accum.second.push_back(c);
+ }
+
+ if(accum.second != "")
+ name.push_back(accum);
+
+ if(level != 0)
+ throw Decoding_Error(decoding_error + "Missing close paren");
+
+ if(name.size() == 0)
+ throw Decoding_Error(decoding_error + "Empty name");
+
+ m_alg_name = name[0].second;
+
+ bool in_modes = false;
+
+ for(size_t i = 1; i != name.size(); ++i)
+ {
+ if(name[i].first == 0)
+ {
+ m_mode_info.push_back(make_arg(name, i));
+ in_modes = true;
+ }
+ else if(name[i].first == 1 && !in_modes)
+ m_args.push_back(make_arg(name, i));
+ }
+ }
+
+std::string SCAN_Name::arg(size_t i) const
+ {
+ if(i >= arg_count())
+ throw Invalid_Argument("SCAN_Name::arg " + std::to_string(i) +
+ " out of range for '" + to_string() + "'");
+ return m_args[i];
+ }
+
+std::string SCAN_Name::arg(size_t i, const std::string& def_value) const
+ {
+ if(i >= arg_count())
+ return def_value;
+ return m_args[i];
+ }
+
+size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const
+ {
+ if(i >= arg_count())
+ return def_value;
+ return to_u32bit(m_args[i]);
+ }
+
+}