• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 package android.util;
17 
18 import android.text.TextUtils;
19 
20 import java.time.Duration;
21 import java.time.format.DateTimeParseException;
22 
23 /**
24  * Parses a list of key=value pairs, separated by some delimiter, and puts the results in
25  * an internal Map. Values can be then queried by key, or if not found, a default value
26  * can be used.
27  * @hide
28  */
29 public class KeyValueListParser {
30     private final ArrayMap<String, String> mValues = new ArrayMap<>();
31     private final TextUtils.StringSplitter mSplitter;
32 
33     /**
34      * Constructs a new KeyValueListParser. This can be reused for different strings
35      * by calling {@link #setString(String)}.
36      * @param delim The delimiter that separates key=value pairs.
37      */
KeyValueListParser(char delim)38     public KeyValueListParser(char delim) {
39         mSplitter = new TextUtils.SimpleStringSplitter(delim);
40     }
41 
42     /**
43      * Resets the parser with a new string to parse. The string is expected to be in the following
44      * format:
45      * <pre>key1=value,key2=value,key3=value</pre>
46      *
47      * where the delimiter is a comma.
48      *
49      * @param str the string to parse.
50      * @throws IllegalArgumentException if the string is malformed.
51      */
setString(String str)52     public void setString(String str) throws IllegalArgumentException {
53         mValues.clear();
54         if (str != null) {
55             mSplitter.setString(str);
56             for (String pair : mSplitter) {
57                 int sep = pair.indexOf('=');
58                 if (sep < 0) {
59                     mValues.clear();
60                     throw new IllegalArgumentException(
61                             "'" + pair + "' in '" + str + "' is not a valid key-value pair");
62                 }
63                 mValues.put(pair.substring(0, sep).trim(), pair.substring(sep + 1).trim());
64             }
65         }
66     }
67 
68     /**
69      * Get the value for key as an int.
70      * @param key The key to lookup.
71      * @param def The value to return if the key was not found, or the value was not a long.
72      * @return the int value associated with the key.
73      */
getInt(String key, int def)74     public int getInt(String key, int def) {
75         String value = mValues.get(key);
76         if (value != null) {
77             try {
78                 return Integer.parseInt(value);
79             } catch (NumberFormatException e) {
80                 // fallthrough
81             }
82         }
83         return def;
84     }
85 
86     /**
87      * Get the value for key as a long.
88      * @param key The key to lookup.
89      * @param def The value to return if the key was not found, or the value was not a long.
90      * @return the long value associated with the key.
91      */
getLong(String key, long def)92     public long getLong(String key, long def) {
93         String value = mValues.get(key);
94         if (value != null) {
95             try {
96                 return Long.parseLong(value);
97             } catch (NumberFormatException e) {
98                 // fallthrough
99             }
100         }
101         return def;
102     }
103 
104     /**
105      * Get the value for key as a float.
106      * @param key The key to lookup.
107      * @param def The value to return if the key was not found, or the value was not a float.
108      * @return the float value associated with the key.
109      */
getFloat(String key, float def)110     public float getFloat(String key, float def) {
111         String value = mValues.get(key);
112         if (value != null) {
113             try {
114                 return Float.parseFloat(value);
115             } catch (NumberFormatException e) {
116                 // fallthrough
117             }
118         }
119         return def;
120     }
121 
122     /**
123      * Get the value for key as a string.
124      * @param key The key to lookup.
125      * @param def The value to return if the key was not found.
126      * @return the string value associated with the key.
127      */
getString(String key, String def)128     public String getString(String key, String def) {
129         String value = mValues.get(key);
130         if (value != null) {
131             return value;
132         }
133         return def;
134     }
135 
136     /**
137      * Get the value for key as a boolean.
138      * @param key The key to lookup.
139      * @param def The value to return if the key was not found.
140      * @return the string value associated with the key.
141      */
getBoolean(String key, boolean def)142     public boolean getBoolean(String key, boolean def) {
143         String value = mValues.get(key);
144         if (value != null) {
145             try {
146                 return Boolean.parseBoolean(value);
147             } catch (NumberFormatException e) {
148                 // fallthrough
149             }
150         }
151         return def;
152     }
153 
154     /**
155      * Get the value for key as an integer array.
156      *
157      * The value should be encoded as "0:1:2:3:4"
158      *
159      * @param key The key to lookup.
160      * @param def The value to return if the key was not found.
161      * @return the int[] value associated with the key.
162      */
getIntArray(String key, int[] def)163     public int[] getIntArray(String key, int[] def) {
164         String value = mValues.get(key);
165         if (value != null) {
166             try {
167                 String[] parts = value.split(":");
168                 if (parts.length > 0) {
169                     int[] ret = new int[parts.length];
170                     for (int i = 0; i < parts.length; i++) {
171                         ret[i] = Integer.parseInt(parts[i]);
172                     }
173                     return ret;
174                 }
175             } catch (NumberFormatException e) {
176                 // fallthrough
177             }
178         }
179         return def;
180     }
181 
182     /**
183      * @return the number of keys.
184      */
size()185     public int size() {
186         return mValues.size();
187     }
188 
189     /**
190      * @return the key at {@code index}. Use with {@link #size()} to enumerate all key-value pairs.
191      */
keyAt(int index)192     public String keyAt(int index) {
193         return mValues.keyAt(index);
194     }
195 
196     /**
197      * {@hide}
198      * Parse a duration in millis based on java.time.Duration or just a number (millis)
199      */
getDurationMillis(String key, long def)200     public long getDurationMillis(String key, long def) {
201         String value = mValues.get(key);
202         if (value != null) {
203             try {
204                 if (value.startsWith("P") || value.startsWith("p")) {
205                     return Duration.parse(value).toMillis();
206                 } else {
207                     return Long.parseLong(value);
208                 }
209             } catch (NumberFormatException | DateTimeParseException e) {
210                 // fallthrough
211             }
212         }
213         return def;
214     }
215 }
216