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 #include <string>
22 
23 #include "minikin/FontFeature.h"
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 
update(int32_t data)40     inline Hasher& update(int32_t data) {
41         update(static_cast<uint32_t>(data));
42         return *this;
43     }
44 
update(uint64_t data)45     inline Hasher& update(uint64_t data) {
46         update(static_cast<uint32_t>(data));
47         update(static_cast<uint32_t>(data >> 32));
48         return *this;
49     }
50 
update(float data)51     inline Hasher& update(float data) {
52         union {
53             float f;
54             uint32_t i;
55         } bits;
56         bits.f = data;
57         return update(bits.i);
58     }
59 
update(const std::vector<FontFeature> & features)60     inline Hasher& update(const std::vector<FontFeature>& features) {
61         uint32_t size = features.size();
62         update(size);
63         for (const FontFeature& feature : features) {
64             update(feature);
65         }
66         return *this;
67     }
68 
update(const FontFeature & feature)69     inline Hasher& update(const FontFeature& feature) {
70         update(feature.tag);
71         update(feature.value);
72         return *this;
73     }
74 
updateShorts(const uint16_t * data,uint32_t length)75     inline Hasher& updateShorts(const uint16_t* data, uint32_t length) {
76         update(length);
77         uint32_t i;
78         for (i = 0; i < (length & -2); i += 2) {
79             update((uint32_t)data[i] | ((uint32_t)data[i + 1] << 16));
80         }
81         if (length & 1) {
82             update((uint32_t)data[i]);
83         }
84         return *this;
85     }
86 
updateString(const std::string & str)87     inline Hasher& updateString(const std::string& str) {
88         uint32_t size = str.size();
89         update(size);
90         uint32_t i;
91         for (i = 0; i < (size & -4); i += 4) {
92             update((uint32_t)str[i] | ((uint32_t)str[i + 1] << 8) | ((uint32_t)str[i + 2] << 16) |
93                    ((uint32_t)str[i + 3] << 24));
94         }
95         if (size & 3) {
96             uint32_t data = str[i];
97             data |= ((size & 3) > 1) ? ((uint32_t)str[i + 1] << 8) : 0;
98             data |= ((size & 3) > 2) ? ((uint32_t)str[i + 2] << 16) : 0;
99             update(data);
100         }
101         return *this;
102     }
103 
hash()104     IGNORE_INTEGER_OVERFLOW inline uint32_t hash() {
105         uint32_t hash = mHash;
106         hash += (hash << 3);
107         hash ^= (hash >> 11);
108         hash += (hash << 15);
109         return hash;
110     }
111 
112 private:
113     uint32_t mHash;
114 };
115 
116 }  // namespace minikin
117 
118 #endif  // MINIKIN_HASHER_H
119