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