1 /*
2  * Copyright (C) 2015 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_LOCALE_LIST_CACHE_H
18 #define MINIKIN_LOCALE_LIST_CACHE_H
19 
20 #include <mutex>
21 #include <unordered_map>
22 
23 #include "minikin/Buffer.h"
24 #include "minikin/Macros.h"
25 
26 #include "Locale.h"
27 
28 namespace minikin {
29 
30 class LocaleListCache {
31 public:
32     // A special ID for the invalid locale list.
33     const static uint32_t kInvalidListId = (uint32_t)(-1);
34 
35     // Returns the locale list ID for the given string representation of LocaleList.
getId(const std::string & locales)36     static inline uint32_t getId(const std::string& locales) {
37         return getInstance().getIdInternal(locales);
38     }
39 
40     // Returns the locale list ID for the LocaleList serialized in the buffer.
readFrom(BufferReader * reader)41     static inline uint32_t readFrom(BufferReader* reader) {
42         return getInstance().readFromInternal(reader);
43     }
44 
writeTo(BufferWriter * writer,uint32_t id)45     static inline void writeTo(BufferWriter* writer, uint32_t id) {
46         return getInstance().writeToInternal(writer, id);
47     }
48 
getById(uint32_t id)49     static inline const LocaleList& getById(uint32_t id) {
50         return getInstance().getByIdInternal(id);
51     }
52 
53 private:
54     struct LocaleVectorHash {
55         size_t operator()(const std::vector<Locale>& locales) const;
56     };
57 
58     LocaleListCache();  // Singleton
~LocaleListCache()59     ~LocaleListCache() {}
60 
61     uint32_t getIdInternal(const std::string& locales);
62     uint32_t getIdInternal(std::vector<Locale>&& locales) EXCLUSIVE_LOCKS_REQUIRED(mMutex);
63     uint32_t readFromInternal(BufferReader* reader);
64     void writeToInternal(BufferWriter* writer, uint32_t id);
65     const LocaleList& getByIdInternal(uint32_t id);
66 
67     // Caller should acquire a lock before calling the method.
getInstance()68     static LocaleListCache& getInstance() {
69         static LocaleListCache instance;
70         return instance;
71     }
72 
73     std::vector<LocaleList> mLocaleLists GUARDED_BY(mMutex);
74 
75     // A map from the list of locale identifier to the ID.
76     //
77     // Locale's operator==() doesn't have reflexivity for unsupported locales,
78     // but it won't cause problems because we never store unsupported locales in
79     // LocaleListCache. See parseLocaleList() in LocaleListCache.cpp.
80     std::unordered_map<std::vector<Locale>, uint32_t, LocaleVectorHash> mLocaleListLookupTable
81             GUARDED_BY(mMutex);
82 
83     // A cache map from the string representation of the font locale list to the ID.
84     // This is a mere cache over mLocaleListLookupTable. Some LocaleList objects may be in
85     // mLocaleListLookupTable even if they are not in mLocaleListStringCache.
86     std::unordered_map<std::string, uint32_t> mLocaleListStringCache GUARDED_BY(mMutex);
87 
88     std::mutex mMutex;
89 };
90 
91 }  // namespace minikin
92 
93 #endif  // MINIKIN_LOCALE_LIST_CACHE_H
94