1 /*
2 * Copyright (C) 2014 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 #include "Rule.h"
18
19 #include <utils/String8.h>
20
21 using namespace android;
22
23 namespace split {
24
indentStr(String8 & str,int indent)25 inline static void indentStr(String8& str, int indent) {
26 while (indent > 0) {
27 str.append(" ");
28 indent--;
29 }
30 }
31
Rule(const Rule & rhs)32 Rule::Rule(const Rule& rhs)
33 : RefBase()
34 , op(rhs.op)
35 , key(rhs.key)
36 , negate(rhs.negate)
37 , stringArgs(rhs.stringArgs)
38 , longArgs(rhs.longArgs)
39 , subrules(rhs.subrules) {
40 }
41
toJson(int indent) const42 String8 Rule::toJson(int indent) const {
43 String8 str;
44 indentStr(str, indent);
45 str.append("{\n");
46 indent++;
47 indentStr(str, indent);
48 str.append("\"op\": \"");
49 switch (op) {
50 case ALWAYS_TRUE:
51 str.append("ALWAYS_TRUE");
52 break;
53 case GREATER_THAN:
54 str.append("GREATER_THAN");
55 break;
56 case LESS_THAN:
57 str.append("LESS_THAN");
58 break;
59 case EQUALS:
60 str.append("EQUALS");
61 break;
62 case AND_SUBRULES:
63 str.append("AND_SUBRULES");
64 break;
65 case OR_SUBRULES:
66 str.append("OR_SUBRULES");
67 break;
68 case CONTAINS_ANY:
69 str.append("CONTAINS_ANY");
70 break;
71 default:
72 str.appendFormat("%d", op);
73 break;
74 }
75 str.append("\"");
76
77 if (negate) {
78 str.append(",\n");
79 indentStr(str, indent);
80 str.append("\"negate\": true");
81 }
82
83 bool includeKey = true;
84 switch (op) {
85 case AND_SUBRULES:
86 case OR_SUBRULES:
87 includeKey = false;
88 break;
89 default:
90 break;
91 }
92
93 if (includeKey) {
94 str.append(",\n");
95 indentStr(str, indent);
96 str.append("\"property\": \"");
97 switch (key) {
98 case NONE:
99 str.append("NONE");
100 break;
101 case SDK_VERSION:
102 str.append("SDK_VERSION");
103 break;
104 case SCREEN_DENSITY:
105 str.append("SCREEN_DENSITY");
106 break;
107 case NATIVE_PLATFORM:
108 str.append("NATIVE_PLATFORM");
109 break;
110 case LANGUAGE:
111 str.append("LANGUAGE");
112 break;
113 default:
114 str.appendFormat("%d", key);
115 break;
116 }
117 str.append("\"");
118 }
119
120 if (op == AND_SUBRULES || op == OR_SUBRULES) {
121 str.append(",\n");
122 indentStr(str, indent);
123 str.append("\"subrules\": [\n");
124 const size_t subruleCount = subrules.size();
125 for (size_t i = 0; i < subruleCount; i++) {
126 str.append(subrules[i]->toJson(indent + 1));
127 if (i != subruleCount - 1) {
128 str.append(",");
129 }
130 str.append("\n");
131 }
132 indentStr(str, indent);
133 str.append("]");
134 } else {
135 switch (key) {
136 case SDK_VERSION:
137 case SCREEN_DENSITY: {
138 str.append(",\n");
139 indentStr(str, indent);
140 str.append("\"args\": [");
141 const size_t argCount = longArgs.size();
142 for (size_t i = 0; i < argCount; i++) {
143 if (i != 0) {
144 str.append(", ");
145 }
146 str.appendFormat("%d", longArgs[i]);
147 }
148 str.append("]");
149 break;
150 }
151 case LANGUAGE:
152 case NATIVE_PLATFORM: {
153 str.append(",\n");
154 indentStr(str, indent);
155 str.append("\"args\": [");
156 const size_t argCount = stringArgs.size();
157 for (size_t i = 0; i < argCount; i++) {
158 if (i != 0) {
159 str.append(", ");
160 }
161 str.append(stringArgs[i]);
162 }
163 str.append("]");
164 break;
165 }
166 default:
167 break;
168 }
169 }
170 str.append("\n");
171 indent--;
172 indentStr(str, indent);
173 str.append("}");
174 return str;
175 }
176
simplify(sp<Rule> rule)177 sp<Rule> Rule::simplify(sp<Rule> rule) {
178 if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) {
179 return rule;
180 }
181
182 Vector<sp<Rule> > newSubrules;
183 newSubrules.setCapacity(rule->subrules.size());
184 const size_t subruleCount = rule->subrules.size();
185 for (size_t i = 0; i < subruleCount; i++) {
186 sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i));
187 if (simplifiedRule != NULL) {
188 if (simplifiedRule->op == rule->op) {
189 newSubrules.appendVector(simplifiedRule->subrules);
190 } else {
191 newSubrules.add(simplifiedRule);
192 }
193 }
194 }
195
196 const size_t newSubruleCount = newSubrules.size();
197 if (newSubruleCount == 0) {
198 return NULL;
199 } else if (subruleCount == 1) {
200 return newSubrules.editTop();
201 }
202 rule->subrules = newSubrules;
203 return rule;
204 }
205
206 } // namespace split
207