1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MINIKIN_HASHER_H
18 #define MINIKIN_HASHER_H
19 
20 #include <cstdint>
21 
22 #include <string>
23 
24 #include "minikin/Macros.h"
25 
26 namespace minikin {
27 
28 // Provides a Jenkins hash implementation.
29 class Hasher {
30 public:
Hasher()31     Hasher() : mHash(0u) {}
32 
update(uint32_t data)33     IGNORE_INTEGER_OVERFLOW inline Hasher& update(uint32_t data) {
34         mHash += data;
35         mHash += (mHash << 10);
36         mHash ^= (mHash >> 6);
37         return *this;
38     }
39 
updateShorts(const uint16_t * data,uint32_t length)40     inline Hasher& updateShorts(const uint16_t* data, uint32_t length) {
41         update(length);
42         uint32_t i;
43         for (i = 0; i < (length & -2); i += 2) {
44             update((uint32_t)data[i] | ((uint32_t)data[i + 1] << 16));
45         }
46         if (length & 1) {
47             update((uint32_t)data[i]);
48         }
49         return *this;
50     }
51 
updateString(const std::string & str)52     inline Hasher& updateString(const std::string& str) {
53         uint32_t size = str.size();
54         update(size);
55         uint32_t i;
56         for (i = 0; i < (size & -4); i += 4) {
57             update((uint32_t)str[i] | ((uint32_t)str[i + 1] << 8) | ((uint32_t)str[i + 2] << 16) |
58                    ((uint32_t)str[i + 3] << 24));
59         }
60         if (size & 3) {
61             uint32_t data = str[i];
62             data |= ((size & 3) > 1) ? ((uint32_t)str[i + 1] << 8) : 0;
63             data |= ((size & 3) > 2) ? ((uint32_t)str[i + 2] << 16) : 0;
64             update(data);
65         }
66         return *this;
67     }
68 
hash()69     IGNORE_INTEGER_OVERFLOW inline uint32_t hash() {
70         uint32_t hash = mHash;
71         hash += (hash << 3);
72         hash ^= (hash >> 11);
73         hash += (hash << 15);
74         return hash;
75     }
76 
77 private:
78     uint32_t mHash;
79 };
80 
81 }  // namespace minikin
82 
83 #endif  // MINIKIN_HASHER_H
84