Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05:01

0001 #ifndef DataFormats_Provenance_Hash_h
0002 #define DataFormats_Provenance_Hash_h
0003 
0004 #include <string>
0005 #include <functional>
0006 
0007 /*----------------------------------------------------------------------
0008   
0009 Hash:
0010 
0011   Note: The call to 'fixup' in every member function is a temporary
0012   measure for backwards compatibility. It is necessary in every function
0013   because Root creates instances of the class *without* using the
0014   interface of the class, thus making it insufficient to assure that
0015   all constructors make corrected instances.
0016 
0017 ----------------------------------------------------------------------*/
0018 namespace cms {
0019   class Digest;
0020 }
0021 
0022 namespace edm {
0023 
0024   namespace detail {
0025     // This string is the 16-byte, non-printable version.
0026     std::string const& InvalidHash();
0027   }  // namespace detail
0028 
0029   namespace hash_detail {
0030     typedef std::string value_type;
0031     value_type compactForm_(value_type const& hash);
0032     void fixup_(value_type& hash);
0033     bool isCompactForm_(value_type const& hash);
0034     bool isValid_(value_type const& hash);
0035     void throwIfIllFormed(value_type const& hash);
0036     void toString_(std::string& result, value_type const& hash);
0037     void toDigest_(cms::Digest& digest, value_type const& hash);
0038     std::ostream& print_(std::ostream& os, value_type const& hash);
0039     size_t smallHash_(value_type const& hash);
0040   }  // namespace hash_detail
0041 
0042   template <int I>
0043   class Hash {
0044   public:
0045     typedef hash_detail::value_type value_type;
0046 
0047     Hash();
0048     explicit Hash(value_type const& v);
0049 
0050     Hash(Hash<I> const&);
0051     Hash<I>& operator=(Hash<I> const& iRHS);
0052 
0053     Hash(Hash<I>&&) = default;
0054     Hash<I>& operator=(Hash<I>&&) = default;
0055 
0056     void reset();
0057 
0058     // For now, just check the most basic: a default constructed
0059     // ParameterSetID is not valid. This is very crude: we are
0060     // assuming that nobody created a ParameterSetID from an empty
0061     // string, nor from any string that is not a valid string
0062     // representation of an MD5 checksum.
0063     bool isValid() const;
0064 
0065     bool operator<(Hash<I> const& other) const;
0066     bool operator>(Hash<I> const& other) const;
0067     bool operator==(Hash<I> const& other) const;
0068     bool operator!=(Hash<I> const& other) const;
0069     std::ostream& print(std::ostream& os) const;
0070     void toString(std::string& result) const;
0071     void toDigest(cms::Digest& digest) const;
0072     void swap(Hash<I>& other);
0073 
0074     // Return the 16-byte (non-printable) string form.
0075     value_type compactForm() const;
0076 
0077     bool isCompactForm() const;
0078 
0079     ///returns a short hash which can be used with hashing containers
0080     size_t smallHash() const;
0081 
0082     //Used by ROOT storage
0083     // CMS_CLASS_VERSION(11) // This macro is not defined here, so expand it.
0084     static short Class_Version() { return 11; }
0085 
0086   private:
0087     /// Hexified version of data *must* contain a multiple of 2
0088     /// bytes. If it does not, throw an exception.
0089     void throwIfIllFormed() const;
0090 
0091     template <typename Op>
0092     bool compareUsing(Hash<I> const& iOther, Op op) const {
0093       bool meCF = hash_detail::isCompactForm_(hash_);
0094       bool otherCF = hash_detail::isCompactForm_(iOther.hash_);
0095       if (meCF == otherCF) {
0096         return op(this->hash_, iOther.hash_);
0097       }
0098       //copy constructor will do compact form conversion
0099       if (meCF) {
0100         Hash<I> temp(iOther);  // NOLINT(performance-unnecessary-copy-initialization)
0101         return op(this->hash_, temp.hash_);
0102       }
0103       Hash<I> temp(*this);
0104       return op(temp.hash_, iOther.hash_);
0105     }
0106 
0107     value_type hash_;
0108   };
0109 
0110   //--------------------------------------------------------------------
0111   //
0112   // Implementation details follow...
0113   //--------------------------------------------------------------------
0114 
0115   template <int I>
0116   inline Hash<I>::Hash() : hash_(detail::InvalidHash()) {}
0117 
0118   template <int I>
0119   inline Hash<I>::Hash(typename Hash<I>::value_type const& v) : hash_(v) {
0120     hash_detail::fixup_(hash_);
0121   }
0122 
0123   template <int I>
0124   inline Hash<I>::Hash(Hash<I> const& iOther) : hash_(iOther.hash_) {
0125     hash_detail::fixup_(hash_);
0126   }
0127 
0128   template <int I>
0129   inline Hash<I>& Hash<I>::operator=(Hash<I> const& iRHS) {
0130     hash_ = iRHS.hash_;
0131     hash_detail::fixup_(hash_);
0132     return *this;
0133   }
0134 
0135   template <int I>
0136   inline void Hash<I>::reset() {
0137     hash_ = detail::InvalidHash();
0138   }
0139 
0140   template <int I>
0141   inline bool Hash<I>::isValid() const {
0142     return hash_detail::isValid_(hash_);
0143   }
0144 
0145   template <int I>
0146   inline bool Hash<I>::operator<(Hash<I> const& other) const {
0147     return this->compareUsing(other, std::less<std::string>());
0148   }
0149 
0150   template <int I>
0151   inline bool Hash<I>::operator>(Hash<I> const& other) const {
0152     return this->compareUsing(other, std::greater<std::string>());
0153   }
0154 
0155   template <int I>
0156   inline bool Hash<I>::operator==(Hash<I> const& other) const {
0157     return this->compareUsing(other, std::equal_to<std::string>());
0158   }
0159 
0160   template <int I>
0161   inline bool Hash<I>::operator!=(Hash<I> const& other) const {
0162     return this->compareUsing(other, std::not_equal_to<std::string>());
0163   }
0164 
0165   template <int I>
0166   inline std::ostream& Hash<I>::print(std::ostream& os) const {
0167     return hash_detail::print_(os, hash_);
0168   }
0169 
0170   template <int I>
0171   inline void Hash<I>::toString(std::string& result) const {
0172     hash_detail::toString_(result, hash_);
0173   }
0174 
0175   template <int I>
0176   inline void Hash<I>::toDigest(cms::Digest& digest) const {
0177     hash_detail::toDigest_(digest, hash_);
0178   }
0179 
0180   template <int I>
0181   inline void Hash<I>::swap(Hash<I>& other) {
0182     hash_.swap(other.hash_);
0183   }
0184 
0185   template <int I>
0186   inline typename Hash<I>::value_type Hash<I>::compactForm() const {
0187     return hash_detail::compactForm_(hash_);
0188   }
0189 
0190   template <int I>
0191   inline size_t Hash<I>::smallHash() const {
0192     return hash_detail::smallHash_(hash_);
0193   }
0194 
0195   // Note: this template is not declared 'inline' because of the
0196   // switch statement.
0197 
0198   template <int I>
0199   inline bool Hash<I>::isCompactForm() const {
0200     return hash_detail::isCompactForm_(hash_);
0201   }
0202 
0203   // Free swap function
0204   template <int I>
0205   inline void swap(Hash<I>& a, Hash<I>& b) {
0206     a.swap(b);
0207   }
0208 
0209   template <int I>
0210   inline std::ostream& operator<<(std::ostream& os, Hash<I> const& h) {
0211     return h.print(os);
0212   }
0213 
0214 }  // namespace edm
0215 #endif