Botan 3.0.0-alpha0
Crypto and TLS for C&
scan_name.cpp
Go to the documentation of this file.
1/*
2* SCAN Name Abstraction
3* (C) 2008-2009,2015 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/scan_name.h>
9#include <botan/internal/parsing.h>
10#include <botan/exceptn.h>
11
12namespace Botan {
13
14namespace {
15
16std::string make_arg(const std::vector<std::pair<size_t, std::string>>& name, size_t start)
17 {
18 std::string output = name[start].second;
19 size_t level = name[start].first;
20
21 size_t paren_depth = 0;
22
23 for(size_t i = start + 1; i != name.size(); ++i)
24 {
25 if(name[i].first <= name[start].first)
26 break;
27
28 if(name[i].first > level)
29 {
30 output += "(" + name[i].second;
31 ++paren_depth;
32 }
33 else if(name[i].first < level)
34 {
35 for (size_t j = name[i].first; j < level; j++) {
36 output += ")";
37 --paren_depth;
38 }
39 output += "," + name[i].second;
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}
58
59SCAN_Name::SCAN_Name(const char* algo_spec) : SCAN_Name(std::string(algo_spec))
60 {
61 }
62
63SCAN_Name::SCAN_Name(const std::string& algo_spec) :
64 m_orig_algo_spec(algo_spec),
65 m_alg_name(),
66 m_args(),
67 m_mode_info()
68 {
69 if(algo_spec.empty())
70 throw Invalid_Argument("Expected algorithm name, got empty string");
71
72 std::vector<std::pair<size_t, std::string>> name;
73 size_t level = 0;
74 std::pair<size_t, std::string> accum = std::make_pair(level, "");
75
76 const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
77
78 for(char c : algo_spec)
79 {
80 if(c == '/' || c == ',' || c == '(' || c == ')')
81 {
82 if(c == '(')
83 ++level;
84 else if(c == ')')
85 {
86 if(level == 0)
87 throw Decoding_Error(decoding_error + "Mismatched parens");
88 --level;
89 }
90
91 if(c == '/' && level > 0)
92 accum.second.push_back(c);
93 else
94 {
95 if(!accum.second.empty())
96 name.push_back(accum);
97 accum = std::make_pair(level, "");
98 }
99 }
100 else
101 accum.second.push_back(c);
102 }
103
104 if(!accum.second.empty())
105 name.push_back(accum);
106
107 if(level != 0)
108 throw Decoding_Error(decoding_error + "Missing close paren");
109
110 if(name.empty())
111 throw Decoding_Error(decoding_error + "Empty name");
112
113 m_alg_name = name[0].second;
114
115 bool in_modes = false;
116
117 for(size_t i = 1; i != name.size(); ++i)
118 {
119 if(name[i].first == 0)
120 {
121 m_mode_info.push_back(make_arg(name, i));
122 in_modes = true;
123 }
124 else if(name[i].first == 1 && !in_modes)
125 m_args.push_back(make_arg(name, i));
126 }
127 }
128
129std::string SCAN_Name::arg(size_t i) const
130 {
131 if(i >= arg_count())
132 throw Invalid_Argument("SCAN_Name::arg " + std::to_string(i) +
133 " out of range for '" + to_string() + "'");
134 return m_args[i];
135 }
136
137std::string SCAN_Name::arg(size_t i, const std::string& def_value) const
138 {
139 if(i >= arg_count())
140 return def_value;
141 return m_args[i];
142 }
143
144size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const
145 {
146 if(i >= arg_count())
147 return def_value;
148 return to_u32bit(m_args[i]);
149 }
150
151size_t SCAN_Name::arg_as_integer(size_t i) const
152 {
153 return to_u32bit(arg(i));
154 }
155
156}
std::string arg(size_t i) const
Definition: scan_name.cpp:129
const std::string & to_string() const
Definition: scan_name.h:39
size_t arg_count() const
Definition: scan_name.h:49
SCAN_Name(const char *algo_spec)
Definition: scan_name.cpp:59
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:144
std::string name
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:209
Definition: alg_id.cpp:13
uint32_t to_u32bit(const std::string &str)
Definition: parsing.cpp:29
Definition: bigint.h:1077