aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-10-07 17:37:55 +0000
committerlloyd <[email protected]>2009-10-07 17:37:55 +0000
commit2d2cb73d20d5f08e5091147a69aa7b2b633880de (patch)
treed79417a3afc571354aa7c06da56fc222ba4ad0b4
parent14781861531974130e48c996f2ac18e037c9bff6 (diff)
New parsing system for SCAN names
-rw-r--r--src/libstate/scan_name.cpp118
-rw-r--r--src/libstate/scan_name.h13
2 files changed, 92 insertions, 39 deletions
diff --git a/src/libstate/scan_name.cpp b/src/libstate/scan_name.cpp
index bdafde225..224d2e509 100644
--- a/src/libstate/scan_name.cpp
+++ b/src/libstate/scan_name.cpp
@@ -14,28 +14,50 @@ namespace Botan {
namespace {
-std::vector<std::string>
-parse_and_deref_aliases(const std::string& algo_spec)
+std::string make_arg(
+ const std::vector<std::pair<u32bit, std::string> >& name, u32bit start)
{
- std::vector<std::string> parts = parse_algorithm_name(algo_spec);
- std::vector<std::string> out;
+ std::string output = name[start].second;
+ u32bit level = name[start].first;
- for(size_t i = 0; i != parts.size(); ++i)
+ u32bit paren_depth = 0;
+
+ for(u32bit i = start + 1; i != name.size(); ++i)
{
- std::string part_i = global_state().deref_alias(parts[i]);
+ if(name[i].first <= name[start].first)
+ break;
- if(i == 0 && part_i.find_first_of(",()") != std::string::npos)
+ if(name[i].first > level)
{
- std::vector<std::string> parts_i = parse_and_deref_aliases(part_i);
-
- for(size_t j = 0; j != parts_i.size(); ++j)
- out.push_back(parts_i[j]);
+ output += '(' + name[i].second;
+ ++paren_depth;
+ }
+ else if(name[i].first < level)
+ {
+ output += ")," + name[i].second;
+ --paren_depth;
}
else
- out.push_back(part_i);
+ {
+ if(output[output.size() - 1] != '(')
+ output += ",";
+ output += name[i].second;
+ }
+
+ level = name[i].first;
}
- return out;
+ for(u32bit i = 0; i != paren_depth; ++i)
+ output += ')';
+
+ return output;
+ }
+
+std::pair<u32bit, std::string>
+deref_aliases(const std::pair<u32bit, std::string>& in)
+ {
+ return std::make_pair(in.first,
+ global_state().deref_alias(in.second));
}
}
@@ -44,27 +66,57 @@ SCAN_Name::SCAN_Name(const std::string& algo_spec)
{
orig_algo_spec = algo_spec;
- try
- {
- name = parse_and_deref_aliases(algo_spec);
- if(name.size() == 0)
- throw Decoding_Error("Bad SCAN name " + algo_spec);
- }
- catch(Invalid_Algorithm_Name)
+ std::vector<std::pair<u32bit, std::string> > name;
+ u32bit level = 0;
+ std::pair<u32bit, std::string> accum = std::make_pair(level, "");
+
+ for(u32bit i = 0; i != algo_spec.size(); ++i)
{
- name.clear();
+ char c = algo_spec[i];
+
+ if(c == '/' || c == ',' || c == '(' || c == ')')
+ {
+ if(c == '(')
+ ++level;
+ else if(c == ')')
+ {
+ if(level == 0)
+ throw Decoding_Error("Bad SCAN name " + algo_spec);
+ --level;
+ }
+
+ if(c == '/' && level > 0)
+ accum.second.push_back(c);
+ else
+ {
+ if(accum.second != "")
+ name.push_back(deref_aliases(accum));
+ accum = std::make_pair(level, "");
+ }
+ }
+ else
+ accum.second.push_back(c);
}
- if(name.size() <= 1 && algo_spec.find('/') != std::string::npos)
- {
- std::vector<std::string> algo_parts = split_on(algo_spec, '/');
+ if(accum.second != "")
+ name.push_back(deref_aliases(accum));
+
+ if(level != 0 || name.size() == 0)
+ throw Decoding_Error("Bad SCAN name " + algo_spec);
+
+ alg_name = name[0].second;
- name = parse_and_deref_aliases(algo_parts[0]);
- if(name.size() == 0)
- throw Decoding_Error("Bad SCAN name " + algo_spec);
+ bool in_modes = false;
- for(size_t i = 1; i != algo_parts.size(); ++i)
- mode_str.push_back(algo_parts[i]);
+ for(u32bit i = 1; i != name.size(); ++i)
+ {
+ if(name[i].first == 0)
+ {
+ mode_info.push_back(make_arg(name, i));
+ in_modes = true;
+ }
+ else if(name[i].first == 1 && !in_modes)
+ args.push_back(make_arg(name, i));
}
}
@@ -72,7 +124,7 @@ std::string SCAN_Name::algo_name_and_args() const
{
std::string out;
- out = name[0];
+ out = algo_name();
if(arg_count())
{
@@ -94,21 +146,21 @@ std::string SCAN_Name::arg(u32bit i) const
{
if(i >= arg_count())
throw std::range_error("SCAN_Name::argument");
- return name[i+1];
+ return args[i];
}
std::string SCAN_Name::arg(u32bit i, const std::string& def_value) const
{
if(i >= arg_count())
return def_value;
- return name[i+1];
+ return args[i];
}
u32bit SCAN_Name::arg_as_u32bit(u32bit i, u32bit def_value) const
{
if(i >= arg_count())
return def_value;
- return to_u32bit(name[i+1]);
+ return to_u32bit(args[i]);
}
}
diff --git a/src/libstate/scan_name.h b/src/libstate/scan_name.h
index 6dbd67c4f..ced5f3e15 100644
--- a/src/libstate/scan_name.h
+++ b/src/libstate/scan_name.h
@@ -35,7 +35,7 @@ class SCAN_Name
/**
@return the algorithm name
*/
- std::string algo_name() const { return name[0]; }
+ std::string algo_name() const { return alg_name; }
/**
@return the algorithm name plus any arguments
@@ -45,7 +45,7 @@ class SCAN_Name
/**
@return the number of arguments
*/
- u32bit arg_count() const { return name.size() - 1; }
+ u32bit arg_count() const { return args.size(); }
/**
@return if the number of arguments is between lower and upper
@@ -77,18 +77,19 @@ class SCAN_Name
@return the cipher mode (if any)
*/
std::string cipher_mode() const
- { return (mode_str.size() >= 1) ? mode_str[0] : ""; }
+ { return (mode_info.size() >= 1) ? mode_info[0] : ""; }
/**
@return the cipher mode padding (if any)
*/
std::string cipher_mode_pad() const
- { return (mode_str.size() >= 2) ? mode_str[1] : ""; }
+ { return (mode_info.size() >= 2) ? mode_info[1] : ""; }
private:
std::string orig_algo_spec;
- std::vector<std::string> name;
- std::vector<std::string> mode_str;
+ std::string alg_name;
+ std::vector<std::string> args;
+ std::vector<std::string> mode_info;
};
}