Home | History | Annotate | Download | only in lib
      1 // Copyright 2016 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_
      7 
      8 #include <cstring>
      9 #include <functional>
     10 #include <type_traits>
     11 #include <vector>
     12 
     13 #include "base/optional.h"
     14 #include "mojo/public/cpp/bindings/lib/template_util.h"
     15 
     16 namespace mojo {
     17 namespace internal {
     18 
     19 template <typename T>
     20 size_t HashCombine(size_t seed, const T& value) {
     21   // Based on proposal in:
     22   // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
     23   return seed ^ (std::hash<T>()(value) + (seed << 6) + (seed >> 2));
     24 }
     25 
     26 template <typename T>
     27 struct HasHashMethod {
     28   template <typename U>
     29   static char Test(decltype(&U::Hash));
     30   template <typename U>
     31   static int Test(...);
     32   static const bool value = sizeof(Test<T>(0)) == sizeof(char);
     33 
     34  private:
     35   EnsureTypeIsComplete<T> check_t_;
     36 };
     37 
     38 template <typename T, bool has_hash_method = HasHashMethod<T>::value>
     39 struct HashTraits;
     40 
     41 template <typename T>
     42 size_t Hash(size_t seed, const T& value);
     43 
     44 template <typename T>
     45 struct HashTraits<T, true> {
     46   static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); }
     47 };
     48 
     49 template <typename T>
     50 struct HashTraits<T, false> {
     51   static size_t Hash(size_t seed, const T& value) {
     52     return HashCombine(seed, value);
     53   }
     54 };
     55 
     56 template <typename T>
     57 struct HashTraits<std::vector<T>, false> {
     58   static size_t Hash(size_t seed, const std::vector<T>& value) {
     59     for (const auto& element : value) {
     60       seed = HashCombine(seed, element);
     61     }
     62     return seed;
     63   }
     64 };
     65 
     66 template <typename T>
     67 struct HashTraits<base::Optional<std::vector<T>>, false> {
     68   static size_t Hash(size_t seed, const base::Optional<std::vector<T>>& value) {
     69     if (!value)
     70       return HashCombine(seed, 0);
     71 
     72     return Hash(seed, *value);
     73   }
     74 };
     75 
     76 template <typename T>
     77 size_t Hash(size_t seed, const T& value) {
     78   return HashTraits<T>::Hash(seed, value);
     79 }
     80 
     81 }  // namespace internal
     82 }  // namespace mojo
     83 
     84 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_
     85