You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.5 KiB
207 lines
5.5 KiB
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "Rule.h"
|
|
|
|
#include <utils/String8.h>
|
|
|
|
using namespace android;
|
|
|
|
namespace split {
|
|
|
|
inline static void indentStr(String8& str, int indent) {
|
|
while (indent > 0) {
|
|
str.append(" ");
|
|
indent--;
|
|
}
|
|
}
|
|
|
|
Rule::Rule(const Rule& rhs)
|
|
: RefBase()
|
|
, op(rhs.op)
|
|
, key(rhs.key)
|
|
, negate(rhs.negate)
|
|
, stringArgs(rhs.stringArgs)
|
|
, longArgs(rhs.longArgs)
|
|
, subrules(rhs.subrules) {
|
|
}
|
|
|
|
String8 Rule::toJson(int indent) const {
|
|
String8 str;
|
|
indentStr(str, indent);
|
|
str.append("{\n");
|
|
indent++;
|
|
indentStr(str, indent);
|
|
str.append("\"op\": \"");
|
|
switch (op) {
|
|
case ALWAYS_TRUE:
|
|
str.append("ALWAYS_TRUE");
|
|
break;
|
|
case GREATER_THAN:
|
|
str.append("GREATER_THAN");
|
|
break;
|
|
case LESS_THAN:
|
|
str.append("LESS_THAN");
|
|
break;
|
|
case EQUALS:
|
|
str.append("EQUALS");
|
|
break;
|
|
case AND_SUBRULES:
|
|
str.append("AND_SUBRULES");
|
|
break;
|
|
case OR_SUBRULES:
|
|
str.append("OR_SUBRULES");
|
|
break;
|
|
case CONTAINS_ANY:
|
|
str.append("CONTAINS_ANY");
|
|
break;
|
|
default:
|
|
str.appendFormat("%d", op);
|
|
break;
|
|
}
|
|
str.append("\"");
|
|
|
|
if (negate) {
|
|
str.append(",\n");
|
|
indentStr(str, indent);
|
|
str.append("\"negate\": true");
|
|
}
|
|
|
|
bool includeKey = true;
|
|
switch (op) {
|
|
case AND_SUBRULES:
|
|
case OR_SUBRULES:
|
|
includeKey = false;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (includeKey) {
|
|
str.append(",\n");
|
|
indentStr(str, indent);
|
|
str.append("\"property\": \"");
|
|
switch (key) {
|
|
case NONE:
|
|
str.append("NONE");
|
|
break;
|
|
case SDK_VERSION:
|
|
str.append("SDK_VERSION");
|
|
break;
|
|
case SCREEN_DENSITY:
|
|
str.append("SCREEN_DENSITY");
|
|
break;
|
|
case NATIVE_PLATFORM:
|
|
str.append("NATIVE_PLATFORM");
|
|
break;
|
|
case LANGUAGE:
|
|
str.append("LANGUAGE");
|
|
break;
|
|
default:
|
|
str.appendFormat("%d", key);
|
|
break;
|
|
}
|
|
str.append("\"");
|
|
}
|
|
|
|
if (op == AND_SUBRULES || op == OR_SUBRULES) {
|
|
str.append(",\n");
|
|
indentStr(str, indent);
|
|
str.append("\"subrules\": [\n");
|
|
const size_t subruleCount = subrules.size();
|
|
for (size_t i = 0; i < subruleCount; i++) {
|
|
str.append(subrules[i]->toJson(indent + 1));
|
|
if (i != subruleCount - 1) {
|
|
str.append(",");
|
|
}
|
|
str.append("\n");
|
|
}
|
|
indentStr(str, indent);
|
|
str.append("]");
|
|
} else {
|
|
switch (key) {
|
|
case SDK_VERSION:
|
|
case SCREEN_DENSITY: {
|
|
str.append(",\n");
|
|
indentStr(str, indent);
|
|
str.append("\"args\": [");
|
|
const size_t argCount = longArgs.size();
|
|
for (size_t i = 0; i < argCount; i++) {
|
|
if (i != 0) {
|
|
str.append(", ");
|
|
}
|
|
str.appendFormat("%d", longArgs[i]);
|
|
}
|
|
str.append("]");
|
|
break;
|
|
}
|
|
case LANGUAGE:
|
|
case NATIVE_PLATFORM: {
|
|
str.append(",\n");
|
|
indentStr(str, indent);
|
|
str.append("\"args\": [");
|
|
const size_t argCount = stringArgs.size();
|
|
for (size_t i = 0; i < argCount; i++) {
|
|
if (i != 0) {
|
|
str.append(", ");
|
|
}
|
|
str.append(stringArgs[i]);
|
|
}
|
|
str.append("]");
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
str.append("\n");
|
|
indent--;
|
|
indentStr(str, indent);
|
|
str.append("}");
|
|
return str;
|
|
}
|
|
|
|
sp<Rule> Rule::simplify(sp<Rule> rule) {
|
|
if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) {
|
|
return rule;
|
|
}
|
|
|
|
Vector<sp<Rule> > newSubrules;
|
|
newSubrules.setCapacity(rule->subrules.size());
|
|
const size_t subruleCount = rule->subrules.size();
|
|
for (size_t i = 0; i < subruleCount; i++) {
|
|
sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i));
|
|
if (simplifiedRule != NULL) {
|
|
if (simplifiedRule->op == rule->op) {
|
|
newSubrules.appendVector(simplifiedRule->subrules);
|
|
} else {
|
|
newSubrules.add(simplifiedRule);
|
|
}
|
|
}
|
|
}
|
|
|
|
const size_t newSubruleCount = newSubrules.size();
|
|
if (newSubruleCount == 0) {
|
|
return NULL;
|
|
} else if (subruleCount == 1) {
|
|
return newSubrules.editTop();
|
|
}
|
|
rule->subrules = newSubrules;
|
|
return rule;
|
|
}
|
|
|
|
} // namespace split
|