| /* |
| * 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 |
| */ |
| 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); |
| } |
| } |
| } |