Hash

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
#ifndef DataFormats_Provenance_Hash_h
#define DataFormats_Provenance_Hash_h

#include <string>
#include <functional>

/*----------------------------------------------------------------------
  
Hash:

  Note: The call to 'fixup' in every member function is a temporary
  measure for backwards compatibility. It is necessary in every function
  because Root creates instances of the class *without* using the
  interface of the class, thus making it insufficient to assure that
  all constructors make corrected instances.

----------------------------------------------------------------------*/
namespace cms {
  class Digest;
}

namespace edm {

  namespace detail {
    // This string is the 16-byte, non-printable version.
    std::string const& InvalidHash();
  }  // namespace detail

  namespace hash_detail {
    typedef std::string value_type;
    value_type compactForm_(value_type const& hash);
    void fixup_(value_type& hash);
    bool isCompactForm_(value_type const& hash);
    bool isValid_(value_type const& hash);
    void throwIfIllFormed(value_type const& hash);
    void toString_(std::string& result, value_type const& hash);
    void toDigest_(cms::Digest& digest, value_type const& hash);
    std::ostream& print_(std::ostream& os, value_type const& hash);
    size_t smallHash_(value_type const& hash);
  }  // namespace hash_detail

  template <int I>
  class Hash {
  public:
    typedef hash_detail::value_type value_type;

    Hash();
    explicit Hash(value_type const& v);

    Hash(Hash<I> const&);
    Hash<I>& operator=(Hash<I> const& iRHS);

    Hash(Hash<I>&&) = default;
    Hash<I>& operator=(Hash<I>&&) = default;

    void reset();

    // For now, just check the most basic: a default constructed
    // ParameterSetID is not valid. This is very crude: we are
    // assuming that nobody created a ParameterSetID from an empty
    // string, nor from any string that is not a valid string
    // representation of an MD5 checksum.
    bool isValid() const;

    bool operator<(Hash<I> const& other) const;
    bool operator>(Hash<I> const& other) const;
    bool operator==(Hash<I> const& other) const;
    bool operator!=(Hash<I> const& other) const;
    std::ostream& print(std::ostream& os) const;
    void toString(std::string& result) const;
    void toDigest(cms::Digest& digest) const;
    void swap(Hash<I>& other);

    // Return the 16-byte (non-printable) string form.
    value_type compactForm() const;

    bool isCompactForm() const;

    ///returns a short hash which can be used with hashing containers
    size_t smallHash() const;

    //Used by ROOT storage
    // CMS_CLASS_VERSION(11) // This macro is not defined here, so expand it.
    static short Class_Version() { return 11; }

  private:
    /// Hexified version of data *must* contain a multiple of 2
    /// bytes. If it does not, throw an exception.
    void throwIfIllFormed() const;

    template <typename Op>
    bool compareUsing(Hash<I> const& iOther, Op op) const {
      bool meCF = hash_detail::isCompactForm_(hash_);
      bool otherCF = hash_detail::isCompactForm_(iOther.hash_);
      if (meCF == otherCF) {
        return op(this->hash_, iOther.hash_);
      }
      //copy constructor will do compact form conversion
      if (meCF) {
        Hash<I> temp(iOther);  // NOLINT(performance-unnecessary-copy-initialization)
        return op(this->hash_, temp.hash_);
      }
      Hash<I> temp(*this);
      return op(temp.hash_, iOther.hash_);
    }

    value_type hash_;
  };

  //--------------------------------------------------------------------
  //
  // Implementation details follow...
  //--------------------------------------------------------------------

  template <int I>
  inline Hash<I>::Hash() : hash_(detail::InvalidHash()) {}

  template <int I>
  inline Hash<I>::Hash(typename Hash<I>::value_type const& v) : hash_(v) {
    hash_detail::fixup_(hash_);
  }

  template <int I>
  inline Hash<I>::Hash(Hash<I> const& iOther) : hash_(iOther.hash_) {
    hash_detail::fixup_(hash_);
  }

  template <int I>
  inline Hash<I>& Hash<I>::operator=(Hash<I> const& iRHS) {
    hash_ = iRHS.hash_;
    hash_detail::fixup_(hash_);
    return *this;
  }

  template <int I>
  inline void Hash<I>::reset() {
    hash_ = detail::InvalidHash();
  }

  template <int I>
  inline bool Hash<I>::isValid() const {
    return hash_detail::isValid_(hash_);
  }

  template <int I>
  inline bool Hash<I>::operator<(Hash<I> const& other) const {
    return this->compareUsing(other, std::less<std::string>());
  }

  template <int I>
  inline bool Hash<I>::operator>(Hash<I> const& other) const {
    return this->compareUsing(other, std::greater<std::string>());
  }

  template <int I>
  inline bool Hash<I>::operator==(Hash<I> const& other) const {
    return this->compareUsing(other, std::equal_to<std::string>());
  }

  template <int I>
  inline bool Hash<I>::operator!=(Hash<I> const& other) const {
    return this->compareUsing(other, std::not_equal_to<std::string>());
  }

  template <int I>
  inline std::ostream& Hash<I>::print(std::ostream& os) const {
    return hash_detail::print_(os, hash_);
  }

  template <int I>
  inline void Hash<I>::toString(std::string& result) const {
    hash_detail::toString_(result, hash_);
  }

  template <int I>
  inline void Hash<I>::toDigest(cms::Digest& digest) const {
    hash_detail::toDigest_(digest, hash_);
  }

  template <int I>
  inline void Hash<I>::swap(Hash<I>& other) {
    hash_.swap(other.hash_);
  }

  template <int I>
  inline typename Hash<I>::value_type Hash<I>::compactForm() const {
    return hash_detail::compactForm_(hash_);
  }

  template <int I>
  inline size_t Hash<I>::smallHash() const {
    return hash_detail::smallHash_(hash_);
  }

  // Note: this template is not declared 'inline' because of the
  // switch statement.

  template <int I>
  inline bool Hash<I>::isCompactForm() const {
    return hash_detail::isCompactForm_(hash_);
  }

  // Free swap function
  template <int I>
  inline void swap(Hash<I>& a, Hash<I>& b) {
    a.swap(b);
  }

  template <int I>
  inline std::ostream& operator<<(std::ostream& os, Hash<I> const& h) {
    return h.print(os);
  }

}  // namespace edm
#endif