Rule.cpp 5.5 KB

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