Botan 1.10.17
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
14namespace Botan {
15
16namespace {
17
18std::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
57std::pair<size_t, std::string>
58deref_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
66SCAN_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
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
153std::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
160std::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
167size_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 deref_alias(const std::string &alias) const
Definition libstate.cpp:162
std::string arg(size_t i) const
SCAN_Name(std::string algo_spec)
Definition scan_name.cpp:66
size_t arg_count() const
Definition scan_name.h:47
std::string algo_name() const
Definition scan_name.h:37
std::string algo_name_and_args() const
size_t arg_as_integer(size_t i, size_t def_value) const
u32bit to_u32bit(const std::string &number)
Definition parsing.cpp:18
Library_State & global_state()
Decoding_Error(const std::string &name)
Definition exceptn.h:140