private Map getHeader()

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;
    }