blob: 783b2d63bcf354d7690be6b3f3b9cf70d2b57999 [file] [log] [blame]
/*
* Copyright (C) 2015 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.
*/
package android.util;
import android.text.TextUtils;
import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
import java.time.Duration;
import java.time.format.DateTimeParseException;
/**
* Parses a list of key=value pairs, separated by some delimiter, and puts the results in
* an internal Map. Values can be then queried by key, or if not found, a default value
* can be used.
* @hide
*/
@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class KeyValueListParser {
private final ArrayMap<String, String> mValues = new ArrayMap<>();
private final TextUtils.StringSplitter mSplitter;
/**
* Constructs a new KeyValueListParser. This can be reused for different strings
* by calling {@link #setString(String)}.
* @param delim The delimiter that separates key=value pairs.
*/
public KeyValueListParser(char delim) {
mSplitter = new TextUtils.SimpleStringSplitter(delim);
}
/**
* Resets the parser with a new string to parse. The string is expected to be in the following
* format:
* <pre>key1=value,key2=value,key3=value</pre>
*
* where the delimiter is a comma.
*
* @param str the string to parse.
* @throws IllegalArgumentException if the string is malformed.
*/
public void setString(String str) throws IllegalArgumentException {
mValues.clear();
if (str != null) {
mSplitter.setString(str);
for (String pair : mSplitter) {
int sep = pair.indexOf('=');
if (sep < 0) {
mValues.clear();
throw new IllegalArgumentException(
"'" + pair + "' in '" + str + "' is not a valid key-value pair");
}
mValues.put(pair.substring(0, sep).trim(), pair.substring(sep + 1).trim());
}
}
}
/**
* Get the value for key as an int.
* @param key The key to lookup.
* @param def The value to return if the key was not found, or the value was not a long.
* @return the int value associated with the key.
*/
public int getInt(String key, int def) {
String value = mValues.get(key);
if (value != null) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
// fallthrough
}
}
return def;
}
/**
* Get the value for key as a long.
* @param key The key to lookup.
* @param def The value to return if the key was not found, or the value was not a long.
* @return the long value associated with the key.
*/
public long getLong(String key, long def) {
String value = mValues.get(key);
if (value != null) {
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
// fallthrough
}
}
return def;
}
/**
* Get the value for key as a float.
* @param key The key to lookup.
* @param def The value to return if the key was not found, or the value was not a float.
* @return the float value associated with the key.
*/
public float getFloat(String key, float def) {
String value = mValues.get(key);
if (value != null) {
try {
return Float.parseFloat(value);
} catch (NumberFormatException e) {
// fallthrough
}
}
return def;
}
/**
* Get the value for key as a string.
* @param key The key to lookup.
* @param def The value to return if the key was not found.
* @return the string value associated with the key.
*/
public String getString(String key, String def) {
String value = mValues.get(key);
if (value != null) {
return value;
}
return def;
}
/**
* Get the value for key as a boolean.
* @param key The key to lookup.
* @param def The value to return if the key was not found.
* @return the string value associated with the key.
*/
public boolean getBoolean(String key, boolean def) {
String value = mValues.get(key);
if (value != null) {
try {
return Boolean.parseBoolean(value);
} catch (NumberFormatException e) {
// fallthrough
}
}
return def;
}
/**
* Get the value for key as an integer array.
*
* The value should be encoded as "0:1:2:3:4"
*
* @param key The key to lookup.
* @param def The value to return if the key was not found.
* @return the int[] value associated with the key.
*/
public int[] getIntArray(String key, int[] def) {
String value = mValues.get(key);
if (value != null) {
try {
String[] parts = value.split(":");
if (parts.length > 0) {
int[] ret = new int[parts.length];
for (int i = 0; i < parts.length; i++) {
ret[i] = Integer.parseInt(parts[i]);
}
return ret;
}
} catch (NumberFormatException e) {
// fallthrough
}
}
return def;
}
/**
* @return the number of keys.
*/
public int size() {
return mValues.size();
}
/**
* @return the key at {@code index}. Use with {@link #size()} to enumerate all key-value pairs.
*/
public String keyAt(int index) {
return mValues.keyAt(index);
}
/**
* {@hide}
* Parse a duration in millis based on java.time.Duration or just a number (millis)
*/
public long getDurationMillis(String key, long def) {
String value = mValues.get(key);
if (value != null) {
try {
if (value.startsWith("P") || value.startsWith("p")) {
return Duration.parse(value).toMillis();
} else {
return Long.parseLong(value);
}
} catch (NumberFormatException | DateTimeParseException e) {
// fallthrough
}
}
return def;
}
/** Represents an integer config value. */
public static class IntValue {
private final String mKey;
private final int mDefaultValue;
private int mValue;
/** Constructor, initialize with a config key and a default value. */
public IntValue(String key, int defaultValue) {
mKey = key;
mDefaultValue = defaultValue;
mValue = mDefaultValue;
}
/** Read a value from {@link KeyValueListParser} */
public void parse(KeyValueListParser parser) {
mValue = parser.getInt(mKey, mDefaultValue);
}
/** Return the config key. */
public String getKey() {
return mKey;
}
/** Return the default value. */
public int getDefaultValue() {
return mDefaultValue;
}
/** Return the actual config value. */
public int getValue() {
return mValue;
}
/** Overwrites with a value. */
public void setValue(int value) {
mValue = value;
}
/** Used for dumpsys */
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.print(mKey);
pw.print("=");
pw.print(mValue);
pw.println();
}
/** Used for proto dumpsys */
public void dumpProto(ProtoOutputStream proto, long tag) {
proto.write(tag, mValue);
}
}
/** Represents an long config value. */
public static class LongValue {
private final String mKey;
private final long mDefaultValue;
private long mValue;
/** Constructor, initialize with a config key and a default value. */
public LongValue(String key, long defaultValue) {
mKey = key;
mDefaultValue = defaultValue;
mValue = mDefaultValue;
}
/** Read a value from {@link KeyValueListParser} */
public void parse(KeyValueListParser parser) {
mValue = parser.getLong(mKey, mDefaultValue);
}
/** Return the config key. */
public String getKey() {
return mKey;
}
/** Return the default value. */
public long getDefaultValue() {
return mDefaultValue;
}
/** Return the actual config value. */
public long getValue() {
return mValue;
}
/** Overwrites with a value. */
public void setValue(long value) {
mValue = value;
}
/** Used for dumpsys */
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.print(mKey);
pw.print("=");
pw.print(mValue);
pw.println();
}
/** Used for proto dumpsys */
public void dumpProto(ProtoOutputStream proto, long tag) {
proto.write(tag, mValue);
}
}
/** Represents an string config value. */
public static class StringValue {
private final String mKey;
private final String mDefaultValue;
private String mValue;
/** Constructor, initialize with a config key and a default value. */
public StringValue(String key, String defaultValue) {
mKey = key;
mDefaultValue = defaultValue;
mValue = mDefaultValue;
}
/** Read a value from {@link KeyValueListParser} */
public void parse(KeyValueListParser parser) {
mValue = parser.getString(mKey, mDefaultValue);
}
/** Return the config key. */
public String getKey() {
return mKey;
}
/** Return the default value. */
public String getDefaultValue() {
return mDefaultValue;
}
/** Return the actual config value. */
public String getValue() {
return mValue;
}
/** Overwrites with a value. */
public void setValue(String value) {
mValue = value;
}
/** Used for dumpsys */
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.print(mKey);
pw.print("=");
pw.print(mValue);
pw.println();
}
/** Used for proto dumpsys */
public void dumpProto(ProtoOutputStream proto, long tag) {
proto.write(tag, mValue);
}
}
/** Represents an float config value. */
public static class FloatValue {
private final String mKey;
private final float mDefaultValue;
private float mValue;
/** Constructor, initialize with a config key and a default value. */
public FloatValue(String key, float defaultValue) {
mKey = key;
mDefaultValue = defaultValue;
mValue = mDefaultValue;
}
/** Read a value from {@link KeyValueListParser} */
public void parse(KeyValueListParser parser) {
mValue = parser.getFloat(mKey, mDefaultValue);
}
/** Return the config key. */
public String getKey() {
return mKey;
}
/** Return the default value. */
public float getDefaultValue() {
return mDefaultValue;
}
/** Return the actual config value. */
public float getValue() {
return mValue;
}
/** Overwrites with a value. */
public void setValue(float value) {
mValue = value;
}
/** Used for dumpsys */
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.print(mKey);
pw.print("=");
pw.print(mValue);
pw.println();
}
/** Used for proto dumpsys */
public void dumpProto(ProtoOutputStream proto, long tag) {
proto.write(tag, mValue);
}
}
}