xref: /aosp_15_r20/frameworks/base/tools/aapt/ResourceIdCache.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker //
2*d57664e9SAndroid Build Coastguard Worker // Copyright 2012 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker //
4*d57664e9SAndroid Build Coastguard Worker // Manage a resource ID cache.
5*d57664e9SAndroid Build Coastguard Worker 
6*d57664e9SAndroid Build Coastguard Worker #define LOG_TAG "ResourceIdCache"
7*d57664e9SAndroid Build Coastguard Worker 
8*d57664e9SAndroid Build Coastguard Worker #include <utils/String16.h>
9*d57664e9SAndroid Build Coastguard Worker #include <utils/Log.h>
10*d57664e9SAndroid Build Coastguard Worker #include "ResourceIdCache.h"
11*d57664e9SAndroid Build Coastguard Worker #include <map>
12*d57664e9SAndroid Build Coastguard Worker 
13*d57664e9SAndroid Build Coastguard Worker static size_t mHits = 0;
14*d57664e9SAndroid Build Coastguard Worker static size_t mMisses = 0;
15*d57664e9SAndroid Build Coastguard Worker static size_t mCollisions = 0;
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker static const size_t MAX_CACHE_ENTRIES = 2048;
18*d57664e9SAndroid Build Coastguard Worker static const android::String16 TRUE16("1");
19*d57664e9SAndroid Build Coastguard Worker static const android::String16 FALSE16("0");
20*d57664e9SAndroid Build Coastguard Worker 
21*d57664e9SAndroid Build Coastguard Worker struct CacheEntry {
22*d57664e9SAndroid Build Coastguard Worker     // concatenation of the relevant strings into a single instance
23*d57664e9SAndroid Build Coastguard Worker     android::String16 hashedName;
24*d57664e9SAndroid Build Coastguard Worker     uint32_t id;
25*d57664e9SAndroid Build Coastguard Worker 
CacheEntryCacheEntry26*d57664e9SAndroid Build Coastguard Worker     CacheEntry() {}
CacheEntryCacheEntry27*d57664e9SAndroid Build Coastguard Worker     CacheEntry(const android::String16& name, uint32_t resId) : hashedName(name), id(resId) { }
28*d57664e9SAndroid Build Coastguard Worker };
29*d57664e9SAndroid Build Coastguard Worker 
30*d57664e9SAndroid Build Coastguard Worker static std::map< uint32_t, CacheEntry > mIdMap;
31*d57664e9SAndroid Build Coastguard Worker 
32*d57664e9SAndroid Build Coastguard Worker 
33*d57664e9SAndroid Build Coastguard Worker // djb2; reasonable choice for strings when collisions aren't particularly important
hashround(uint32_t hash,int c)34*d57664e9SAndroid Build Coastguard Worker static inline uint32_t hashround(uint32_t hash, int c) {
35*d57664e9SAndroid Build Coastguard Worker     return ((hash << 5) + hash) + c;    /* hash * 33 + c */
36*d57664e9SAndroid Build Coastguard Worker }
37*d57664e9SAndroid Build Coastguard Worker 
hash(const android::String16 & hashableString)38*d57664e9SAndroid Build Coastguard Worker static uint32_t hash(const android::String16& hashableString) {
39*d57664e9SAndroid Build Coastguard Worker     uint32_t hash = 5381;
40*d57664e9SAndroid Build Coastguard Worker     const char16_t* str = hashableString.c_str();
41*d57664e9SAndroid Build Coastguard Worker     while (int c = *str++) hash = hashround(hash, c);
42*d57664e9SAndroid Build Coastguard Worker     return hash;
43*d57664e9SAndroid Build Coastguard Worker }
44*d57664e9SAndroid Build Coastguard Worker 
45*d57664e9SAndroid Build Coastguard Worker namespace android {
46*d57664e9SAndroid Build Coastguard Worker 
makeHashableName(const android::String16 & package,const android::String16 & type,const android::String16 & name,bool onlyPublic)47*d57664e9SAndroid Build Coastguard Worker static inline String16 makeHashableName(const android::String16& package,
48*d57664e9SAndroid Build Coastguard Worker         const android::String16& type,
49*d57664e9SAndroid Build Coastguard Worker         const android::String16& name,
50*d57664e9SAndroid Build Coastguard Worker         bool onlyPublic) {
51*d57664e9SAndroid Build Coastguard Worker     String16 hashable = String16(name);
52*d57664e9SAndroid Build Coastguard Worker     hashable += type;
53*d57664e9SAndroid Build Coastguard Worker     hashable += package;
54*d57664e9SAndroid Build Coastguard Worker     hashable += (onlyPublic ? TRUE16 : FALSE16);
55*d57664e9SAndroid Build Coastguard Worker     return hashable;
56*d57664e9SAndroid Build Coastguard Worker }
57*d57664e9SAndroid Build Coastguard Worker 
lookup(const android::String16 & package,const android::String16 & type,const android::String16 & name,bool onlyPublic)58*d57664e9SAndroid Build Coastguard Worker uint32_t ResourceIdCache::lookup(const android::String16& package,
59*d57664e9SAndroid Build Coastguard Worker         const android::String16& type,
60*d57664e9SAndroid Build Coastguard Worker         const android::String16& name,
61*d57664e9SAndroid Build Coastguard Worker         bool onlyPublic) {
62*d57664e9SAndroid Build Coastguard Worker     const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
63*d57664e9SAndroid Build Coastguard Worker     const uint32_t hashcode = hash(hashedName);
64*d57664e9SAndroid Build Coastguard Worker     std::map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode);
65*d57664e9SAndroid Build Coastguard Worker     if (item == mIdMap.end()) {
66*d57664e9SAndroid Build Coastguard Worker         // cache miss
67*d57664e9SAndroid Build Coastguard Worker         mMisses++;
68*d57664e9SAndroid Build Coastguard Worker         return 0;
69*d57664e9SAndroid Build Coastguard Worker     }
70*d57664e9SAndroid Build Coastguard Worker 
71*d57664e9SAndroid Build Coastguard Worker     // legit match?
72*d57664e9SAndroid Build Coastguard Worker     if (hashedName == (*item).second.hashedName) {
73*d57664e9SAndroid Build Coastguard Worker         mHits++;
74*d57664e9SAndroid Build Coastguard Worker         return (*item).second.id;
75*d57664e9SAndroid Build Coastguard Worker     }
76*d57664e9SAndroid Build Coastguard Worker 
77*d57664e9SAndroid Build Coastguard Worker     // collision
78*d57664e9SAndroid Build Coastguard Worker     mCollisions++;
79*d57664e9SAndroid Build Coastguard Worker     mIdMap.erase(hashcode);
80*d57664e9SAndroid Build Coastguard Worker     return 0;
81*d57664e9SAndroid Build Coastguard Worker }
82*d57664e9SAndroid Build Coastguard Worker 
83*d57664e9SAndroid Build Coastguard Worker // returns the resource ID being stored, for callsite convenience
store(const android::String16 & package,const android::String16 & type,const android::String16 & name,bool onlyPublic,uint32_t resId)84*d57664e9SAndroid Build Coastguard Worker uint32_t ResourceIdCache::store(const android::String16& package,
85*d57664e9SAndroid Build Coastguard Worker         const android::String16& type,
86*d57664e9SAndroid Build Coastguard Worker         const android::String16& name,
87*d57664e9SAndroid Build Coastguard Worker         bool onlyPublic,
88*d57664e9SAndroid Build Coastguard Worker         uint32_t resId) {
89*d57664e9SAndroid Build Coastguard Worker     if (mIdMap.size() < MAX_CACHE_ENTRIES) {
90*d57664e9SAndroid Build Coastguard Worker         const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
91*d57664e9SAndroid Build Coastguard Worker         const uint32_t hashcode = hash(hashedName);
92*d57664e9SAndroid Build Coastguard Worker         mIdMap[hashcode] = CacheEntry(hashedName, resId);
93*d57664e9SAndroid Build Coastguard Worker     }
94*d57664e9SAndroid Build Coastguard Worker     return resId;
95*d57664e9SAndroid Build Coastguard Worker }
96*d57664e9SAndroid Build Coastguard Worker 
dump()97*d57664e9SAndroid Build Coastguard Worker void ResourceIdCache::dump() {
98*d57664e9SAndroid Build Coastguard Worker     printf("ResourceIdCache dump:\n");
99*d57664e9SAndroid Build Coastguard Worker     printf("Size: %zd\n", mIdMap.size());
100*d57664e9SAndroid Build Coastguard Worker     printf("Hits:   %zd\n", mHits);
101*d57664e9SAndroid Build Coastguard Worker     printf("Misses: %zd\n", mMisses);
102*d57664e9SAndroid Build Coastguard Worker     printf("(Collisions: %zd)\n", mCollisions);
103*d57664e9SAndroid Build Coastguard Worker }
104*d57664e9SAndroid Build Coastguard Worker 
105*d57664e9SAndroid Build Coastguard Worker }
106