CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DataFormats/Provenance/interface/Hash.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Provenance_Hash_h
00002 #define DataFormats_Provenance_Hash_h
00003 
00004 #include <string>
00005 
00006 /*----------------------------------------------------------------------
00007   
00008 Hash:
00009 
00010   Note: The call to 'fixup' in every member function is a temporary
00011   measure for backwards compatibility. It is necessary in every function
00012   because Root creates instances of the class *without* using the
00013   interface of the class, thus making it insufficient to assure that
00014   all constructors make corrected instances.
00015 
00016 ----------------------------------------------------------------------*/
00017 namespace cms {
00018   class Digest;
00019 }
00020 
00021 namespace edm {
00022 
00023   namespace detail {
00024     // This string is the 16-byte, non-printable version.
00025     std::string const& InvalidHash();
00026   }
00027 
00028   namespace hash_detail {
00029     typedef std::string value_type;
00030     value_type compactForm_(value_type const& hash);
00031     void fixup_(value_type& hash);
00032     bool isCompactForm_(value_type const& hash);
00033     bool isValid_(value_type const& hash);
00034     void throwIfIllFormed(value_type const& hash);
00035     void toString_(std::string& result, value_type const& hash);
00036     void toDigest_(cms::Digest& digest, value_type const& hash);
00037     std::ostream& print_(std::ostream& os, value_type const& hash);
00038   }
00039 
00040   template <int I>
00041   class Hash {
00042   public:
00043     typedef hash_detail::value_type value_type;
00044 
00045     Hash();
00046     explicit Hash(value_type const& v);
00047 
00048     Hash(Hash<I> const&);
00049     Hash<I>& operator=(Hash<I> const& iRHS);
00050 
00051     void reset();
00052 
00053     // For now, just check the most basic: a default constructed
00054     // ParameterSetID is not valid. This is very crude: we are
00055     // assuming that nobody created a ParameterSetID from an empty
00056     // string, nor from any string that is not a valid string
00057     // representation of an MD5 checksum.
00058     bool isValid() const;
00059 
00060     bool operator<(Hash<I> const& other) const;
00061     bool operator>(Hash<I> const& other) const;
00062     bool operator==(Hash<I> const& other) const;
00063     bool operator!=(Hash<I> const& other) const;
00064     std::ostream& print(std::ostream& os) const;
00065     void toString(std::string& result) const;
00066     void toDigest(cms::Digest& digest) const;
00067     void swap(Hash<I>& other);
00068 
00069     // Return the 16-byte (non-printable) string form.
00070     value_type compactForm() const;
00071     
00072     bool isCompactForm() const;
00073     
00074     //Used by ROOT storage
00075     // CMS_CLASS_VERSION(10) // This macro is not defined here, so expand it.
00076     static short Class_Version() {return 10;}
00077 
00078   private:
00079 
00082     void throwIfIllFormed() const;
00083 
00084     template<typename Op>
00085       bool
00086       compareUsing(Hash<I> const& iOther, Op op) const {
00087         bool meCF = hash_detail::isCompactForm_(hash_);
00088         bool otherCF = hash_detail::isCompactForm_(iOther.hash_);
00089         if(meCF == otherCF) {
00090           return op(this->hash_,iOther.hash_);
00091         }
00092         //copy constructor will do compact form conversion
00093         if(meCF) {
00094            Hash<I> temp(iOther);
00095            return op(this->hash_,temp.hash_);
00096         } 
00097         Hash<I> temp(*this);
00098         return op(temp.hash_,iOther.hash_);
00099       }
00100 
00101     value_type hash_;
00102   };
00103 
00104 
00105   //--------------------------------------------------------------------
00106   //
00107   // Implementation details follow...
00108   //--------------------------------------------------------------------
00109 
00110 
00111   template <int I>
00112   inline
00113   Hash<I>::Hash() : hash_(detail::InvalidHash()) {}
00114 
00115   template <int I>
00116   inline
00117   Hash<I>::Hash(typename Hash<I>::value_type const& v) : hash_(v) {
00118     hash_detail::fixup_(hash_);
00119   }
00120 
00121   template <int I>
00122   inline
00123   Hash<I>::Hash(Hash<I> const& iOther) : hash_(iOther.hash_) {
00124      hash_detail::fixup_(hash_);
00125   }
00126 
00127   template <int I>
00128   inline
00129   Hash<I>& 
00130   Hash<I>::operator=(Hash<I> const& iRHS) {
00131     hash_ = iRHS.hash_;
00132     hash_detail::fixup_(hash_);
00133     return *this;
00134   }
00135   
00136   template <int I>
00137   inline
00138   void 
00139   Hash<I>::reset() {
00140     hash_ = detail::InvalidHash();
00141   }
00142   
00143   template <int I>
00144   inline
00145   bool 
00146   Hash<I>::isValid() const {
00147     return hash_detail::isValid_(hash_);
00148   }
00149   
00150   template <int I>
00151   inline
00152   bool
00153   Hash<I>::operator<(Hash<I> const& other) const {
00154     return this->compareUsing(other, std::less<std::string>());
00155   }
00156 
00157   template <int I>
00158   inline
00159   bool 
00160   Hash<I>::operator>(Hash<I> const& other) const {
00161     return this->compareUsing(other, std::greater<std::string>());
00162   }
00163 
00164   template <int I>
00165   inline
00166   bool 
00167   Hash<I>::operator==(Hash<I> const& other) const {
00168     return this->compareUsing(other, std::equal_to<std::string>());
00169   }
00170 
00171   template <int I>
00172   inline
00173   bool 
00174   Hash<I>::operator!=(Hash<I> const& other) const {
00175     return this->compareUsing(other, std::not_equal_to<std::string>());
00176   }
00177 
00178   template <int I>
00179   inline
00180   std::ostream& 
00181   Hash<I>::print(std::ostream& os) const {
00182     return hash_detail::print_(os, hash_);
00183   }
00184 
00185   template <int I>
00186   inline
00187   void
00188   Hash<I>::toString(std::string& result) const {
00189     hash_detail::toString_(result, hash_);
00190   }
00191 
00192   template <int I>
00193   inline
00194   void
00195   Hash<I>::toDigest(cms::Digest& digest) const {
00196     hash_detail::toDigest_(digest, hash_);
00197   }
00198 
00199   template <int I>
00200   inline
00201   void 
00202   Hash<I>::swap(Hash<I>& other) {
00203     hash_.swap(other.hash_);
00204   }
00205 
00206   template <int I>
00207   inline
00208   typename Hash<I>::value_type
00209   Hash<I>::compactForm() const {
00210     return hash_detail::compactForm_(hash_);
00211   }
00212 
00213   // Note: this template is not declared 'inline' because of the
00214   // switch statement.
00215 
00216   template <int I>
00217   inline
00218   bool Hash<I>::isCompactForm() const {
00219     return hash_detail::isCompactForm_(hash_);
00220   }
00221   
00222 
00223   // Free swap function
00224   template <int I>
00225   inline
00226   void
00227   swap(Hash<I>& a, Hash<I>& b) {
00228     a.swap(b);
00229   }
00230 
00231   template <int I>
00232   inline
00233   std::ostream&
00234   operator<<(std::ostream& os, Hash<I> const& h) {
00235     return h.print(os);
00236   }
00237 
00238 }
00239 #endif