1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#ifndef SkChecksum_DEFINED
9cb93a386Sopenharmony_ci#define SkChecksum_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkString.h"
12cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
13cb93a386Sopenharmony_ci#include "include/private/SkNoncopyable.h"
14cb93a386Sopenharmony_ci#include "include/private/SkOpts_spi.h"
15cb93a386Sopenharmony_ci#include "include/private/SkTLogic.h"
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_ciclass SkChecksum : SkNoncopyable {
18cb93a386Sopenharmony_cipublic:
19cb93a386Sopenharmony_ci    /**
20cb93a386Sopenharmony_ci     * uint32_t -> uint32_t hash, useful for when you're about to trucate this hash but you
21cb93a386Sopenharmony_ci     * suspect its low bits aren't well mixed.
22cb93a386Sopenharmony_ci     *
23cb93a386Sopenharmony_ci     * This is the Murmur3 finalizer.
24cb93a386Sopenharmony_ci     */
25cb93a386Sopenharmony_ci    static uint32_t Mix(uint32_t hash) {
26cb93a386Sopenharmony_ci        hash ^= hash >> 16;
27cb93a386Sopenharmony_ci        hash *= 0x85ebca6b;
28cb93a386Sopenharmony_ci        hash ^= hash >> 13;
29cb93a386Sopenharmony_ci        hash *= 0xc2b2ae35;
30cb93a386Sopenharmony_ci        hash ^= hash >> 16;
31cb93a386Sopenharmony_ci        return hash;
32cb93a386Sopenharmony_ci    }
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci    /**
35cb93a386Sopenharmony_ci     * uint32_t -> uint32_t hash, useful for when you're about to trucate this hash but you
36cb93a386Sopenharmony_ci     * suspect its low bits aren't well mixed.
37cb93a386Sopenharmony_ci     *
38cb93a386Sopenharmony_ci     *  This version is 2-lines cheaper than Mix, but seems to be sufficient for the font cache.
39cb93a386Sopenharmony_ci     */
40cb93a386Sopenharmony_ci    static uint32_t CheapMix(uint32_t hash) {
41cb93a386Sopenharmony_ci        hash ^= hash >> 16;
42cb93a386Sopenharmony_ci        hash *= 0x85ebca6b;
43cb93a386Sopenharmony_ci        hash ^= hash >> 16;
44cb93a386Sopenharmony_ci        return hash;
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci};
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci// SkGoodHash should usually be your first choice in hashing data.
49cb93a386Sopenharmony_ci// It should be both reasonably fast and high quality.
50cb93a386Sopenharmony_cistruct SkGoodHash {
51cb93a386Sopenharmony_ci    template <typename K>
52cb93a386Sopenharmony_ci    std::enable_if_t<sizeof(K) == 4, uint32_t> operator()(const K& k) const {
53cb93a386Sopenharmony_ci        return SkChecksum::Mix(*(const uint32_t*)&k);
54cb93a386Sopenharmony_ci    }
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci    template <typename K>
57cb93a386Sopenharmony_ci    std::enable_if_t<sizeof(K) != 4, uint32_t> operator()(const K& k) const {
58cb93a386Sopenharmony_ci        return SkOpts::hash_fn(&k, sizeof(K), 0);
59cb93a386Sopenharmony_ci    }
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci    uint32_t operator()(const SkString& k) const {
62cb93a386Sopenharmony_ci        return SkOpts::hash_fn(k.c_str(), k.size(), 0);
63cb93a386Sopenharmony_ci    }
64cb93a386Sopenharmony_ci};
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci#endif
67