Botan  1.10.9
scan_name.cpp
Go to the documentation of this file.
1 /*
2 * SCAN Name Abstraction
3 * (C) 2008-2009 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/scan_name.h>
9 #include <botan/parsing.h>
10 #include <botan/libstate.h>
11 #include <botan/exceptn.h>
12 #include <stdexcept>
13 
14 namespace Botan {
15 
16 namespace {
17 
18 std::string make_arg(
19  const std::vector<std::pair<size_t, std::string> >& name, size_t start)
20  {
21  std::string output = name[start].second;
22  size_t level = name[start].first;
23 
24  size_t paren_depth = 0;
25 
26  for(size_t i = start + 1; i != name.size(); ++i)
27  {
28  if(name[i].first <= name[start].first)
29  break;
30 
31  if(name[i].first > level)
32  {
33  output += '(' + name[i].second;
34  ++paren_depth;
35  }
36  else if(name[i].first < level)
37  {
38  output += ")," + name[i].second;
39  --paren_depth;
40  }
41  else
42  {
43  if(output[output.size() - 1] != '(')
44  output += ",";
45  output += name[i].second;
46  }
47 
48  level = name[i].first;
49  }
50 
51  for(size_t i = 0; i != paren_depth; ++i)
52  output += ')';
53 
54  return output;
55  }
56 
57 std::pair<size_t, std::string>
58 deref_aliases(const std::pair<size_t, std::string>& in)
59  {
60  return std::make_pair(in.first,
61  global_state().deref_alias(in.second));
62  }
63 
64 }
65 
66 SCAN_Name::SCAN_Name(std::string algo_spec)
67  {
68  orig_algo_spec = algo_spec;
69 
70  std::vector<std::pair<size_t, std::string> > name;
71  size_t level = 0;
72  std::pair<size_t, std::string> accum = std::make_pair(level, "");
73 
74  std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
75 
76  algo_spec = global_state().deref_alias(algo_spec);
77 
78  for(size_t i = 0; i != algo_spec.size(); ++i)
79  {
80  char c = algo_spec[i];
81 
82  if(c == '/' || c == ',' || c == '(' || c == ')')
83  {
84  if(c == '(')
85  ++level;
86  else if(c == ')')
87  {
88  if(level == 0)
89  throw Decoding_Error(decoding_error + "Mismatched parens");
90  --level;
91  }
92 
93  if(c == '/' && level > 0)
94  accum.second.push_back(c);
95  else
96  {
97  if(accum.second != "")
98  name.push_back(deref_aliases(accum));
99  accum = std::make_pair(level, "");
100  }
101  }
102  else
103  accum.second.push_back(c);
104  }
105 
106  if(accum.second != "")
107  name.push_back(deref_aliases(accum));
108 
109  if(level != 0)
110  throw Decoding_Error(decoding_error + "Missing close paren");
111 
112  if(name.size() == 0)
113  throw Decoding_Error(decoding_error + "Empty name");
114 
115  alg_name = name[0].second;
116 
117  bool in_modes = false;
118 
119  for(size_t i = 1; i != name.size(); ++i)
120  {
121  if(name[i].first == 0)
122  {
123  mode_info.push_back(make_arg(name, i));
124  in_modes = true;
125  }
126  else if(name[i].first == 1 && !in_modes)
127  args.push_back(make_arg(name, i));
128  }
129  }
130 
131 std::string SCAN_Name::algo_name_and_args() const
132  {
133  std::string out;
134 
135  out = algo_name();
136 
137  if(arg_count())
138  {
139  out += '(';
140  for(size_t i = 0; i != arg_count(); ++i)
141  {
142  out += arg(i);
143  if(i != arg_count() - 1)
144  out += ',';
145  }
146  out += ')';
147 
148  }
149 
150  return out;
151  }
152 
153 std::string SCAN_Name::arg(size_t i) const
154  {
155  if(i >= arg_count())
156  throw std::range_error("SCAN_Name::argument - i out of range");
157  return args[i];
158  }
159 
160 std::string SCAN_Name::arg(size_t i, const std::string& def_value) const
161  {
162  if(i >= arg_count())
163  return def_value;
164  return args[i];
165  }
166 
167 size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const
168  {
169  if(i >= arg_count())
170  return def_value;
171  return to_u32bit(args[i]);
172  }
173 
174 }
std::string arg(size_t i) const
Definition: scan_name.cpp:153
size_t arg_count() const
Definition: scan_name.h:47
std::string algo_name() const
Definition: scan_name.h:37
Library_State & global_state()
std::string deref_alias(const std::string &alias) const
Definition: libstate.cpp:162
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:167
SCAN_Name(std::string algo_spec)
Definition: scan_name.cpp:66
u32bit to_u32bit(const std::string &number)
Definition: parsing.cpp:18
std::string algo_name_and_args() const
Definition: scan_name.cpp:131