in xstream/src/java/com/thoughtworks/xstream/core/util/XmlHeaderAwareReader.java [67:179]
private Map<String, String> getHeader(final PushbackInputStream[] in) throws IOException {
final Map<String, String> header = new HashMap<>();
header.put(KEY_ENCODING, "UTF-8");
header.put(KEY_VERSION, "1.0");
int state = STATE_BOM;
final ByteArrayOutputStream out = new ByteArrayOutputStream(64);
int i = 0;
char ch = 0;
char valueEnd = 0;
final StringBuffer name = new StringBuffer();
final StringBuffer value = new StringBuffer();
boolean escape = false;
while (i != -1 && (i = in[0].read()) != -1) {
out.write(i);
ch = (char)i;
switch (state) {
case STATE_BOM:
if (ch == 0xEF && out.size() == 1 || ch == 0xBB && out.size() == 2 || ch == 0xBF && out.size() == 3) {
if (ch == 0xBF) {
out.reset();
state = STATE_START;
}
break;
} else if (out.size() > 1) {
i = -1;
break;
} else {
state = STATE_START;
}
//$FALL-THROUGH$
case STATE_START:
if (!Character.isWhitespace(ch)) {
if (ch == '<') {
state = STATE_AWAIT_XML_HEADER;
} else {
i = -1;
}
}
break;
case STATE_AWAIT_XML_HEADER:
if (!Character.isWhitespace(ch)) {
name.append(Character.toLowerCase(ch));
if (!XML_TOKEN.startsWith(name.substring(0))) {
i = -1;
}
} else {
if (name.toString().equals(XML_TOKEN)) {
state = STATE_ATTR_NAME;
name.setLength(0);
} else {
i = -1;
}
}
break;
case STATE_ATTR_NAME:
if (!Character.isWhitespace(ch)) {
if (ch == '=') {
state = STATE_ATTR_VALUE;
} else {
ch = Character.toLowerCase(ch);
if (Character.isLetter(ch)) {
name.append(ch);
} else {
i = -1;
}
}
} else if (name.length() > 0) {
i = -1;
}
break;
case STATE_ATTR_VALUE:
if (valueEnd == 0) {
if (ch == '"' || ch == '\'') {
valueEnd = ch;
} else {
i = -1;
}
} else {
if (ch == '\\' && !escape) {
escape = true;
break;
}
if (ch == valueEnd && !escape) {
valueEnd = 0;
state = STATE_ATTR_NAME;
header.put(name.toString(), value.toString());
name.setLength(0);
value.setLength(0);
} else {
escape = false;
if (ch != '\n') {
value.append(ch);
} else {
i = -1;
}
}
}
break;
}
}
final byte[] pushbackData = out.toByteArray();
for (i = pushbackData.length; i-- > 0;) {
final byte b = pushbackData[i];
try {
in[0].unread(b);
} catch (final IOException ex) {
in[0] = new PushbackInputStream(in[0], ++i);
}
}
return header;
}