xref: /aosp_15_r20/frameworks/minikin/include/minikin/Hasher.h (revision 834a2baab5fdfc28e9a428ee87c7ea8f6a06a53d)
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/FontVariation.h"
25 #include "minikin/Macros.h"
26 #include "minikin/SortedPackedVector.h"
27 
28 namespace minikin {
29 
30 // Provides a Jenkins hash implementation.
31 class Hasher {
32 public:
Hasher()33     Hasher() : mHash(0u) {}
34 
update(uint32_t data)35     IGNORE_INTEGER_OVERFLOW inline Hasher& update(uint32_t data) {
36         mHash += data;
37         mHash += (mHash << 10);
38         mHash ^= (mHash >> 6);
39         return *this;
40     }
41 
update(int32_t data)42     inline Hasher& update(int32_t data) {
43         update(static_cast<uint32_t>(data));
44         return *this;
45     }
46 
update(uint64_t data)47     inline Hasher& update(uint64_t data) {
48         update(static_cast<uint32_t>(data));
49         update(static_cast<uint32_t>(data >> 32));
50         return *this;
51     }
52 
update(float data)53     inline Hasher& update(float data) {
54         union {
55             float f;
56             uint32_t i;
57         } bits;
58         bits.f = data;
59         return update(bits.i);
60     }
61 
update(const std::vector<FontFeature> & features)62     inline Hasher& update(const std::vector<FontFeature>& features) {
63         uint32_t size = features.size();
64         update(size);
65         for (const FontFeature& feature : features) {
66             update(feature);
67         }
68         return *this;
69     }
70 
update(const FontFeature & feature)71     inline Hasher& update(const FontFeature& feature) {
72         update(feature.tag);
73         update(feature.value);
74         return *this;
75     }
76 
update(const VariationSettings & vars)77     inline Hasher& update(const VariationSettings& vars) {
78         update(vars.size());
79         for (const FontVariation& var : vars) {
80             update(var.axisTag);
81             update(var.value);
82         }
83         return *this;
84     }
85 
86     template <typename V>
updatePackedVector(const V & vec)87     inline Hasher& updatePackedVector(const V& vec) {
88         using T = typename V::value_type;
89         for (const T& p : vec) {
90             update(p);
91         }
92         return *this;
93     }
94 
updateShorts(const uint16_t * data,uint32_t length)95     inline Hasher& updateShorts(const uint16_t* data, uint32_t length) {
96         update(length);
97         uint32_t i;
98         for (i = 0; i < (length & -2); i += 2) {
99             update((uint32_t)data[i] | ((uint32_t)data[i + 1] << 16));
100         }
101         if (length & 1) {
102             update((uint32_t)data[i]);
103         }
104         return *this;
105     }
106 
updateString(const std::string & str)107     inline Hasher& updateString(const std::string& str) {
108         uint32_t size = str.size();
109         update(size);
110         uint32_t i;
111         for (i = 0; i < (size & -4); i += 4) {
112             update((uint32_t)str[i] | ((uint32_t)str[i + 1] << 8) | ((uint32_t)str[i + 2] << 16) |
113                    ((uint32_t)str[i + 3] << 24));
114         }
115         if (size & 3) {
116             uint32_t data = str[i];
117             data |= ((size & 3) > 1) ? ((uint32_t)str[i + 1] << 8) : 0;
118             data |= ((size & 3) > 2) ? ((uint32_t)str[i + 2] << 16) : 0;
119             update(data);
120         }
121         return *this;
122     }
123 
update(const FontVariation & var)124     inline Hasher& update(const FontVariation& var) {
125         update(static_cast<uint32_t>(var.axisTag));
126         update(static_cast<float>(var.value));
127         return *this;
128     }
129 
130     template <typename T, size_t ARRAYSIZE>
update(const SortedPackedVector<T,ARRAYSIZE> & vec)131     inline Hasher& update(const SortedPackedVector<T, ARRAYSIZE>& vec) {
132         uint32_t size = vec.size();
133         update(size);
134         for (uint32_t i = 0; i < size; ++i) {
135             update(vec[i]);
136         }
137         return *this;
138     }
139 
hash()140     IGNORE_INTEGER_OVERFLOW inline uint32_t hash() {
141         uint32_t hash = mHash;
142         hash += (hash << 3);
143         hash ^= (hash >> 11);
144         hash += (hash << 15);
145         return hash;
146     }
147 
148 #ifdef __APPLE__
update(uintptr_t data)149     inline Hasher& update(uintptr_t data) {
150         update(static_cast<uint32_t>(data));
151         if (sizeof(uintptr_t) > sizeof(uint32_t)) {
152             update(static_cast<uint32_t>(data >> 32));
153         }
154         return *this;
155     }
156 #endif
157 
158 private:
159     uint32_t mHash;
160 };
161 
162 }  // namespace minikin
163 
164 #endif  // MINIKIN_HASHER_H
165