Crypto++
algparam.h
1 #ifndef CRYPTOPP_ALGPARAM_H
2 #define CRYPTOPP_ALGPARAM_H
3 
4 #include "cryptlib.h"
5 #include "smartptr.h"
6 #include "secblock.h"
7 
8 NAMESPACE_BEGIN(CryptoPP)
9 
10 //! used to pass byte array input as part of a NameValuePairs object
11 /*! the deepCopy option is used when the NameValuePairs object can't
12  keep a copy of the data available */
14 {
15 public:
16  ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
17  {
18  Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
19  }
20  ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
21  {
22  Assign(data, size, deepCopy);
23  }
24  template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
25  {
26  CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
27  Assign((const byte *)string.data(), string.size(), deepCopy);
28  }
29 
30  void Assign(const byte *data, size_t size, bool deepCopy)
31  {
32  if (deepCopy)
33  m_block.Assign(data, size);
34  else
35  {
36  m_data = data;
37  m_size = size;
38  }
39  m_deepCopy = deepCopy;
40  }
41 
42  const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
43  const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
44  size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
45 
46 private:
47  bool m_deepCopy;
48  const byte *m_data;
49  size_t m_size;
50  SecByteBlock m_block;
51 };
52 
54 {
55 public:
56  ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
57  : m_data(data), m_size(size) {}
59  : m_data(block.begin()), m_size(block.size()) {}
60 
61  byte *begin() const {return m_data;}
62  byte *end() const {return m_data + m_size;}
63  size_t size() const {return m_size;}
64 
65 private:
66  byte *m_data;
67  size_t m_size;
68 };
69 
70 class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
71 {
72 public:
73  CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
74  : m_pairs1(pairs1), m_pairs2(pairs2) {}
75 
76  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
77 
78 private:
79  const NameValuePairs &m_pairs1, &m_pairs2;
80 };
81 
82 template <class T, class BASE>
84 {
85 public:
86  GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
87  : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
88  {
89  if (strcmp(m_name, "ValueNames") == 0)
90  {
91  m_found = m_getValueNames = true;
92  NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
93  if (searchFirst)
94  searchFirst->GetVoidValue(m_name, valueType, pValue);
95  if (typeid(T) != typeid(BASE))
96  pObject->BASE::GetVoidValue(m_name, valueType, pValue);
97  ((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
98  }
99 
100  if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
101  {
102  NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
103  *reinterpret_cast<const T **>(pValue) = pObject;
104  m_found = true;
105  return;
106  }
107 
108  if (!m_found && searchFirst)
109  m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
110 
111  if (!m_found && typeid(T) != typeid(BASE))
112  m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
113  }
114 
115  operator bool() const {return m_found;}
116 
117  template <class R>
118  GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
119  {
120  if (m_getValueNames)
121  (*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
122  if (!m_found && strcmp(name, m_name) == 0)
123  {
124  NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
125  *reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
126  m_found = true;
127  }
128  return *this;
129  }
130 
131  GetValueHelperClass<T,BASE> &Assignable()
132  {
133 #ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
134  if (m_getValueNames)
135  ((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
136  if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
137  {
138  NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
139  *reinterpret_cast<T *>(m_pValue) = *m_pObject;
140  m_found = true;
141  }
142 #endif
143  return *this;
144  }
145 
146 private:
147  const T *m_pObject;
148  const char *m_name;
149  const std::type_info *m_valueType;
150  void *m_pValue;
151  bool m_found, m_getValueNames;
152 };
153 
154 template <class BASE, class T>
155 GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
156 {
157  return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
158 }
159 
160 template <class T>
161 GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
162 {
163  return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
164 }
165 
166 // ********************************************************
167 
168 template <class R>
169 R Hack_DefaultValueFromConstReferenceType(const R &)
170 {
171  return R();
172 }
173 
174 template <class R>
175 bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
176 {
177  return source.GetValue(name, const_cast<R &>(value));
178 }
179 
180 template <class T, class BASE>
182 {
183 public:
184  AssignFromHelperClass(T *pObject, const NameValuePairs &source)
185  : m_pObject(pObject), m_source(source), m_done(false)
186  {
187  if (source.GetThisObject(*pObject))
188  m_done = true;
189  else if (typeid(BASE) != typeid(T))
190  pObject->BASE::AssignFrom(source);
191  }
192 
193  template <class R>
194  AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
195  {
196  if (!m_done)
197  {
198  R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
199  if (!Hack_GetValueIntoConstReference(m_source, name, value))
200  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
201  (m_pObject->*pm)(value);
202  }
203  return *this;
204  }
205 
206  template <class R, class S>
207  AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
208  {
209  if (!m_done)
210  {
211  R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
212  if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
213  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
214  S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
215  if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
216  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
217  (m_pObject->*pm)(value1, value2);
218  }
219  return *this;
220  }
221 
222 private:
223  T *m_pObject;
224  const NameValuePairs &m_source;
225  bool m_done;
226 };
227 
228 template <class BASE, class T>
229 AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
230 {
231  return AssignFromHelperClass<T, BASE>(pObject, source);
232 }
233 
234 template <class T>
235 AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
236 {
237  return AssignFromHelperClass<T, T>(pObject, source);
238 }
239 
240 // ********************************************************
241 
242 // to allow the linker to discard Integer code if not needed.
243 typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
244 CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
245 
246 CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
247 
248 class CRYPTOPP_DLL AlgorithmParametersBase
249 {
250 public:
252  {
253  public:
254  ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
255  };
256 
257  // this is actually a move, not a copy
259  : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
260  {
261  m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
262  x.m_used = true;
263  }
264 
265  AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
266  : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
267 
268  virtual ~AlgorithmParametersBase()
269  {
270 #ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
271  if (!std::uncaught_exception())
272 #else
273  try
274 #endif
275  {
276  if (m_throwIfNotUsed && !m_used)
277  throw ParameterNotUsed(m_name);
278  }
279 #ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
280  catch(...)
281  {
282  }
283 #endif
284  }
285 
286  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
287 
288 protected:
289  friend class AlgorithmParameters;
290  void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
291 
292  virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
293  virtual void MoveInto(void *p) const =0; // not really const
294 
295  const char *m_name;
296  bool m_throwIfNotUsed;
297  mutable bool m_used;
299 };
300 
301 template <class T>
303 {
304 public:
305  AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
306  : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
307  {
308  }
309 
310  void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
311  {
312  // special case for retrieving an Integer parameter when an int was passed in
313  if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
314  {
315  NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
316  *reinterpret_cast<T *>(pValue) = m_value;
317  }
318  }
319 
320  void MoveInto(void *buffer) const
321  {
323  }
324 
325 protected:
326  T m_value;
327 };
328 
329 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
330 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
331 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
332 
333 class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
334 {
335 public:
337 
338 #ifdef __BORLANDC__
339  template <class T>
340  AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
341  : m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
342  , m_defaultThrowIfNotUsed(throwIfNotUsed)
343  {
344  }
345 #endif
346 
348 
349  AlgorithmParameters & operator=(const AlgorithmParameters &x);
350 
351  template <class T>
352  AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
353  {
354  member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
355  p->m_next.reset(m_next.release());
356  m_next.reset(p.release());
357  m_defaultThrowIfNotUsed = throwIfNotUsed;
358  return *this;
359  }
360 
361  template <class T>
362  AlgorithmParameters & operator()(const char *name, const T &value)
363  {
364  return operator()(name, value, m_defaultThrowIfNotUsed);
365  }
366 
367  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
368 
369 protected:
371  bool m_defaultThrowIfNotUsed;
372 };
373 
374 //! Create an object that implements NameValuePairs for passing parameters
375 /*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
376  \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
377  such as MSVC 7.0 and earlier.
378  \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
379  repeatedly using operator() on the object returned by MakeParameters, for example:
380  AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
381 */
382 #ifdef __BORLANDC__
383 typedef AlgorithmParameters MakeParameters;
384 #else
385 template <class T>
386 AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
387 {
388  return AlgorithmParameters()(name, value, throwIfNotUsed);
389 }
390 #endif
391 
392 #define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
393 #define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
394 #define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
395 
396 NAMESPACE_END
397 
398 #endif
used to pass byte array input as part of a NameValuePairs object
Definition: algparam.h:13
base class for all exceptions thrown by Crypto++
Definition: cryptlib.h:109
exception thrown when an invalid argument is detected
Definition: cryptlib.h:144
bool GetThisObject(T &object) const
get a copy of this object or a subobject of it
Definition: cryptlib.h:247
bool GetValue(const char *name, T &value) const
get a named value, returns true if the name exists
Definition: cryptlib.h:261
virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0
to be implemented by derived classes, users should use one of the above functions instead ...
static void ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving)
used by derived classes to check for type mismatch
Definition: cryptlib.h:289
interface for retrieving values given their names
Definition: cryptlib.h:224