diff options
author | Jack Lloyd <[email protected]> | 2020-11-28 07:23:51 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2020-11-28 08:04:03 -0500 |
commit | 7ed45bc0da169349ae42450e07a4f2c07be5af14 (patch) | |
tree | 1dfddc26893fa3f2272e9b14eabf48da576388c8 /src/lib/utils/scan_name.cpp | |
parent | b00cd7cea9233b782697f645a5aa54fd59ecacd9 (diff) |
Make scan_name.h, cpuid.h and http_util.h internal
Diffstat (limited to 'src/lib/utils/scan_name.cpp')
-rw-r--r-- | src/lib/utils/scan_name.cpp | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/lib/utils/scan_name.cpp b/src/lib/utils/scan_name.cpp new file mode 100644 index 000000000..56c06dcc5 --- /dev/null +++ b/src/lib/utils/scan_name.cpp @@ -0,0 +1,154 @@ +/* +* SCAN Name Abstraction +* (C) 2008-2009,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/internal/scan_name.h> +#include <botan/internal/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]); + } + +size_t SCAN_Name::arg_as_integer(size_t i) const + { + return to_u32bit(arg(i)); + } + +} |