Merge change 840 into donut
* changes:
TypedProperties: change the file format to be a subset of Java
diff --git a/core/java/com/android/internal/util/TypedProperties.java b/core/java/com/android/internal/util/TypedProperties.java
index 48479e3..299108f 100644
--- a/core/java/com/android/internal/util/TypedProperties.java
+++ b/core/java/com/android/internal/util/TypedProperties.java
@@ -43,7 +43,7 @@
/* The only non-quoted-string words we'll be reading are:
* - property names: [._$a-zA-Z0-9]
- * - type names (case insensitive): [a-zA-Z]
+ * - type names: [a-zS]
* - number literals: [-0-9.eExXA-Za-z] ('x' for 0xNNN hex literals. "NaN", "Infinity")
* - "true" or "false" (case insensitive): [a-zA-Z]
*/
@@ -62,12 +62,13 @@
// Other special characters
st.whitespaceChars(' ', ' ');
st.whitespaceChars('\t', '\t');
-
+ st.whitespaceChars('\n', '\n');
+ st.whitespaceChars('\r', '\r');
st.quoteChar('"');
- st.commentChar('#');
-
- st.eolIsSignificant(true);
+ // Java-style comments
+ st.slashStarComments(true);
+ st.slashSlashComments(true);
return st;
}
@@ -100,59 +101,36 @@
static final int TYPE_ERROR = -1;
/**
- * Converts a case-insensitive string to an internal type constant.
+ * Converts a string to an internal type constant.
*
* @param typeName the type name to convert
* @return the type constant that corresponds to {@code typeName},
* or {@code TYPE_ERROR} if the type is unknown
*/
static int interpretType(String typeName) {
- if ("unset".equalsIgnoreCase(typeName)) {
+ if ("unset".equals(typeName)) {
return TYPE_UNSET;
- } else if ("boolean".equalsIgnoreCase(typeName)) {
+ } else if ("boolean".equals(typeName)) {
return TYPE_BOOLEAN;
- } else if ("byte".equalsIgnoreCase(typeName)) {
+ } else if ("byte".equals(typeName)) {
return TYPE_BYTE;
- } else if ("short".equalsIgnoreCase(typeName)) {
+ } else if ("short".equals(typeName)) {
return TYPE_SHORT;
- } else if ("int".equalsIgnoreCase(typeName)) {
+ } else if ("int".equals(typeName)) {
return TYPE_INT;
- } else if ("long".equalsIgnoreCase(typeName)) {
+ } else if ("long".equals(typeName)) {
return TYPE_LONG;
- } else if ("float".equalsIgnoreCase(typeName)) {
+ } else if ("float".equals(typeName)) {
return TYPE_FLOAT;
- } else if ("double".equalsIgnoreCase(typeName)) {
+ } else if ("double".equals(typeName)) {
return TYPE_DOUBLE;
- } else if ("string".equalsIgnoreCase(typeName)) {
+ } else if ("String".equals(typeName)) {
return TYPE_STRING;
}
return TYPE_ERROR;
}
/**
- * Consumes EOL tokens.
- * Returns when a non-EOL token is found.
- *
- * @param st The {@code StreamTokenizer} to read tokens from
- * @return > 0 if an EOL token was seen, < 0 if EOF was seen,
- * 0 if no tokens were consumed
- */
- static int eatEols(StreamTokenizer st) throws IOException {
- int token;
- boolean eolSeen = false;
- do {
- token = st.nextToken();
- if (token == StreamTokenizer.TT_EOF) {
- return -1;
- } else if (token == StreamTokenizer.TT_EOL) {
- eolSeen = true;
- }
- } while (token == StreamTokenizer.TT_EOL);
- st.pushBack();
- return eolSeen ? 1 : 0;
- }
-
- /**
* Parses the data in the reader.
*
* @param r The {@code Reader} containing input data to parse
@@ -171,17 +149,29 @@
Pattern.compile("(" + identifierPattern + "\\.)*" + identifierPattern);
- boolean eolNeeded = false;
while (true) {
int token;
- // Eat one or more EOL, or quit on EOF.
- int eolStatus = eatEols(st);
- if (eolStatus < 0) {
- // EOF occurred.
+ // Read the next token, which is either the type or EOF.
+ token = st.nextToken();
+ if (token == StreamTokenizer.TT_EOF) {
break;
- } else if (eolNeeded && eolStatus == 0) {
- throw new ParseException(st, "end of line or end of file");
+ }
+ if (token != StreamTokenizer.TT_WORD) {
+ throw new ParseException(st, "type name");
+ }
+ final int type = interpretType(st.sval);
+ if (type == TYPE_ERROR) {
+ throw new ParseException(st, "valid type name");
+ }
+ st.sval = null;
+
+ if (type == TYPE_UNSET) {
+ // Expect '('.
+ token = st.nextToken();
+ if (token != '(') {
+ throw new ParseException(st, "'('");
+ }
}
// Read the property name.
@@ -195,18 +185,12 @@
}
st.sval = null;
- // Read the type.
- token = st.nextToken();
- if (token != StreamTokenizer.TT_WORD) {
- throw new ParseException(st, "type name");
- }
- final int type = interpretType(st.sval);
- if (type == TYPE_ERROR) {
- throw new ParseException(st, "valid type name");
- }
- st.sval = null;
-
if (type == TYPE_UNSET) {
+ // Expect ')'.
+ token = st.nextToken();
+ if (token != ')') {
+ throw new ParseException(st, "')'");
+ }
map.remove(propertyName);
} else {
// Expect '='.
@@ -229,8 +213,11 @@
map.put(propertyName, value);
}
- // Require that we see at least one EOL before the next token.
- eolNeeded = true;
+ // Expect ';'.
+ token = st.nextToken();
+ if (token != ';') {
+ throw new ParseException(st, "';'");
+ }
}
}
@@ -251,9 +238,9 @@
throw new ParseException(st, "boolean constant");
}
- if ("true".equalsIgnoreCase(st.sval)) {
+ if ("true".equals(st.sval)) {
return Boolean.TRUE;
- } else if ("false".equalsIgnoreCase(st.sval)) {
+ } else if ("false".equals(st.sval)) {
return Boolean.FALSE;
}
@@ -339,7 +326,7 @@
// Expect a quoted string or the word "null".
if (token == '"') {
return st.sval;
- } else if (token == StreamTokenizer.TT_WORD && "null".equalsIgnoreCase(st.sval)) {
+ } else if (token == StreamTokenizer.TT_WORD && "null".equals(st.sval)) {
return NULL_STRING;
}
throw new ParseException(st, "double-quoted string or 'null'");
@@ -361,40 +348,47 @@
* Properties that have already been loaded are preserved unless
* the new Reader overrides or unsets earlier values for the
* same properties.
- *
+ * <p>
* File syntax:
- *
- * <property-name> <type> = <value>
- * <property-name> unset
- *
- * '#' is a comment character; it and anything appearing after it
- * on the line is ignored.
- *
+ * <blockquote>
+ * <tt>
+ * <type> <property-name> = <value> ;
+ * <br />
+ * unset ( <property-name> ) ;
+ * </tt>
+ * <p>
+ * "//" comments everything until the end of the line.
+ * "/a;" comments everything until the next appearance of "a;/".
+ * <p>
* Blank lines are ignored.
- *
- * The only required whitespace is between the property name
- * and the type.
- *
- * Property assignments may not be split across multiple lines.
- *
+ * <p>
+ * The only required whitespace is between the type and
+ * the property name.
+ * <p>
+ * <type> is one of {boolean, byte, short, int, long,
+ * float, double, String}, and is case-sensitive.
+ * <p>
* <property-name> is a valid fully-qualified class name
* (one or more valid identifiers separated by dot characters).
- *
- * <type> is one of {boolean, byte, short, int, long,
- * float, double, string}, and is case-insensitive.
- *
+ * <p>
* <value> depends on the type:
- * - boolean: one of {true, false} (case-insensitive)
- * - byte, short, int, long: a valid Java integer constant
- * (including non-base-10 constants like 0xabc and 074)
- * whose value does not overflow the type. NOTE: these are
- * interpreted as Java integer values, so they are all signed.
- * - float, double: a valid Java floating-point constant.
- * If the type is float, the value must fit in 32 bits.
- * - string: a double-quoted string value, or the word {@code null}.
- * NOTE: the contents of the string must be 7-bit clean ASCII;
- * C-style octal escapes are recognized, but Unicode escapes are not.
- *
+ * <ul>
+ * <li> boolean: one of {true, false} (case-sensitive)
+ * <li> byte, short, int, long: a valid Java integer constant
+ * (including non-base-10 constants like 0xabc and 074)
+ * whose value does not overflow the type. NOTE: these are
+ * interpreted as Java integer values, so they are all signed.
+ * <li> float, double: a valid Java floating-point constant.
+ * If the type is float, the value must fit in 32 bits.
+ * <li> String: a double-quoted string value, or the word {@code null}.
+ * NOTE: the contents of the string must be 7-bit clean ASCII;
+ * C-style octal escapes are recognized, but Unicode escapes are not.
+ * </ul>
+ * <p>
+ * Passing a property-name to {@code unset()} will unset the property,
+ * removing its value and type information, as if it had never been
+ * defined.
+ * </blockquote>
*
* @param r The Reader to load properties from
* @throws IOException if an error occurs when reading the data