in juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java [326:410]
private <K,V> Map<K,V> parseIntoMap2(UonReader r, Map<K,V> m, ClassMeta<?> type, Object outer) throws IOException, ParseException, ExecutableException {
ClassMeta<K> keyType = (ClassMeta<K>)(type.isArgs() || type.isCollectionOrArray() ? getClassMeta(Integer.class) : type.getKeyType());
int c = r.peekSkipWs();
if (c == -1)
return m;
final int S1=1; // Looking for attrName start.
final int S2=2; // Found attrName end, looking for =.
final int S3=3; // Found =, looking for valStart.
final int S4=4; // Looking for & or end.
boolean isInEscape = false;
int state = S1;
int argIndex = 0;
K currAttr = null;
while (c != -1) {
c = r.read();
if (! isInEscape) {
if (state == S1) {
if (c == -1)
return m;
r.unread();
Object attr = parseAttr(r, true);
currAttr = attr == null ? null : convertAttrToType(m, trim(attr.toString()), keyType);
state = S2;
c = 0; // Avoid isInEscape if c was '\'
} else if (state == S2) {
if (c == '\u0002')
state = S3;
else if (c == -1 || c == '\u0001') {
m.put(currAttr, null);
if (c == -1)
return m;
state = S1;
}
} else if (state == S3) {
if (c == -1 || c == '\u0001') {
ClassMeta<V> valueType = (ClassMeta<V>)(type.isArgs() ? type.getArg(argIndex++) : type.isCollectionOrArray() ? type.getElementType() : type.getValueType());
V value = convertAttrToType(m, "", valueType);
m.put(currAttr, value);
if (c == -1)
return m;
state = S1;
} else {
// For performance, we bypass parseAnything for string values.
ClassMeta<V> valueType = (ClassMeta<V>)(type.isArgs() ? type.getArg(argIndex++) : type.isCollectionOrArray() ? type.getElementType() : type.getValueType());
V value = (V)(valueType.isString() ? super.parseString(r.unread(), true) : super.parseAnything(valueType, r.unread(), outer, true, null));
// If we already encountered this parameter, turn it into a list.
if (m.containsKey(currAttr) && valueType.isObject()) {
Object v2 = m.get(currAttr);
if (! (v2 instanceof JsonList)) {
v2 = new JsonList(v2).setBeanSession(this);
m.put(currAttr, (V)v2);
}
((JsonList)v2).add(value);
} else {
m.put(currAttr, value);
}
state = S4;
c = 0; // Avoid isInEscape if c was '\'
}
} else if (state == S4) {
if (c == '\u0001')
state = S1;
else if (c == -1) {
return m;
}
}
}
isInEscape = (c == '\\' && ! isInEscape);
}
if (state == S1)
throw new ParseException(this, "Could not find attribute name on object.");
if (state == S2)
throw new ParseException(this, "Could not find '=' following attribute name on object.");
if (state == S3)
throw new ParseException(this, "Dangling '=' found in object entry");
if (state == S4)
throw new ParseException(this, "Could not find end of object.");
return null; // Unreachable.
}