1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include "Rule.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include <utils/String8.h>
20*d57664e9SAndroid Build Coastguard Worker
21*d57664e9SAndroid Build Coastguard Worker using namespace android;
22*d57664e9SAndroid Build Coastguard Worker
23*d57664e9SAndroid Build Coastguard Worker namespace split {
24*d57664e9SAndroid Build Coastguard Worker
indentStr(String8 & str,int indent)25*d57664e9SAndroid Build Coastguard Worker inline static void indentStr(String8& str, int indent) {
26*d57664e9SAndroid Build Coastguard Worker while (indent > 0) {
27*d57664e9SAndroid Build Coastguard Worker str.append(" ");
28*d57664e9SAndroid Build Coastguard Worker indent--;
29*d57664e9SAndroid Build Coastguard Worker }
30*d57664e9SAndroid Build Coastguard Worker }
31*d57664e9SAndroid Build Coastguard Worker
Rule(const Rule & rhs)32*d57664e9SAndroid Build Coastguard Worker Rule::Rule(const Rule& rhs)
33*d57664e9SAndroid Build Coastguard Worker : RefBase()
34*d57664e9SAndroid Build Coastguard Worker , op(rhs.op)
35*d57664e9SAndroid Build Coastguard Worker , key(rhs.key)
36*d57664e9SAndroid Build Coastguard Worker , negate(rhs.negate)
37*d57664e9SAndroid Build Coastguard Worker , stringArgs(rhs.stringArgs)
38*d57664e9SAndroid Build Coastguard Worker , longArgs(rhs.longArgs)
39*d57664e9SAndroid Build Coastguard Worker , subrules(rhs.subrules) {
40*d57664e9SAndroid Build Coastguard Worker }
41*d57664e9SAndroid Build Coastguard Worker
toJson(int indent) const42*d57664e9SAndroid Build Coastguard Worker String8 Rule::toJson(int indent) const {
43*d57664e9SAndroid Build Coastguard Worker String8 str;
44*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
45*d57664e9SAndroid Build Coastguard Worker str.append("{\n");
46*d57664e9SAndroid Build Coastguard Worker indent++;
47*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
48*d57664e9SAndroid Build Coastguard Worker str.append("\"op\": \"");
49*d57664e9SAndroid Build Coastguard Worker switch (op) {
50*d57664e9SAndroid Build Coastguard Worker case ALWAYS_TRUE:
51*d57664e9SAndroid Build Coastguard Worker str.append("ALWAYS_TRUE");
52*d57664e9SAndroid Build Coastguard Worker break;
53*d57664e9SAndroid Build Coastguard Worker case GREATER_THAN:
54*d57664e9SAndroid Build Coastguard Worker str.append("GREATER_THAN");
55*d57664e9SAndroid Build Coastguard Worker break;
56*d57664e9SAndroid Build Coastguard Worker case LESS_THAN:
57*d57664e9SAndroid Build Coastguard Worker str.append("LESS_THAN");
58*d57664e9SAndroid Build Coastguard Worker break;
59*d57664e9SAndroid Build Coastguard Worker case EQUALS:
60*d57664e9SAndroid Build Coastguard Worker str.append("EQUALS");
61*d57664e9SAndroid Build Coastguard Worker break;
62*d57664e9SAndroid Build Coastguard Worker case AND_SUBRULES:
63*d57664e9SAndroid Build Coastguard Worker str.append("AND_SUBRULES");
64*d57664e9SAndroid Build Coastguard Worker break;
65*d57664e9SAndroid Build Coastguard Worker case OR_SUBRULES:
66*d57664e9SAndroid Build Coastguard Worker str.append("OR_SUBRULES");
67*d57664e9SAndroid Build Coastguard Worker break;
68*d57664e9SAndroid Build Coastguard Worker case CONTAINS_ANY:
69*d57664e9SAndroid Build Coastguard Worker str.append("CONTAINS_ANY");
70*d57664e9SAndroid Build Coastguard Worker break;
71*d57664e9SAndroid Build Coastguard Worker default:
72*d57664e9SAndroid Build Coastguard Worker str.appendFormat("%d", op);
73*d57664e9SAndroid Build Coastguard Worker break;
74*d57664e9SAndroid Build Coastguard Worker }
75*d57664e9SAndroid Build Coastguard Worker str.append("\"");
76*d57664e9SAndroid Build Coastguard Worker
77*d57664e9SAndroid Build Coastguard Worker if (negate) {
78*d57664e9SAndroid Build Coastguard Worker str.append(",\n");
79*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
80*d57664e9SAndroid Build Coastguard Worker str.append("\"negate\": true");
81*d57664e9SAndroid Build Coastguard Worker }
82*d57664e9SAndroid Build Coastguard Worker
83*d57664e9SAndroid Build Coastguard Worker bool includeKey = true;
84*d57664e9SAndroid Build Coastguard Worker switch (op) {
85*d57664e9SAndroid Build Coastguard Worker case AND_SUBRULES:
86*d57664e9SAndroid Build Coastguard Worker case OR_SUBRULES:
87*d57664e9SAndroid Build Coastguard Worker includeKey = false;
88*d57664e9SAndroid Build Coastguard Worker break;
89*d57664e9SAndroid Build Coastguard Worker default:
90*d57664e9SAndroid Build Coastguard Worker break;
91*d57664e9SAndroid Build Coastguard Worker }
92*d57664e9SAndroid Build Coastguard Worker
93*d57664e9SAndroid Build Coastguard Worker if (includeKey) {
94*d57664e9SAndroid Build Coastguard Worker str.append(",\n");
95*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
96*d57664e9SAndroid Build Coastguard Worker str.append("\"property\": \"");
97*d57664e9SAndroid Build Coastguard Worker switch (key) {
98*d57664e9SAndroid Build Coastguard Worker case NONE:
99*d57664e9SAndroid Build Coastguard Worker str.append("NONE");
100*d57664e9SAndroid Build Coastguard Worker break;
101*d57664e9SAndroid Build Coastguard Worker case SDK_VERSION:
102*d57664e9SAndroid Build Coastguard Worker str.append("SDK_VERSION");
103*d57664e9SAndroid Build Coastguard Worker break;
104*d57664e9SAndroid Build Coastguard Worker case SCREEN_DENSITY:
105*d57664e9SAndroid Build Coastguard Worker str.append("SCREEN_DENSITY");
106*d57664e9SAndroid Build Coastguard Worker break;
107*d57664e9SAndroid Build Coastguard Worker case NATIVE_PLATFORM:
108*d57664e9SAndroid Build Coastguard Worker str.append("NATIVE_PLATFORM");
109*d57664e9SAndroid Build Coastguard Worker break;
110*d57664e9SAndroid Build Coastguard Worker case LANGUAGE:
111*d57664e9SAndroid Build Coastguard Worker str.append("LANGUAGE");
112*d57664e9SAndroid Build Coastguard Worker break;
113*d57664e9SAndroid Build Coastguard Worker default:
114*d57664e9SAndroid Build Coastguard Worker str.appendFormat("%d", key);
115*d57664e9SAndroid Build Coastguard Worker break;
116*d57664e9SAndroid Build Coastguard Worker }
117*d57664e9SAndroid Build Coastguard Worker str.append("\"");
118*d57664e9SAndroid Build Coastguard Worker }
119*d57664e9SAndroid Build Coastguard Worker
120*d57664e9SAndroid Build Coastguard Worker if (op == AND_SUBRULES || op == OR_SUBRULES) {
121*d57664e9SAndroid Build Coastguard Worker str.append(",\n");
122*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
123*d57664e9SAndroid Build Coastguard Worker str.append("\"subrules\": [\n");
124*d57664e9SAndroid Build Coastguard Worker const size_t subruleCount = subrules.size();
125*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < subruleCount; i++) {
126*d57664e9SAndroid Build Coastguard Worker str.append(subrules[i]->toJson(indent + 1));
127*d57664e9SAndroid Build Coastguard Worker if (i != subruleCount - 1) {
128*d57664e9SAndroid Build Coastguard Worker str.append(",");
129*d57664e9SAndroid Build Coastguard Worker }
130*d57664e9SAndroid Build Coastguard Worker str.append("\n");
131*d57664e9SAndroid Build Coastguard Worker }
132*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
133*d57664e9SAndroid Build Coastguard Worker str.append("]");
134*d57664e9SAndroid Build Coastguard Worker } else {
135*d57664e9SAndroid Build Coastguard Worker switch (key) {
136*d57664e9SAndroid Build Coastguard Worker case SDK_VERSION:
137*d57664e9SAndroid Build Coastguard Worker case SCREEN_DENSITY: {
138*d57664e9SAndroid Build Coastguard Worker str.append(",\n");
139*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
140*d57664e9SAndroid Build Coastguard Worker str.append("\"args\": [");
141*d57664e9SAndroid Build Coastguard Worker const size_t argCount = longArgs.size();
142*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < argCount; i++) {
143*d57664e9SAndroid Build Coastguard Worker if (i != 0) {
144*d57664e9SAndroid Build Coastguard Worker str.append(", ");
145*d57664e9SAndroid Build Coastguard Worker }
146*d57664e9SAndroid Build Coastguard Worker str.appendFormat("%d", longArgs[i]);
147*d57664e9SAndroid Build Coastguard Worker }
148*d57664e9SAndroid Build Coastguard Worker str.append("]");
149*d57664e9SAndroid Build Coastguard Worker break;
150*d57664e9SAndroid Build Coastguard Worker }
151*d57664e9SAndroid Build Coastguard Worker case LANGUAGE:
152*d57664e9SAndroid Build Coastguard Worker case NATIVE_PLATFORM: {
153*d57664e9SAndroid Build Coastguard Worker str.append(",\n");
154*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
155*d57664e9SAndroid Build Coastguard Worker str.append("\"args\": [");
156*d57664e9SAndroid Build Coastguard Worker const size_t argCount = stringArgs.size();
157*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < argCount; i++) {
158*d57664e9SAndroid Build Coastguard Worker if (i != 0) {
159*d57664e9SAndroid Build Coastguard Worker str.append(", ");
160*d57664e9SAndroid Build Coastguard Worker }
161*d57664e9SAndroid Build Coastguard Worker str.append(stringArgs[i]);
162*d57664e9SAndroid Build Coastguard Worker }
163*d57664e9SAndroid Build Coastguard Worker str.append("]");
164*d57664e9SAndroid Build Coastguard Worker break;
165*d57664e9SAndroid Build Coastguard Worker }
166*d57664e9SAndroid Build Coastguard Worker default:
167*d57664e9SAndroid Build Coastguard Worker break;
168*d57664e9SAndroid Build Coastguard Worker }
169*d57664e9SAndroid Build Coastguard Worker }
170*d57664e9SAndroid Build Coastguard Worker str.append("\n");
171*d57664e9SAndroid Build Coastguard Worker indent--;
172*d57664e9SAndroid Build Coastguard Worker indentStr(str, indent);
173*d57664e9SAndroid Build Coastguard Worker str.append("}");
174*d57664e9SAndroid Build Coastguard Worker return str;
175*d57664e9SAndroid Build Coastguard Worker }
176*d57664e9SAndroid Build Coastguard Worker
simplify(sp<Rule> rule)177*d57664e9SAndroid Build Coastguard Worker sp<Rule> Rule::simplify(sp<Rule> rule) {
178*d57664e9SAndroid Build Coastguard Worker if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) {
179*d57664e9SAndroid Build Coastguard Worker return rule;
180*d57664e9SAndroid Build Coastguard Worker }
181*d57664e9SAndroid Build Coastguard Worker
182*d57664e9SAndroid Build Coastguard Worker Vector<sp<Rule> > newSubrules;
183*d57664e9SAndroid Build Coastguard Worker newSubrules.setCapacity(rule->subrules.size());
184*d57664e9SAndroid Build Coastguard Worker const size_t subruleCount = rule->subrules.size();
185*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < subruleCount; i++) {
186*d57664e9SAndroid Build Coastguard Worker sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i));
187*d57664e9SAndroid Build Coastguard Worker if (simplifiedRule != NULL) {
188*d57664e9SAndroid Build Coastguard Worker if (simplifiedRule->op == rule->op) {
189*d57664e9SAndroid Build Coastguard Worker newSubrules.appendVector(simplifiedRule->subrules);
190*d57664e9SAndroid Build Coastguard Worker } else {
191*d57664e9SAndroid Build Coastguard Worker newSubrules.add(simplifiedRule);
192*d57664e9SAndroid Build Coastguard Worker }
193*d57664e9SAndroid Build Coastguard Worker }
194*d57664e9SAndroid Build Coastguard Worker }
195*d57664e9SAndroid Build Coastguard Worker
196*d57664e9SAndroid Build Coastguard Worker const size_t newSubruleCount = newSubrules.size();
197*d57664e9SAndroid Build Coastguard Worker if (newSubruleCount == 0) {
198*d57664e9SAndroid Build Coastguard Worker return NULL;
199*d57664e9SAndroid Build Coastguard Worker } else if (subruleCount == 1) {
200*d57664e9SAndroid Build Coastguard Worker return newSubrules.editTop();
201*d57664e9SAndroid Build Coastguard Worker }
202*d57664e9SAndroid Build Coastguard Worker rule->subrules = newSubrules;
203*d57664e9SAndroid Build Coastguard Worker return rule;
204*d57664e9SAndroid Build Coastguard Worker }
205*d57664e9SAndroid Build Coastguard Worker
206*d57664e9SAndroid Build Coastguard Worker } // namespace split
207