16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/*
26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License.
66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at
76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software
116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and
146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License.
156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#ifndef AAPT_CONFIG_DESCRIPTION_H
186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#define AAPT_CONFIG_DESCRIPTION_H
196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <ostream>
216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
22ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "androidfw/ResourceTypes.h"
23d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h"
24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt {
266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
27bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski/*
28bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski * Subclass of ResTable_config that adds convenient
29bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski * initialization and comparison methods.
30bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski */
316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskistruct ConfigDescription : public android::ResTable_config {
32bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  /**
33bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * Returns an immutable default config.
34bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   */
35ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  static const ConfigDescription& DefaultConfig();
36cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
37bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  /*
38bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * Parse a string of the form 'fr-sw600dp-land' and fill in the
39bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * given ResTable_config with resulting configuration parameters.
40bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   *
41bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * The resulting configuration has the appropriate sdkVersion defined
42bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * for backwards compatibility.
43bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   */
44d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski  static bool Parse(const android::StringPiece& str, ConfigDescription* out = nullptr);
45cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
46bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  /**
47bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * If the configuration uses an axis that was added after
48bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * the original Android release, make sure the SDK version
49bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * is set accordingly.
50bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   */
51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  static void ApplyVersionForCompatibility(ConfigDescription* config);
52cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
53cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ConfigDescription();
54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ConfigDescription(const android::ResTable_config& o);  // NOLINT(implicit)
55cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ConfigDescription(const ConfigDescription& o);
56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ConfigDescription(ConfigDescription&& o);
57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
58cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ConfigDescription& operator=(const android::ResTable_config& o);
59cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ConfigDescription& operator=(const ConfigDescription& o);
60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ConfigDescription& operator=(ConfigDescription&& o);
61cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ConfigDescription CopyWithoutSdkVersion() const;
63cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
64b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski  // Returns the BCP-47 language tag of this configuration's locale.
65b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski  std::string GetBcp47LanguageTag(bool canonicalize = false) const;
66b58c3ef023acf3851e4a0557d04d65d52835d2dfAdam Lesinski
6793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  std::string to_string() const;
6893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
69bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  /**
70bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * A configuration X dominates another configuration Y, if X has at least the
71bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * precedence of Y and X is strictly more general than Y: for any type defined
72bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * by X, the same type is defined by Y with a value equal to or, in the case
73bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * of ranges, more specific than that of X.
74bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   *
75bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * For example, the configuration 'en-w800dp' dominates 'en-rGB-w1024dp'. It
76bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * does not dominate 'fr', 'en-w720dp', or 'mcc001-en-w800dp'.
77bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   */
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool Dominates(const ConfigDescription& o) const;
79cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
80bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  /**
81bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * Returns true if this configuration defines a more important configuration
82bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * parameter than o. For example, "en" has higher precedence than "v23",
83bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * whereas "en" has the same precedence as "en-v23".
84bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   */
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool HasHigherPrecedenceThan(const ConfigDescription& o) const;
86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
87bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  /**
88bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * A configuration conflicts with another configuration if both
89bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * configurations define an incompatible configuration parameter. An
90bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * incompatible configuration parameter is a non-range, non-density parameter
91bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * that is defined in both configurations as a different, non-default value.
92bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   */
93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool ConflictsWith(const ConfigDescription& o) const;
94cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
95bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  /**
96bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * A configuration is compatible with another configuration if both
97bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * configurations can match a common concrete device configuration and are
98bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * unrelated by domination. For example, land-v11 conflicts with port-v21
99bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   * but is compatible with v21 (both land-v11 and v21 would match en-land-v23).
100bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski   */
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool IsCompatibleWith(const ConfigDescription& o) const;
102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MatchWithDensity(const ConfigDescription& o) const;
104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool operator<(const ConfigDescription& o) const;
106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool operator<=(const ConfigDescription& o) const;
107cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool operator==(const ConfigDescription& o) const;
108cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool operator!=(const ConfigDescription& o) const;
109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool operator>=(const ConfigDescription& o) const;
110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool operator>(const ConfigDescription& o) const;
1116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski};
1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ConfigDescription::ConfigDescription() {
114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  memset(this, 0, sizeof(*this));
115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size = sizeof(android::ResTable_config);
1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ConfigDescription::ConfigDescription(const android::ResTable_config& o) {
119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  *static_cast<android::ResTable_config*>(this) = o;
120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size = sizeof(android::ResTable_config);
1216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ConfigDescription::ConfigDescription(const ConfigDescription& o) {
124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  *static_cast<android::ResTable_config*>(this) = o;
1256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ConfigDescription::ConfigDescription(ConfigDescription&& o) {
128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  *this = o;
1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
131bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinskiinline ConfigDescription& ConfigDescription::operator=(
132bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski    const android::ResTable_config& o) {
133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  *static_cast<android::ResTable_config*>(this) = o;
134cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  size = sizeof(android::ResTable_config);
135cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return *this;
1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
138bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinskiinline ConfigDescription& ConfigDescription::operator=(
139bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski    const ConfigDescription& o) {
140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  *static_cast<android::ResTable_config*>(this) = o;
141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return *this;
1426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) {
145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  *this = o;
146cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return *this;
1476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
149bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinskiinline bool ConfigDescription::MatchWithDensity(
150bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski    const ConfigDescription& o) const {
151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return match(o) && (density == 0 || density == o.density);
15277788eb4cf0c5dba0f7370192e40364fe853050aAlexandria Cornwall}
15377788eb4cf0c5dba0f7370192e40364fe853050aAlexandria Cornwall
1546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool ConfigDescription::operator<(const ConfigDescription& o) const {
155cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return compare(o) < 0;
1566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool ConfigDescription::operator<=(const ConfigDescription& o) const {
159cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return compare(o) <= 0;
1606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool ConfigDescription::operator==(const ConfigDescription& o) const {
163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return compare(o) == 0;
1646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool ConfigDescription::operator!=(const ConfigDescription& o) const {
167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return compare(o) != 0;
1686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool ConfigDescription::operator>=(const ConfigDescription& o) const {
171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return compare(o) >= 0;
1726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool ConfigDescription::operator>(const ConfigDescription& o) const {
175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return compare(o) > 0;
1766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
178bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinskiinline ::std::ostream& operator<<(::std::ostream& out,
179bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski                                  const ConfigDescription& o) {
180bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski  return out << o.toString().string();
181bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski}
182bb94f32a0042c8e2ab3d6e0de1b693713d2a6eabAdam Lesinski
183cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
1846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
185cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#endif  // AAPT_CONFIG_DESCRIPTION_H
186