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.

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

mercurial