Home | History | Annotate | Download | only in aapt2
      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 AAPT_STRING_POOL_H
     18 #define AAPT_STRING_POOL_H
     19 
     20 #include <functional>
     21 #include <memory>
     22 #include <string>
     23 #include <unordered_map>
     24 #include <vector>
     25 
     26 #include "android-base/macros.h"
     27 #include "androidfw/StringPiece.h"
     28 
     29 #include "ConfigDescription.h"
     30 #include "util/BigBuffer.h"
     31 
     32 namespace aapt {
     33 
     34 struct Span {
     35   std::string name;
     36   uint32_t first_char;
     37   uint32_t last_char;
     38 };
     39 
     40 struct StyleString {
     41   std::string str;
     42   std::vector<Span> spans;
     43 };
     44 
     45 // A StringPool for storing the value of String and StyledString resources.
     46 // Styles and Strings are stored separately, since the runtime variant of this
     47 // class -- ResStringPool -- requires that styled strings *always* appear first, since their
     48 // style data is stored as an array indexed by the same indices as the main string pool array.
     49 // Otherwise, the style data array would have to be sparse and take up more space.
     50 class StringPool {
     51  public:
     52   using size_type = size_t;
     53 
     54   class Context {
     55    public:
     56     enum : uint32_t {
     57       kHighPriority = 1u,
     58       kNormalPriority = 0x7fffffffu,
     59       kLowPriority = 0xffffffffu,
     60     };
     61     uint32_t priority = kNormalPriority;
     62     ConfigDescription config;
     63 
     64     Context() = default;
     65     Context(uint32_t p, const ConfigDescription& c) : priority(p), config(c) {}
     66     explicit Context(uint32_t p) : priority(p) {}
     67     explicit Context(const ConfigDescription& c) : priority(kNormalPriority), config(c) {
     68     }
     69   };
     70 
     71   class Entry;
     72 
     73   class Ref {
     74    public:
     75     Ref();
     76     Ref(const Ref&);
     77     ~Ref();
     78 
     79     Ref& operator=(const Ref& rhs);
     80     bool operator==(const Ref& rhs) const;
     81     bool operator!=(const Ref& rhs) const;
     82     const std::string* operator->() const;
     83     const std::string& operator*() const;
     84 
     85     size_t index() const;
     86     const Context& GetContext() const;
     87 
     88    private:
     89     friend class StringPool;
     90 
     91     explicit Ref(Entry* entry);
     92 
     93     Entry* entry_;
     94   };
     95 
     96   class StyleEntry;
     97 
     98   class StyleRef {
     99    public:
    100     StyleRef();
    101     StyleRef(const StyleRef&);
    102     ~StyleRef();
    103 
    104     StyleRef& operator=(const StyleRef& rhs);
    105     bool operator==(const StyleRef& rhs) const;
    106     bool operator!=(const StyleRef& rhs) const;
    107     const StyleEntry* operator->() const;
    108     const StyleEntry& operator*() const;
    109 
    110     size_t index() const;
    111     const Context& GetContext() const;
    112 
    113    private:
    114     friend class StringPool;
    115 
    116     explicit StyleRef(StyleEntry* entry);
    117 
    118     StyleEntry* entry_;
    119   };
    120 
    121   class Entry {
    122    public:
    123     std::string value;
    124     Context context;
    125 
    126    private:
    127     friend class StringPool;
    128     friend class Ref;
    129 
    130     size_t index_;
    131     int ref_;
    132     const StringPool* pool_;
    133   };
    134 
    135   struct Span {
    136     Ref name;
    137     uint32_t first_char;
    138     uint32_t last_char;
    139   };
    140 
    141   class StyleEntry {
    142    public:
    143     std::string value;
    144     Context context;
    145     std::vector<Span> spans;
    146 
    147    private:
    148     friend class StringPool;
    149     friend class StyleRef;
    150 
    151     size_t index_;
    152     int ref_;
    153   };
    154 
    155   static bool FlattenUtf8(BigBuffer* out, const StringPool& pool);
    156   static bool FlattenUtf16(BigBuffer* out, const StringPool& pool);
    157 
    158   StringPool() = default;
    159   StringPool(StringPool&&) = default;
    160   StringPool& operator=(StringPool&&) = default;
    161 
    162   // Adds a string to the pool, unless it already exists. Returns a reference to the string in the
    163   // pool.
    164   Ref MakeRef(const android::StringPiece& str);
    165 
    166   // Adds a string to the pool, unless it already exists, with a context object that can be used
    167   // when sorting the string pool. Returns a reference to the string in the pool.
    168   Ref MakeRef(const android::StringPiece& str, const Context& context);
    169 
    170   // Adds a string from another string pool. Returns a reference to the string in the string pool.
    171   Ref MakeRef(const Ref& ref);
    172 
    173   // Adds a style to the string pool and returns a reference to it.
    174   StyleRef MakeRef(const StyleString& str);
    175 
    176   // Adds a style to the string pool with a context object that can be used when sorting the string
    177   // pool. Returns a reference to the style in the string pool.
    178   StyleRef MakeRef(const StyleString& str, const Context& context);
    179 
    180   // Adds a style from another string pool. Returns a reference to the style in the string pool.
    181   StyleRef MakeRef(const StyleRef& ref);
    182 
    183   // Moves pool into this one without coalescing strings. When this function returns, pool will be
    184   // empty.
    185   void Merge(StringPool&& pool);
    186 
    187   inline const std::vector<std::unique_ptr<Entry>>& strings() const {
    188     return strings_;
    189   }
    190 
    191   // Returns the number of strings in the table.
    192   inline size_t size() const {
    193     return styles_.size() + strings_.size();
    194   }
    195 
    196   // Reserves space for strings and styles as an optimization.
    197   void HintWillAdd(size_t string_count, size_t style_count);
    198 
    199   // Sorts the strings according to their Context using some comparison function.
    200   // Equal Contexts are further sorted by string value, lexicographically.
    201   // If no comparison function is provided, values are only sorted lexicographically.
    202   void Sort(const std::function<int(const Context&, const Context&)>& cmp = nullptr);
    203 
    204   // Removes any strings that have no references.
    205   void Prune();
    206 
    207  private:
    208   DISALLOW_COPY_AND_ASSIGN(StringPool);
    209 
    210   static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8);
    211 
    212   Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique);
    213   void ReAssignIndices();
    214 
    215   std::vector<std::unique_ptr<Entry>> strings_;
    216   std::vector<std::unique_ptr<StyleEntry>> styles_;
    217   std::unordered_multimap<android::StringPiece, Entry*> indexed_strings_;
    218 };
    219 
    220 }  // namespace aapt
    221 
    222 #endif  // AAPT_STRING_POOL_H
    223