📄 maps.java
字号:
parse(Map map, String src, char separator, char quote) throws IllegalSyntaxException { return parse(map, src, separator, quote, false); } /** * Parses a string into a map. * * <p>If = is omitted, whether it is considered as a key with the null * value or a value with the null key depends on * the asValue argument. If true, it is considered as a value with * the null key. * * <p>For example, if the following string is parsed with asValue=false:<br/> * a12=12,b3,c6=abc=125,x=y * * <p>Then, a map with the following content is returned:<br/> * ("a12", "12"), ("b3", null), ("c6", "abc=125"), ("x", "y") * * <p>Notice: only the first = after separator is meaningful, * so you don't have to escape the following =. * <p>Beside specifying the quote character, you could use back slash * quote a single character (as Java does). * * @param map the map to put parsed results to; null to create a * new hash map * @param src the string to parse * @param separator the separator, e.g., ' ' or ','. * @param quote the quote character to surrounding value, e.g., * name = 'value'. If (char)0, no quotation is recognized. * Notice: if value is an expression, it is better to specify (char)0 * because expression might contain strings. * @param asValue whether to consider the substring without = as * a value (with the null key), or as a key (with the null value) * @return the map being generated * * @exception IllegalSyntaxException if syntax errors * @see CollectionsX#parse * @see #toString(Map, char, char) * @since 2.4.0 */ public static final Map parse(Map map, String src, char separator, char quote, boolean asValue) throws IllegalSyntaxException { if (separator == (char)0) throw new IllegalArgumentException("Separator cannot be 0"); if (map == null) map = new HashMap(); if (src == null || src.length() == 0) return map; //nothing to do //prepare delimiters for keys and values. final String delimValue, delimKey; { final StringBuffer delimsb = new StringBuffer().append(separator); if (quote != (char)0) delimsb.append(quote); delimValue = delimsb.toString(); delimKey = delimsb.append('=').toString(); } //parase for (int j = 0, len = src.length();;) { //handle name Token tk = next(src, delimKey, j, true);// if (D.ON && log.finerable()) log.finer("name: "+tk.token+" "+tk.cc); j = tk.next; final String name = tk.token; switch (tk.cc) { case '=': if (name.length() == 0) throw newIllegalSyntaxException(MCommon.UNEXPECTED_CHARACTER, tk.cc, src); ++j; //skip = break; case (char)0:// assert tk.next >= len; if (name.length() > 0) if (asValue) map.put(null, name); else map.put(name, null); return map;//done default: //If separator is ' ', tk.cc can be anything; see next() if ((separator != ' ' && tk.cc != separator) || name.length() == 0) throw newIllegalSyntaxException(MCommon.UNEXPECTED_CHARACTER, tk.cc, src); if (asValue) map.put(null, name); else map.put(name, null); if (tk.cc == separator) ++j; //skip separator continue; } //handle value tk = next(src, delimValue, j, false);// if (D.ON && log.finerable()) log.finer("value: "+tk.token+" "+tk.cc); j = tk.next; final String value = tk.token; if (quote != (char)0 && tk.cc == quote) { if (value.length() > 0) throw newIllegalSyntaxException(MCommon.UNEXPECTED_CHARACTER, tk.cc, src); final StringBuffer valsb = new StringBuffer(32); for (;;) { if (++j == len) throw newIllegalSyntaxException(MCommon.EXPECTING_CHARACTER, tk.cc, src); final char cc = src.charAt(j); if (cc == tk.cc) break; valsb.append(cc == '\\' ? escape(src, ++j): cc); } map.put(name, valsb.toString()); ++j; //skip the closing ' or " } else { map.put(name, value); } if (separator != ' ') { //If not ' ', ensure the following is a separator j = Strings.skipWhitespaces(src, j); if (j >= len) return map; if (src.charAt(j) != separator) throw newIllegalSyntaxException(MCommon.EXPECTING_CHARACTER, separator, src); ++j; //skip separator } } } private static final IllegalSyntaxException newIllegalSyntaxException(int code, char cc, String src) { return new IllegalSyntaxException(code, new Object[] {new Character(cc), src}); } private static class Token { /** The next position right after token. */ private final int next; /** The character before next. */ private final char cc; /** The token before next. */ private final String token; private Token(int next, char cc, String token) { this.next = next; this.cc = cc; this.token = token; } } private static final Token next(String src, String delimiters, int j, boolean whitespaceAware) { final StringBuffer tksb = new StringBuffer(64); final int len = src.length(); j = Strings.skipWhitespaces(src, j); for (; j < len; ++j) { final char cc = src.charAt(j); if (cc == '\\') { tksb.append(escape(src, ++j)); } else if (delimiters.indexOf(cc) >= 0) { //note: cc might be a separator which might be a whitespace j = Strings.skipWhitespaces(src, j); break; //done } else if (Character.isWhitespace(cc)) { final int k = Strings.skipWhitespaces(src, j); //done if the following is nothing but whitespace or... if (whitespaceAware || k >= len || delimiters.indexOf(src.charAt(k))>=0) { j = k; break; //done } if (j > k - 1) { //more than one whitespaces tksb.append(src.substring(j, k)); j = k - 1; //j will increase by one later } else { tksb.append(cc); } } else if (cc == (char)0) { throw newIllegalSyntaxException(MCommon.UNEXPECTED_CHARACTER, (char)0, src); } else { tksb.append(cc); } } return new Token(j, j < len ? src.charAt(j): (char)0, tksb.toString()); } private static final char escape(String src, int j) { if (j >= src.length()) throw new IllegalSyntaxException(MCommon.ILLEGAL_CHAR, "\\"); final char cc = src.charAt(j); return cc == 'n' ? '\n': cc == 't' ? '\t': cc; } /** * Converts a map to a string. * * @param map the map to convert from * @param quote the quotation character; 0 means no quotation surrunding * the value * @param separator the separator between two name=value pairs * @see #parse(Map, String, char, char) */ public static final String toString(Map map, char quote, char separator) { return toStringBuffer(new StringBuffer(64), map, quote, separator) .toString(); } /** Converts a map to string and append to a string buffer. * @see #toString */ public static final StringBuffer toStringBuffer(StringBuffer sb, Map map, char quote, char separator) { if (separator == (char)0) throw new IllegalArgumentException("Separator cannot be 0"); if (map.isEmpty()) return sb; //nothing to do //prepare characters to escape with backslash. final String escKey, escValue; { final StringBuffer escsb = new StringBuffer(12) .append(",\\'\" \n\t").append(separator); if (quote != (char)0 && quote != '\'' && quote != '"') escsb.append(quote); escValue = escsb.toString(); escKey = escsb.append('=').toString(); } //convert one-by-one for (final Iterator it = map.entrySet().iterator(); it.hasNext();) { final Map.Entry me = (Map.Entry)it.next(); final Object key = me.getKey(); if (key == null) throw new IllegalSyntaxException("Unable to encode null key: "+map); final String skey = key.toString(); if (skey == null || skey.length() == 0) throw new IllegalSyntaxException(MCommon.EMPTY_NOT_ALLOWED, "key"); encode(sb, skey, escKey); final Object val = me.getValue(); if (val != null) { sb.append('='); if (quote != (char)0) sb.append(quote); encode(sb, val.toString(), escValue); if (quote != (char)0) sb.append(quote); } sb.append(separator); } sb.setLength(sb.length() - 1); //remove the last comma return sb; } private static final void encode(StringBuffer sb, String val, String escapes) { for (int j = 0, len = val.length();;) { final int k = Strings.anyOf(val, escapes, j); if (k >= len) { sb.append(val.substring(j)); return; } sb.append(val.substring(j, k)).append('\\'); final char cc = val.charAt(k); sb.append(cc == '\n' ? 'n': cc == '\t' ? 't': cc); j = k + 1; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -