00001 #ifndef DataFormats_Provenance_Hash_h
00002 #define DataFormats_Provenance_Hash_h
00003
00004 #include <string>
00005
00006 #include "FWCore/Utilities/interface/Digest.h"
00007 #include "FWCore/Utilities/interface/EDMException.h"
00008 #include "FWCore/Utilities/interface/Algorithms.h"
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 namespace edm {
00024
00025 namespace detail
00026 {
00027
00028 std::string const& InvalidHash();
00029 }
00030
00031 template <int I>
00032 class Hash {
00033 public:
00034 typedef std::string value_type;
00035
00036 Hash();
00037 explicit Hash(value_type const& v);
00038
00039 Hash(Hash<I> const&);
00040 Hash<I> const& operator=(Hash<I> const& iRHS);
00041
00042
00043
00044
00045
00046
00047 bool isValid() const;
00048
00049 bool operator< (Hash<I> const& other) const;
00050 bool operator> (Hash<I> const& other) const;
00051 bool operator== (Hash<I> const& other) const;
00052 bool operator!= (Hash<I> const& other) const;
00053 std::ostream& print(std::ostream& os) const;
00054 void swap(Hash<I>& other);
00055
00056
00057 value_type compactForm() const;
00058
00059 bool isCompactForm()const;
00060
00061 private:
00062
00065 void throwIfIllFormed() const;
00066
00067
00068
00069
00070 void fixup();
00071
00072 template< typename Op>
00073 bool
00074 compareUsing(Hash<I> const& iOther, Op op) const {
00075 if(this->isCompactForm() == iOther.isCompactForm()) {
00076 return op(this->hash_,iOther.hash_);
00077 }
00078 Hash<I> tMe(*this);
00079 Hash<I> tOther(iOther);
00080 return op(tMe.hash_,tOther.hash_);
00081 }
00082
00083 value_type hash_;
00084 };
00085
00086
00087
00088
00089
00090
00091
00092
00093 template <int I>
00094 inline
00095 Hash<I>::Hash() :
00096 hash_()
00097 {
00098 fixup();
00099 }
00100
00101 template <int I>
00102 inline
00103 Hash<I>::Hash(typename Hash<I>::value_type const& v) :
00104 hash_(v)
00105 {
00106 fixup();
00107 }
00108
00109 template <int I>
00110 inline
00111 Hash<I>::Hash(Hash<I> const& iOther):
00112 hash_(iOther.hash_)
00113 {
00114 fixup();
00115 }
00116
00117 template <int I>
00118 inline
00119 Hash<I> const&
00120 Hash<I>::operator=(Hash<I> const& iRHS)
00121 {
00122 hash_=iRHS.hash_;
00123 fixup();
00124 return *this;
00125 }
00126
00127 template <int I>
00128 inline
00129 bool
00130 Hash<I>::isValid() const
00131 {
00132 return isCompactForm() ? (hash_ != edm::detail::InvalidHash()) : (hash_.size()!=0);
00133 }
00134
00135 template <int I>
00136 inline
00137 bool
00138 Hash<I>::operator< (Hash<I> const& other) const
00139 {
00140 return this->compareUsing(other, std::less<std::string >());
00141 }
00142
00143 template <int I>
00144 inline
00145 bool
00146 Hash<I>::operator> (Hash<I> const& other) const
00147 {
00148 return this->compareUsing(other, std::greater<std::string >());
00149 }
00150
00151 template <int I>
00152 inline
00153 bool
00154 Hash<I>::operator== (Hash<I> const& other) const
00155 {
00156 return this->compareUsing(other, std::equal_to<std::string >());
00157 }
00158
00159 template <int I>
00160 inline
00161 bool
00162 Hash<I>::operator!= (Hash<I> const& other) const
00163 {
00164 return this->compareUsing(other, std::not_equal_to<std::string >());
00165 }
00166
00167 template <int I>
00168 inline
00169 std::ostream&
00170 Hash<I>::print(std::ostream& os) const
00171 {
00172 Hash<I> tMe(*this);
00173 cms::MD5Result temp;
00174 copy_all(tMe.hash_, temp.bytes);
00175 os << temp.toString();
00176 return os;
00177 }
00178
00179 template <int I>
00180 inline
00181 void
00182 Hash<I>::swap(Hash<I>& other)
00183 {
00184 fixup();
00185 hash_.swap(other.hash_);
00186 fixup();
00187 }
00188
00189 template <int I>
00190 inline
00191 typename Hash<I>::value_type
00192 Hash<I>::compactForm() const
00193 {
00194 if (this->isCompactForm()) {
00195 return hash_;
00196 }
00197 Hash<I> tMe(*this);
00198 return tMe.compactForm();
00199 }
00200
00201 template <int I>
00202 inline
00203 void
00204 Hash<I>::throwIfIllFormed() const
00205 {
00206
00207 if (hash_.size() % 2 == 1)
00208 {
00209 throw edm::Exception(edm::errors::LogicError)
00210 << "Ill-formed Hash instance. "
00211 << "Please report this to the core framework developers";
00212 }
00213 }
00214
00215
00216
00217
00218 template <int I>
00219 void
00220 Hash<I>::fixup() {
00221 switch (hash_.size()) {
00222 case 0:
00223 {
00224 hash_ = edm::detail::InvalidHash();
00225 }
00226 case 16:
00227 {
00228 break;
00229 }
00230 case 32:
00231 {
00232 cms::MD5Result temp;
00233 temp.fromHexifiedString(hash_);
00234 hash_ = temp.compactForm();
00235 break;
00236 }
00237 default:
00238 {
00239 throw edm::Exception(edm::errors::LogicError)
00240 << "edm::Hash<> instance with data in illegal state:\n"
00241 << hash_
00242 << "\nPlease report this to the core framework developers";
00243 }
00244 }
00245 }
00246
00247 template <int I>
00248 inline
00249 bool Hash<I>::isCompactForm() const {
00250 return 16 == hash_.size();
00251 }
00252
00253
00254
00255 template <int I>
00256 inline
00257 void
00258 swap(Hash<I>& a, Hash<I>& b)
00259 {
00260 a.swap(b);
00261 }
00262
00263 template <int I>
00264 inline
00265 std::ostream&
00266 operator<< (std::ostream& os, Hash<I> const& h)
00267 {
00268 return h.print(os);
00269 }
00270
00271 }
00272 #endif