gfx/skia/trunk/include/core/SkChecksum.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2012 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #ifndef SkChecksum_DEFINED
michael@0 9 #define SkChecksum_DEFINED
michael@0 10
michael@0 11 #include "SkTypes.h"
michael@0 12
michael@0 13 /**
michael@0 14 * Computes a 32bit checksum from a blob of 32bit aligned data. This is meant
michael@0 15 * to be very very fast, as it is used internally by the font cache, in
michael@0 16 * conjuction with the entire raw key. This algorithm does not generate
michael@0 17 * unique values as well as others (e.g. MD5) but it performs much faster.
michael@0 18 * Skia's use cases can survive non-unique values (since the entire key is
michael@0 19 * always available). Clients should only be used in circumstances where speed
michael@0 20 * over uniqueness is at a premium.
michael@0 21 */
michael@0 22 class SkChecksum : SkNoncopyable {
michael@0 23 private:
michael@0 24 /*
michael@0 25 * Our Rotate and Mash helpers are meant to automatically do the right
michael@0 26 * thing depending if sizeof(uintptr_t) is 4 or 8.
michael@0 27 */
michael@0 28 enum {
michael@0 29 ROTR = 17,
michael@0 30 ROTL = sizeof(uintptr_t) * 8 - ROTR,
michael@0 31 HALFBITS = sizeof(uintptr_t) * 4
michael@0 32 };
michael@0 33
michael@0 34 static inline uintptr_t Mash(uintptr_t total, uintptr_t value) {
michael@0 35 return ((total >> ROTR) | (total << ROTL)) ^ value;
michael@0 36 }
michael@0 37
michael@0 38 public:
michael@0 39
michael@0 40 /**
michael@0 41 * Calculate 32-bit Murmur hash (murmur3).
michael@0 42 * This should take 2-3x longer than SkChecksum::Compute, but is a considerably better hash.
michael@0 43 * See en.wikipedia.org/wiki/MurmurHash.
michael@0 44 *
michael@0 45 * @param data Memory address of the data block to be processed. Must be 32-bit aligned.
michael@0 46 * @param size Size of the data block in bytes. Must be a multiple of 4.
michael@0 47 * @param seed Initial hash seed. (optional)
michael@0 48 * @return hash result
michael@0 49 */
michael@0 50 static uint32_t Murmur3(const uint32_t* data, size_t bytes, uint32_t seed=0) {
michael@0 51 SkASSERT(SkIsAlign4(bytes));
michael@0 52 const size_t words = bytes/4;
michael@0 53
michael@0 54 uint32_t hash = seed;
michael@0 55 for (size_t i = 0; i < words; i++) {
michael@0 56 uint32_t k = data[i];
michael@0 57 k *= 0xcc9e2d51;
michael@0 58 k = (k << 15) | (k >> 17);
michael@0 59 k *= 0x1b873593;
michael@0 60
michael@0 61 hash ^= k;
michael@0 62 hash = (hash << 13) | (hash >> 19);
michael@0 63 hash *= 5;
michael@0 64 hash += 0xe6546b64;
michael@0 65 }
michael@0 66 hash ^= bytes;
michael@0 67 hash ^= hash >> 16;
michael@0 68 hash *= 0x85ebca6b;
michael@0 69 hash ^= hash >> 13;
michael@0 70 hash *= 0xc2b2ae35;
michael@0 71 hash ^= hash >> 16;
michael@0 72 return hash;
michael@0 73 }
michael@0 74
michael@0 75 /**
michael@0 76 * Compute a 32-bit checksum for a given data block
michael@0 77 *
michael@0 78 * WARNING: this algorithm is tuned for efficiency, not backward/forward
michael@0 79 * compatibility. It may change at any time, so a checksum generated with
michael@0 80 * one version of the Skia code may not match a checksum generated with
michael@0 81 * a different version of the Skia code.
michael@0 82 *
michael@0 83 * @param data Memory address of the data block to be processed. Must be
michael@0 84 * 32-bit aligned.
michael@0 85 * @param size Size of the data block in bytes. Must be a multiple of 4.
michael@0 86 * @return checksum result
michael@0 87 */
michael@0 88 static uint32_t Compute(const uint32_t* data, size_t size) {
michael@0 89 SkASSERT(SkIsAlign4(size));
michael@0 90
michael@0 91 /*
michael@0 92 * We want to let the compiler use 32bit or 64bit addressing and math
michael@0 93 * so we use uintptr_t as our magic type. This makes the code a little
michael@0 94 * more obscure (we can't hard-code 32 or 64 anywhere, but have to use
michael@0 95 * sizeof()).
michael@0 96 */
michael@0 97 uintptr_t result = 0;
michael@0 98 const uintptr_t* ptr = reinterpret_cast<const uintptr_t*>(data);
michael@0 99
michael@0 100 /*
michael@0 101 * count the number of quad element chunks. This takes into account
michael@0 102 * if we're on a 32bit or 64bit arch, since we use sizeof(uintptr_t)
michael@0 103 * to compute how much to shift-down the size.
michael@0 104 */
michael@0 105 size_t n4 = size / (sizeof(uintptr_t) << 2);
michael@0 106 for (size_t i = 0; i < n4; ++i) {
michael@0 107 result = Mash(result, *ptr++);
michael@0 108 result = Mash(result, *ptr++);
michael@0 109 result = Mash(result, *ptr++);
michael@0 110 result = Mash(result, *ptr++);
michael@0 111 }
michael@0 112 size &= ((sizeof(uintptr_t) << 2) - 1);
michael@0 113
michael@0 114 data = reinterpret_cast<const uint32_t*>(ptr);
michael@0 115 const uint32_t* stop = data + (size >> 2);
michael@0 116 while (data < stop) {
michael@0 117 result = Mash(result, *data++);
michael@0 118 }
michael@0 119
michael@0 120 /*
michael@0 121 * smash us down to 32bits if we were 64. Note that when uintptr_t is
michael@0 122 * 32bits, this code-path should go away, but I still got a warning
michael@0 123 * when I wrote
michael@0 124 * result ^= result >> 32;
michael@0 125 * since >>32 is undefined for 32bit ints, hence the wacky HALFBITS
michael@0 126 * define.
michael@0 127 */
michael@0 128 if (8 == sizeof(result)) {
michael@0 129 result ^= result >> HALFBITS;
michael@0 130 }
michael@0 131 return static_cast<uint32_t>(result);
michael@0 132 }
michael@0 133 };
michael@0 134
michael@0 135 #endif

mercurial