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