1#ifndef CRYPTOPP_ALGPARAM_H 2#define CRYPTOPP_ALGPARAM_H 3 4#include "cryptlib.h" 5#include "smartptr.h" 6#include "secblock.h" 7 8NAMESPACE_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 */ 13class ConstByteArrayParameter 14{ 15public: 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 46private: 47 bool m_deepCopy; 48 const byte *m_data; 49 size_t m_size; 50 SecByteBlock m_block; 51}; 52 53class ByteArrayParameter 54{ 55public: 56 ByteArrayParameter(byte *data = NULL, unsigned int size = 0) 57 : m_data(data), m_size(size) {} 58 ByteArrayParameter(SecByteBlock &block) 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 65private: 66 byte *m_data; 67 size_t m_size; 68}; 69 70class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs 71{ 72public: 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 78private: 79 const NameValuePairs &m_pairs1, &m_pairs2; 80}; 81 82template <class T, class BASE> 83class GetValueHelperClass 84{ 85public: 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 146private: 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 154template <class BASE, class T> 155GetValueHelperClass<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 160template <class T> 161GetValueHelperClass<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 168template <class R> 169R Hack_DefaultValueFromConstReferenceType(const R &) 170{ 171 return R(); 172} 173 174template <class R> 175bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value) 176{ 177 return source.GetValue(name, const_cast<R &>(value)); 178} 179 180template <class T, class BASE> 181class AssignFromHelperClass 182{ 183public: 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 222private: 223 T *m_pObject; 224 const NameValuePairs &m_source; 225 bool m_done; 226}; 227 228template <class BASE, class T> 229AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL) 230{ 231 return AssignFromHelperClass<T, BASE>(pObject, source); 232} 233 234template <class T> 235AssignFromHelperClass<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. 243typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt); 244CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger; 245 246CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId(); 247 248class CRYPTOPP_DLL AlgorithmParametersBase 249{ 250public: 251 class ParameterNotUsed : public Exception 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 258 AlgorithmParametersBase(const AlgorithmParametersBase &x) 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 288protected: 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; 298 member_ptr<AlgorithmParametersBase> m_next; 299}; 300 301template <class T> 302class AlgorithmParametersTemplate : public AlgorithmParametersBase 303{ 304public: 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 { 322 AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this); 323 } 324 325protected: 326 T m_value; 327}; 328 329CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>; 330CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>; 331CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>; 332 333class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs 334{ 335public: 336 AlgorithmParameters(); 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 347 AlgorithmParameters(const AlgorithmParameters &x); 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 369protected: 370 member_ptr<AlgorithmParametersBase> m_next; 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__ 383typedef AlgorithmParameters MakeParameters; 384#else 385template <class T> 386AlgorithmParameters 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 396NAMESPACE_END 397 398#endif 399