00001
00002
00003
00004
00005
00006
00007
00008 #ifndef CRYPTOPP_ALGPARAM_H
00009 #define CRYPTOPP_ALGPARAM_H
00010
00011 #include "cryptlib.h"
00012 #include "config.h"
00013
00014
00015 #if (CRYPTOPP_MSC_VERSION >= 1400)
00016 # pragma warning(push)
00017 # pragma warning(disable: 6011 28193)
00018 #endif
00019
00020 #include "smartptr.h"
00021 #include "secblock.h"
00022 #include "integer.h"
00023 #include "misc.h"
00024
00025 NAMESPACE_BEGIN(CryptoPP)
00026
00027
00028
00029
00030 class ConstByteArrayParameter
00031 {
00032 public:
00033 ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
00034 : m_deepCopy(false), m_data(NULL), m_size(0)
00035 {
00036 Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
00037 }
00038 ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
00039 : m_deepCopy(false), m_data(NULL), m_size(0)
00040 {
00041 Assign(data, size, deepCopy);
00042 }
00043 template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
00044 : m_deepCopy(false), m_data(NULL), m_size(0)
00045 {
00046 CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1);
00047 Assign((const byte *)string.data(), string.size(), deepCopy);
00048 }
00049
00050 void Assign(const byte *data, size_t size, bool deepCopy)
00051 {
00052
00053
00054 if (deepCopy)
00055 m_block.Assign(data, size);
00056 else
00057 {
00058 m_data = data;
00059 m_size = size;
00060 }
00061 m_deepCopy = deepCopy;
00062 }
00063
00064 const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
00065 const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
00066 size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
00067
00068 private:
00069 bool m_deepCopy;
00070 const byte *m_data;
00071 size_t m_size;
00072 SecByteBlock m_block;
00073 };
00074
00075 class ByteArrayParameter
00076 {
00077 public:
00078 ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
00079 : m_data(data), m_size(size) {}
00080 ByteArrayParameter(SecByteBlock &block)
00081 : m_data(block.begin()), m_size(block.size()) {}
00082
00083 byte *begin() const {return m_data;}
00084 byte *end() const {return m_data + m_size;}
00085 size_t size() const {return m_size;}
00086
00087 private:
00088 byte *m_data;
00089 size_t m_size;
00090 };
00091
00092 class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
00093 {
00094 public:
00095 CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
00096 : m_pairs1(pairs1), m_pairs2(pairs2) {}
00097
00098 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
00099
00100 private:
00101 const NameValuePairs &m_pairs1, &m_pairs2;
00102 };
00103
00104 template <class T, class BASE>
00105 class GetValueHelperClass
00106 {
00107 public:
00108 GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
00109 : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
00110 {
00111 if (strcmp(m_name, "ValueNames") == 0)
00112 {
00113 m_found = m_getValueNames = true;
00114 NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
00115 if (searchFirst)
00116 searchFirst->GetVoidValue(m_name, valueType, pValue);
00117 if (typeid(T) != typeid(BASE))
00118 pObject->BASE::GetVoidValue(m_name, valueType, pValue);
00119 ((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
00120 }
00121
00122 if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
00123 {
00124 NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
00125 *reinterpret_cast<const T **>(pValue) = pObject;
00126 m_found = true;
00127 return;
00128 }
00129
00130 if (!m_found && searchFirst)
00131 m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
00132
00133 if (!m_found && typeid(T) != typeid(BASE))
00134 m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
00135 }
00136
00137 operator bool() const {return m_found;}
00138
00139 template <class R>
00140 GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
00141 {
00142 if (m_getValueNames)
00143 (*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
00144 if (!m_found && strcmp(name, m_name) == 0)
00145 {
00146 NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
00147 *reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
00148 m_found = true;
00149 }
00150 return *this;
00151 }
00152
00153 GetValueHelperClass<T,BASE> &Assignable()
00154 {
00155 #ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
00156 if (m_getValueNames)
00157 ((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
00158 if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
00159 {
00160 NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
00161 *reinterpret_cast<T *>(m_pValue) = *m_pObject;
00162 m_found = true;
00163 }
00164 #endif
00165 return *this;
00166 }
00167
00168 private:
00169 const T *m_pObject;
00170 const char *m_name;
00171 const std::type_info *m_valueType;
00172 void *m_pValue;
00173 bool m_found, m_getValueNames;
00174 };
00175
00176 template <class BASE, class T>
00177 GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
00178 {
00179 CRYPTOPP_UNUSED(dummy);
00180 return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
00181 }
00182
00183 template <class T>
00184 GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
00185 {
00186 return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
00187 }
00188
00189
00190
00191
00192 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00193 template <class R>
00194 R Hack_DefaultValueFromConstReferenceType(const R &)
00195 {
00196 return R();
00197 }
00198
00199 template <class R>
00200 bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
00201 {
00202 return source.GetValue(name, const_cast<R &>(value));
00203 }
00204
00205 template <class T, class BASE>
00206 class AssignFromHelperClass
00207 {
00208 public:
00209 AssignFromHelperClass(T *pObject, const NameValuePairs &source)
00210 : m_pObject(pObject), m_source(source), m_done(false)
00211 {
00212 if (source.GetThisObject(*pObject))
00213 m_done = true;
00214 else if (typeid(BASE) != typeid(T))
00215 pObject->BASE::AssignFrom(source);
00216 }
00217
00218 template <class R>
00219 AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R))
00220 {
00221 if (!m_done)
00222 {
00223 R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
00224 if (!Hack_GetValueIntoConstReference(m_source, name, value))
00225 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
00226 (m_pObject->*pm)(value);
00227 }
00228 return *this;
00229 }
00230
00231 template <class R, class S>
00232 AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S))
00233 {
00234 if (!m_done)
00235 {
00236 R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
00237 if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
00238 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
00239 S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
00240 if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
00241 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
00242 (m_pObject->*pm)(value1, value2);
00243 }
00244 return *this;
00245 }
00246
00247 private:
00248 T *m_pObject;
00249 const NameValuePairs &m_source;
00250 bool m_done;
00251 };
00252 #else
00253 template <class T, class BASE>
00254 class AssignFromHelperClass
00255 {
00256 public:
00257 AssignFromHelperClass(T *pObject, const NameValuePairs &source)
00258 : m_pObject(pObject), m_source(source), m_done(false)
00259 {
00260 if (source.GetThisObject(*pObject))
00261 m_done = true;
00262 else if (typeid(BASE) != typeid(T))
00263 pObject->BASE::AssignFrom(source);
00264 }
00265
00266 template <class R>
00267 AssignFromHelperClass & operator()(const char *name, void (T::*pm)(const R&))
00268 {
00269 if (!m_done)
00270 {
00271 R value;
00272 if (!m_source.GetValue(name, value))
00273 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
00274 (m_pObject->*pm)(value);
00275 }
00276 return *this;
00277 }
00278
00279 template <class R, class S>
00280 AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(const R&, const S&))
00281 {
00282 if (!m_done)
00283 {
00284 R value1;
00285 if (!m_source.GetValue(name1, value1))
00286 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
00287 S value2;
00288 if (!m_source.GetValue(name2, value2))
00289 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
00290 (m_pObject->*pm)(value1, value2);
00291 }
00292 return *this;
00293 }
00294
00295 private:
00296 T *m_pObject;
00297 const NameValuePairs &m_source;
00298 bool m_done;
00299 };
00300 #endif
00301
00302 template <class BASE, class T>
00303 AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
00304 {
00305 CRYPTOPP_UNUSED(dummy);
00306 return AssignFromHelperClass<T, BASE>(pObject, source);
00307 }
00308
00309 template <class T>
00310 AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
00311 {
00312 return AssignFromHelperClass<T, T>(pObject, source);
00313 }
00314
00315
00316
00317
00318 typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
00319 CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
00320
00321 CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
00322
00323 class CRYPTOPP_DLL AlgorithmParametersBase
00324 {
00325 public:
00326 class ParameterNotUsed : public Exception
00327 {
00328 public:
00329 ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
00330 };
00331
00332
00333 AlgorithmParametersBase(const AlgorithmParametersBase &x)
00334 : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
00335 {
00336 m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
00337 x.m_used = true;
00338 }
00339
00340 AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
00341 : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
00342
00343 virtual ~AlgorithmParametersBase() CRYPTOPP_THROW
00344 {
00345 #ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
00346 if (!std::uncaught_exception())
00347 #else
00348 try
00349 #endif
00350 {
00351 if (m_throwIfNotUsed && !m_used)
00352 throw ParameterNotUsed(m_name);
00353 }
00354 #ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
00355 catch(const Exception&)
00356 {
00357 }
00358 #endif
00359 }
00360
00361 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
00362
00363 protected:
00364 friend class AlgorithmParameters;
00365 void operator=(const AlgorithmParametersBase& rhs);
00366
00367 virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
00368 virtual void MoveInto(void *p) const =0;
00369
00370 const char *m_name;
00371 bool m_throwIfNotUsed;
00372 mutable bool m_used;
00373 member_ptr<AlgorithmParametersBase> m_next;
00374 };
00375
00376 template <class T>
00377 class AlgorithmParametersTemplate : public AlgorithmParametersBase
00378 {
00379 public:
00380 AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
00381 : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
00382 {
00383 }
00384
00385 void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
00386 {
00387
00388 if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
00389 {
00390 NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
00391 *reinterpret_cast<T *>(pValue) = m_value;
00392 }
00393 }
00394
00395 void MoveInto(void *buffer) const
00396 {
00397 AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
00398 CRYPTOPP_UNUSED(p);
00399 }
00400
00401 protected:
00402 T m_value;
00403 };
00404
00405 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
00406 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
00407 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
00423 {
00424 public:
00425 AlgorithmParameters();
00426
00427 #ifdef __BORLANDC__
00428 template <class T>
00429 AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
00430 : m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
00431 , m_defaultThrowIfNotUsed(throwIfNotUsed)
00432 {
00433 }
00434 #endif
00435
00436 AlgorithmParameters(const AlgorithmParameters &x);
00437
00438 AlgorithmParameters & operator=(const AlgorithmParameters &x);
00439
00440
00441
00442
00443
00444 template <class T>
00445 AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
00446 {
00447 member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
00448 p->m_next.reset(m_next.release());
00449 m_next.reset(p.release());
00450 m_defaultThrowIfNotUsed = throwIfNotUsed;
00451 return *this;
00452 }
00453
00454
00455
00456
00457
00458 template <class T>
00459 AlgorithmParameters & operator()(const char *name, const T &value)
00460 {
00461 return operator()(name, value, m_defaultThrowIfNotUsed);
00462 }
00463
00464 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
00465
00466 protected:
00467 member_ptr<AlgorithmParametersBase> m_next;
00468 bool m_defaultThrowIfNotUsed;
00469 };
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 #ifdef __BORLANDC__
00484 typedef AlgorithmParameters MakeParameters;
00485 #else
00486 template <class T>
00487 AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
00488 {
00489 return AlgorithmParameters()(name, value, throwIfNotUsed);
00490 }
00491 #endif
00492
00493 #define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
00494 #define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
00495 #define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
00496
00497
00498 #if (CRYPTOPP_MSC_VERSION >= 1400)
00499 # pragma warning(pop)
00500 #endif
00501
00502 NAMESPACE_END
00503
00504 #endif