Coverage Report

Created: 2020-03-26 13:53

/src/botan/src/lib/base/scan_name.cpp
Line
Count
Source (jump to first uncovered line)
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/scan_name.h>
9
#include <botan/parsing.h>
10
#include <botan/exceptn.h>
11
12
namespace Botan {
13
14
namespace {
15
16
std::string make_arg(const std::vector<std::pair<size_t, std::string>>& name, size_t start)
17
74.9k
   {
18
74.9k
   std::string output = name[start].second;
19
74.9k
   size_t level = name[start].first;
20
74.9k
21
74.9k
   size_t paren_depth = 0;
22
74.9k
23
74.9k
   for(size_t i = start + 1; i != name.size(); ++i)
24
1.11k
      {
25
1.11k
      if(name[i].first <= name[start].first)
26
1.11k
         break;
27
0
28
0
      if(name[i].first > level)
29
0
         {
30
0
         output += "(" + name[i].second;
31
0
         ++paren_depth;
32
0
         }
33
0
      else if(name[i].first < level)
34
0
         {
35
0
         output += ")," + name[i].second;
36
0
         --paren_depth;
37
0
         }
38
0
      else
39
0
         {
40
0
         if(output[output.size() - 1] != '(')
41
0
            output += ",";
42
0
         output += name[i].second;
43
0
         }
44
0
45
0
      level = name[i].first;
46
0
      }
47
74.9k
48
74.9k
   for(size_t i = 0; i != paren_depth; ++i)
49
0
      output += ")";
50
74.9k
51
74.9k
   return output;
52
74.9k
   }
53
54
}
55
56
SCAN_Name::SCAN_Name(const char* algo_spec) : SCAN_Name(std::string(algo_spec))
57
0
   {
58
0
   }
59
60
SCAN_Name::SCAN_Name(std::string algo_spec) : m_orig_algo_spec(algo_spec), m_alg_name(), m_args(), m_mode_info()
61
90.3k
   {
62
90.3k
   if(algo_spec.size() == 0)
63
0
      throw Invalid_Argument("Expected algorithm name, got empty string");
64
90.3k
65
90.3k
   std::vector<std::pair<size_t, std::string>> name;
66
90.3k
   size_t level = 0;
67
90.3k
   std::pair<size_t, std::string> accum = std::make_pair(level, "");
68
90.3k
69
90.3k
   const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
70
90.3k
71
1.37M
   for(size_t i = 0; i != algo_spec.size(); ++i)
72
1.28M
      {
73
1.28M
      char c = algo_spec[i];
74
1.28M
75
1.28M
      if(c == '/' || c == ',' || c == '(' || c == ')')
76
148k
         {
77
148k
         if(c == '(')
78
73.8k
            ++level;
79
74.9k
         else if(c == ')')
80
73.8k
            {
81
73.8k
            if(level == 0)
82
0
               throw Decoding_Error(decoding_error + "Mismatched parens");
83
73.8k
            --level;
84
73.8k
            }
85
148k
86
148k
         if(c == '/' && level > 0)
87
0
            accum.second.push_back(c);
88
148k
         else
89
148k
            {
90
148k
            if(accum.second != "")
91
148k
               name.push_back(accum);
92
148k
            accum = std::make_pair(level, "");
93
148k
            }
94
148k
         }
95
1.13M
      else
96
1.13M
         accum.second.push_back(c);
97
1.28M
      }
98
90.3k
99
90.3k
   if(accum.second != "")
100
16.5k
      name.push_back(accum);
101
90.3k
102
90.3k
   if(level != 0)
103
0
      throw Decoding_Error(decoding_error + "Missing close paren");
104
90.3k
105
90.3k
   if(name.size() == 0)
106
0
      throw Decoding_Error(decoding_error + "Empty name");
107
90.3k
108
90.3k
   m_alg_name = name[0].second;
109
90.3k
110
90.3k
   bool in_modes = false;
111
90.3k
112
165k
   for(size_t i = 1; i != name.size(); ++i)
113
74.9k
      {
114
74.9k
      if(name[i].first == 0)
115
0
         {
116
0
         m_mode_info.push_back(make_arg(name, i));
117
0
         in_modes = true;
118
0
         }
119
74.9k
      else if(name[i].first == 1 && !in_modes)
120
74.9k
         m_args.push_back(make_arg(name, i));
121
74.9k
      }
122
90.3k
   }
123
124
std::string SCAN_Name::arg(size_t i) const
125
63.6k
   {
126
63.6k
   if(i >= arg_count())
127
0
      throw Invalid_Argument("SCAN_Name::arg " + std::to_string(i) +
128
0
                             " out of range for '" + to_string() + "'");
129
63.6k
   return m_args[i];
130
63.6k
   }
131
132
std::string SCAN_Name::arg(size_t i, const std::string& def_value) const
133
85
   {
134
85
   if(i >= arg_count())
135
0
      return def_value;
136
85
   return m_args[i];
137
85
   }
138
139
size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const
140
2.29k
   {
141
2.29k
   if(i >= arg_count())
142
1.42k
      return def_value;
143
869
   return to_u32bit(m_args[i]);
144
869
   }
145
146
}