Crypto++  5.6.3
Free C++ class library of cryptographic schemes
algparam.h
Go to the documentation of this file.
1 // algparam.h - written and placed in the public domain by Wei Dai
2 
3 //! \file
4 //! \headerfile algparam.h
5 //! \brief Classes for working with NameValuePairs
6 
7 
8 #ifndef CRYPTOPP_ALGPARAM_H
9 #define CRYPTOPP_ALGPARAM_H
10 
11 #include "cryptlib.h"
12 #include "config.h"
13 
14 // TODO: fix 6011 when the API/ABI can change
15 #if CRYPTOPP_MSC_VERSION
16 # pragma warning(push)
17 # pragma warning(disable: 6011 28193)
18 #endif
19 
20 #include "smartptr.h"
21 #include "secblock.h"
22 #include "integer.h"
23 #include "misc.h"
24 
25 NAMESPACE_BEGIN(CryptoPP)
26 
27 //! used to pass byte array input as part of a NameValuePairs object
28 /*! the deepCopy option is used when the NameValuePairs object can't
29  keep a copy of the data available */
31 {
32 public:
33  ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
34  : m_deepCopy(false), m_data(NULL), m_size(0)
35  {
36  Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
37  }
38  ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
39  : m_deepCopy(false), m_data(NULL), m_size(0)
40  {
41  Assign(data, size, deepCopy);
42  }
43  template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
44  : m_deepCopy(false), m_data(NULL), m_size(0)
45  {
46  CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
47  Assign((const byte *)string.data(), string.size(), deepCopy);
48  }
49 
50  void Assign(const byte *data, size_t size, bool deepCopy)
51  {
52  // This fires, which means: no data with a size, or data with no size.
53  // assert((data && size) || !(data || size));
54  if (deepCopy)
55  m_block.Assign(data, size);
56  else
57  {
58  m_data = data;
59  m_size = size;
60  }
61  m_deepCopy = deepCopy;
62  }
63 
64  const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
65  const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
66  size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
67 
68 private:
69  bool m_deepCopy;
70  const byte *m_data;
71  size_t m_size;
72  SecByteBlock m_block;
73 };
74 
76 {
77 public:
78  ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
79  : m_data(data), m_size(size) {}
81  : m_data(block.begin()), m_size(block.size()) {}
82 
83  byte *begin() const {return m_data;}
84  byte *end() const {return m_data + m_size;}
85  size_t size() const {return m_size;}
86 
87 private:
88  byte *m_data;
89  size_t m_size;
90 };
91 
92 class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
93 {
94 public:
95  CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
96  : m_pairs1(pairs1), m_pairs2(pairs2) {}
97 
98  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
99 
100 private:
101  const NameValuePairs &m_pairs1, &m_pairs2;
102 };
103 
104 template <class T, class BASE>
106 {
107 public:
108  GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
109  : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
110  {
111  if (strcmp(m_name, "ValueNames") == 0)
112  {
113  m_found = m_getValueNames = true;
114  NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
115  if (searchFirst)
116  searchFirst->GetVoidValue(m_name, valueType, pValue);
117  if (typeid(T) != typeid(BASE))
118  pObject->BASE::GetVoidValue(m_name, valueType, pValue);
119  ((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
120  }
121 
122  if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
123  {
124  NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
125  *reinterpret_cast<const T **>(pValue) = pObject;
126  m_found = true;
127  return;
128  }
129 
130  if (!m_found && searchFirst)
131  m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
132 
133  if (!m_found && typeid(T) != typeid(BASE))
134  m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
135  }
136 
137  operator bool() const {return m_found;}
138 
139  template <class R>
140  GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
141  {
142  if (m_getValueNames)
143  (*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
144  if (!m_found && strcmp(name, m_name) == 0)
145  {
146  NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
147  *reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
148  m_found = true;
149  }
150  return *this;
151  }
152 
153  GetValueHelperClass<T,BASE> &Assignable()
154  {
155 #ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
156  if (m_getValueNames)
157  ((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
158  if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
159  {
160  NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
161  *reinterpret_cast<T *>(m_pValue) = *m_pObject;
162  m_found = true;
163  }
164 #endif
165  return *this;
166  }
167 
168 private:
169  const T *m_pObject;
170  const char *m_name;
171  const std::type_info *m_valueType;
172  void *m_pValue;
173  bool m_found, m_getValueNames;
174 };
175 
176 template <class BASE, class T>
177 GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
178 {
179  CRYPTOPP_UNUSED(dummy);
180  return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
181 }
182 
183 template <class T>
184 GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
185 {
186  return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
187 }
188 
189 // ********************************************************
190 
191 // VC60 workaround
192 #if defined(_MSC_VER) && (_MSC_VER < 1300)
193 template <class R>
194 R Hack_DefaultValueFromConstReferenceType(const R &)
195 {
196  return R();
197 }
198 
199 template <class R>
200 bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
201 {
202  return source.GetValue(name, const_cast<R &>(value));
203 }
204 
205 template <class T, class BASE>
207 {
208 public:
209  AssignFromHelperClass(T *pObject, const NameValuePairs &source)
210  : m_pObject(pObject), m_source(source), m_done(false)
211  {
212  if (source.GetThisObject(*pObject))
213  m_done = true;
214  else if (typeid(BASE) != typeid(T))
215  pObject->BASE::AssignFrom(source);
216  }
217 
218  template <class R>
219  AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
220  {
221  if (!m_done)
222  {
223  R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
224  if (!Hack_GetValueIntoConstReference(m_source, name, value))
225  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
226  (m_pObject->*pm)(value);
227  }
228  return *this;
229  }
230 
231  template <class R, class S>
232  AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
233  {
234  if (!m_done)
235  {
236  R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
237  if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
238  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
239  S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
240  if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
241  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
242  (m_pObject->*pm)(value1, value2);
243  }
244  return *this;
245  }
246 
247 private:
248  T *m_pObject;
249  const NameValuePairs &m_source;
250  bool m_done;
251 };
252 #else
253 template <class T, class BASE>
255 {
256 public:
257  AssignFromHelperClass(T *pObject, const NameValuePairs &source)
258  : m_pObject(pObject), m_source(source), m_done(false)
259  {
260  if (source.GetThisObject(*pObject))
261  m_done = true;
262  else if (typeid(BASE) != typeid(T))
263  pObject->BASE::AssignFrom(source);
264  }
265 
266  template <class R>
267  AssignFromHelperClass & operator()(const char *name, void (T::*pm)(const R&))
268  {
269  if (!m_done)
270  {
271  R value;
272  if (!m_source.GetValue(name, value))
273  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
274  (m_pObject->*pm)(value);
275  }
276  return *this;
277  }
278 
279  template <class R, class S>
280  AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(const R&, const S&))
281  {
282  if (!m_done)
283  {
284  R value1;
285  if (!m_source.GetValue(name1, value1))
286  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
287  S value2;
288  if (!m_source.GetValue(name2, value2))
289  throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
290  (m_pObject->*pm)(value1, value2);
291  }
292  return *this;
293  }
294 
295 private:
296  T *m_pObject;
297  const NameValuePairs &m_source;
298  bool m_done;
299 };
300 #endif
301 
302 template <class BASE, class T>
303 AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
304 {
305  CRYPTOPP_UNUSED(dummy);
306  return AssignFromHelperClass<T, BASE>(pObject, source);
307 }
308 
309 template <class T>
310 AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
311 {
312  return AssignFromHelperClass<T, T>(pObject, source);
313 }
314 
315 // ********************************************************
316 
317 // to allow the linker to discard Integer code if not needed.
318 typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
319 CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
320 
321 CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
322 
323 class CRYPTOPP_DLL AlgorithmParametersBase
324 {
325 public:
327  {
328  public:
329  ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
330  };
331 
332  // this is actually a move, not a copy
334  : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
335  {
336  m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
337  x.m_used = true;
338  }
339 
340  AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
341  : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
342 
343  virtual ~AlgorithmParametersBase() CRYPTOPP_THROW
344  {
345 #ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
346  if (!std::uncaught_exception())
347 #else
348  try
349 #endif
350  {
351  if (m_throwIfNotUsed && !m_used)
352  throw ParameterNotUsed(m_name);
353  }
354 #ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
355  catch(const Exception&)
356  {
357  }
358 #endif
359  }
360 
361  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
362 
363 protected:
364  friend class AlgorithmParameters;
365  void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
366 
367  virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
368  virtual void MoveInto(void *p) const =0; // not really const
369 
370  const char *m_name;
371  bool m_throwIfNotUsed;
372  mutable bool m_used;
374 };
375 
376 template <class T>
378 {
379 public:
380  AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
381  : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
382  {
383  }
384 
385  void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
386  {
387  // special case for retrieving an Integer parameter when an int was passed in
388  if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
389  {
390  NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
391  *reinterpret_cast<T *>(pValue) = m_value;
392  }
393  }
394 
395  void MoveInto(void *buffer) const
396  {
398  CRYPTOPP_UNUSED(p); // silence warning
399  }
400 
401 protected:
402  T m_value;
403 };
404 
405 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
406 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
407 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
408 
409 //! \class AlgorithmParameters
410 //! \brief An object that implements NameValuePairs
411 //! \tparam T the class or type
412 //! \param name the name of the object or value to retrieve
413 //! \param value reference to a variable that receives the value
414 //! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
415 //! \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
416 //! such as MSVC 7.0 and earlier.
417 //! \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
418 //! repeatedly using operator() on the object returned by MakeParameters, for example:
419 //! <pre>
420 //! AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
421 //! </pre>
422 class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
423 {
424 public:
426 
427 #ifdef __BORLANDC__
428  template <class T>
429  AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
430  : m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
431  , m_defaultThrowIfNotUsed(throwIfNotUsed)
432  {
433  }
434 #endif
435 
437 
438  AlgorithmParameters & operator=(const AlgorithmParameters &x);
439 
440  //! \tparam T the class or type
441  //! \param name the name of the object or value to retrieve
442  //! \param value reference to a variable that receives the value
443  //! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
444  template <class T>
445  AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
446  {
447  member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
448  p->m_next.reset(m_next.release());
449  m_next.reset(p.release());
450  m_defaultThrowIfNotUsed = throwIfNotUsed;
451  return *this;
452  }
453 
454  //! \brief Appends a NameValuePair to a collection of NameValuePairs
455  //! \tparam T the class or type
456  //! \param name the name of the object or value to retrieve
457  //! \param value reference to a variable that receives the value
458  template <class T>
459  AlgorithmParameters & operator()(const char *name, const T &value)
460  {
461  return operator()(name, value, m_defaultThrowIfNotUsed);
462  }
463 
464  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
465 
466 protected:
468  bool m_defaultThrowIfNotUsed;
469 };
470 
471 //! \brief Create an object that implements NameValuePairs
472 //! \tparam T the class or type
473 //! \param name the name of the object or value to retrieve
474 //! \param value reference to a variable that receives the value
475 //! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
476 //! \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
477 //! such as MSVC 7.0 and earlier.
478 //! \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
479 //! repeatedly using \p operator() on the object returned by \p MakeParameters, for example:
480 //! <pre>
481 //! AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
482 //! </pre>
483 #ifdef __BORLANDC__
485 #else
486 template <class T>
487 AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
488 {
489  return AlgorithmParameters()(name, value, throwIfNotUsed);
490 }
491 #endif
492 
493 #define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
494 #define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
495 #define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
496 
497 NAMESPACE_END
498 
499 #endif
used to pass byte array input as part of a NameValuePairs object
Definition: algparam.h:30
Base class for all exceptions thrown by Crypto++.
Definition: cryptlib.h:124
An invalid argument was detected.
Definition: cryptlib.h:166
bool GetThisObject(T &object) const
Get a copy of this object or subobject.
Definition: cryptlib.h:297
Utility functions for the Crypto++ library.
Abstract base classes that provide a uniform interface to this library.
virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0
Get a named value.
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:509
Classes for automatic resource management.
Library configuration file.
SecByteBlock is a SecBlock<byte> typedef.
Definition: secblock.h:719
Classes and functions for secure memory allocations.
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:319
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
Definition: algparam.h:487
#define CRYPTOPP_COMPILE_ASSERT(expr)
Compile time assertion.
Definition: misc.h:98
AlgorithmParameters & operator()(const char *name, const T &value)
Appends a NameValuePair to a collection of NameValuePairs.
Definition: algparam.h:459
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:484
static void ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving)
Ensures an expected name and type is present.
Definition: cryptlib.h:376
AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
Definition: algparam.h:445
An object that implements NameValuePairs.
Definition: algparam.h:422
Crypto++ library namespace.
Interface for retrieving values given their names.
Definition: cryptlib.h:261