1//
2// Copyright 2011 The Android Open Source Project
3//
4// Build resource files from raw assets.
5//
6
7#ifndef RESOURCE_FILTER_H
8#define RESOURCE_FILTER_H
9
10#include <androidfw/ResourceTypes.h>
11#include <set>
12#include <utility>
13#include <utils/Errors.h>
14#include <utils/String8.h>
15#include <utils/StrongPointer.h>
16#include <utils/Vector.h>
17
18#include "AaptAssets.h"
19#include "ConfigDescription.h"
20
21class ResourceFilter : public virtual android::RefBase {
22public:
23    virtual bool match(const android::ResTable_config& config) const = 0;
24};
25
26/**
27 * Implements logic for parsing and handling "-c" options.
28 */
29class WeakResourceFilter : public ResourceFilter {
30public:
31    WeakResourceFilter()
32        : mContainsPseudoAccented(false)
33        , mContainsPseudoBidi(false) {}
34
35    android::status_t parse(const android::String8& str);
36
37    bool match(const android::ResTable_config& config) const;
38
39    inline bool isEmpty() const {
40        return mConfigMask == 0;
41    }
42
43    inline bool containsPseudo() const {
44        return mContainsPseudoAccented;
45    }
46
47    inline bool containsPseudoBidi() const {
48        return mContainsPseudoBidi;
49    }
50
51private:
52    ConfigDescription mDefault;
53    uint32_t mConfigMask;
54    android::Vector<std::pair<ConfigDescription, uint32_t> > mConfigs;
55
56    bool mContainsPseudoAccented;
57    bool mContainsPseudoBidi;
58};
59
60/**
61 * Matches resources that have at least one of the configurations
62 * that this filter is looking for. In order to match a configuration,
63 * the resource must have the exact same configuration.
64 *
65 * This filter acts as a logical OR when matching resources.
66 *
67 * For example, if the filter is looking for resources with
68 * fr-land, de-land, or sw600dp:
69 *
70 * (PASS) fr-land
71 * (FAIL) fr
72 * (PASS) de-land
73 * (FAIL) de
74 * (FAIL) de-sw600dp
75 * (PASS) sw600dp
76 * (FAIL) sw600dp-land
77 */
78class StrongResourceFilter : public ResourceFilter {
79public:
80    StrongResourceFilter() {}
81    explicit StrongResourceFilter(const std::set<ConfigDescription>& configs)
82        : mConfigs(configs) {}
83
84    android::status_t parse(const android::String8& str);
85
86    bool match(const android::ResTable_config& config) const {
87        std::set<ConfigDescription>::const_iterator iter = mConfigs.begin();
88        for (; iter != mConfigs.end(); iter++) {
89            if (iter->compare(config) == 0) {
90                return true;
91            }
92        }
93        return false;
94    }
95
96    inline const std::set<ConfigDescription>& getConfigs() const {
97        return mConfigs;
98    }
99
100private:
101    std::set<ConfigDescription> mConfigs;
102};
103
104/**
105 * Negates the response of the target filter.
106 */
107class InverseResourceFilter : public ResourceFilter {
108public:
109    explicit InverseResourceFilter(const android::sp<ResourceFilter>& filter)
110        : mFilter(filter) {}
111
112    bool match(const android::ResTable_config& config) const {
113        return !mFilter->match(config);
114    }
115
116private:
117    const android::sp<ResourceFilter> mFilter;
118};
119
120/**
121 * A logical AND of all the added filters.
122 */
123class AndResourceFilter : public ResourceFilter {
124public:
125    void addFilter(const android::sp<ResourceFilter>& filter) {
126        mFilters.add(filter);
127    }
128
129    bool match(const android::ResTable_config& config) const {
130        const size_t N = mFilters.size();
131        for (size_t i = 0; i < N; i++) {
132            if (!mFilters[i]->match(config)) {
133                return false;
134            }
135        }
136        return true;
137    }
138
139private:
140    android::Vector<android::sp<ResourceFilter> > mFilters;
141};
142#endif
143