/*
 * Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.net.www;

import java.util.Iterator;

/* This is useful for the nightmare of parsing multi-part HTTP/RFC822 headers
 * sensibly:
 * From a String like: 'timeout=15, max=5'
 * create an array of Strings:
 * { {"timeout", "15"},
 *   {"max", "5"}
 * }
 * From one like: 'Basic Realm="FuzzFace" Foo="Biz Bar Baz"'
 * create one like (no quotes in literal):
 * { {"basic", null},
 *   {"realm", "FuzzFace"}
 *   {"foo", "Biz Bar Baz"}
 * }
 * keys are converted to lower case, vals are left as is....
 *
 * @author Dave Brown
 */


public class HeaderParser {

    /* table of key/val pairs */
    String raw;
    String[][] tab;
    int nkeys;
    int asize = 10; // initial size of array is 10

    public HeaderParser(String raw) {
        this.raw = raw;
        tab = new String[asize][2];
        parse();
    }

    private HeaderParser () {
    }

    /**
     * create a new HeaderParser from this, whose keys (and corresponding values)
     * range from "start" to "end-1"
     */
    public HeaderParser subsequence (int start, int end) {
        if (start == 0 && end == nkeys) {
            return this;
        }
        if (start < 0 || start >= end || end > nkeys)
            throw new IllegalArgumentException ("invalid start or end");
        HeaderParser n = new HeaderParser ();
        n.tab = new String [asize][2];
        n.asize = asize;
        System.arraycopy (tab, start, n.tab, 0, (end-start));
        n.nkeys= (end-start);
        return n;
    }

    private void parse() {

        if (raw != null) {
            raw = raw.trim();
            char[] ca = raw.toCharArray();
            int beg = 0, end = 0, i = 0;
            boolean inKey = true;
            boolean inQuote = false;
            int len = ca.length;
            while (end < len) {
                char c = ca[end];
                if ((c == '=') && !inQuote) { // end of a key
                    tab[i][0] = new String(ca, beg, end-beg).toLowerCase();
                    inKey = false;
                    end++;
                    beg = end;
                } else if (c == '\"') {
                    if (inQuote) {
                        tab[i++][1]= new String(ca, beg, end-beg);
                        inQuote=false;
                        do {
                            end++;
                        } while (end < len && (ca[end] == ' ' || ca[end] == ','));
                        inKey=true;
                        beg=end;
                    } else {
                        inQuote=true;
                        end++;
                        beg=end;
                    }
                } else if (c == ' ' || c == ',') { // end key/val, of whatever we're in
                    if (inQuote) {
                        end++;
                        continue;
                    } else if (inKey) {
                        tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase();
                    } else {
                        tab[i++][1] = (new String(ca, beg, end-beg));
                    }
                    while (end < len && (ca[end] == ' ' || ca[end] == ',')) {
                        end++;
                    }
                    inKey = true;
                    beg = end;
                } else {
                    end++;
                }
                if (i == asize) {
                    asize = asize * 2;
                    String[][] ntab = new String[asize][2];
                    System.arraycopy (tab, 0, ntab, 0, tab.length);
                    tab = ntab;
                }
            }
            // get last key/val, if any
            if (--end > beg) {
                if (!inKey) {
                    if (ca[end] == '\"') {
                        tab[i++][1] = (new String(ca, beg, end-beg));
                    } else {
                        tab[i++][1] = (new String(ca, beg, end-beg+1));
                    }
                } else {
                    tab[i++][0] = (new String(ca, beg, end-beg+1)).toLowerCase();
                }
            } else if (end == beg) {
                if (!inKey) {
                    if (ca[end] == '\"') {
                        tab[i++][1] = String.valueOf(ca[end-1]);
                    } else {
                        tab[i++][1] = String.valueOf(ca[end]);
                    }
                } else {
                    tab[i++][0] = String.valueOf(ca[end]).toLowerCase();
                }
            }
            nkeys=i;
        }

    }

    public String findKey(int i) {
        if (i < 0 || i > asize)
            return null;
        return tab[i][0];
    }

    public String findValue(int i) {
        if (i < 0 || i > asize)
            return null;
        return tab[i][1];
    }

    public String findValue(String key) {
        return findValue(key, null);
    }

    public String findValue(String k, String Default) {
        if (k == null)
            return Default;
        k = k.toLowerCase();
        for (int i = 0; i < asize; ++i) {
            if (tab[i][0] == null) {
                return Default;
            } else if (k.equals(tab[i][0])) {
                return tab[i][1];
            }
        }
        return Default;
    }

    class ParserIterator implements Iterator {
        int index;
        boolean returnsValue; // or key

        ParserIterator (boolean returnValue) {
            returnsValue = returnValue;
        }
        public boolean hasNext () {
            return index<nkeys;
        }
        public Object next () {
            return tab[index++][returnsValue?1:0];
        }
        public void remove () {
            throw new UnsupportedOperationException ("remove not supported");
        }
    }

    public Iterator keys () {
        return new ParserIterator (false);
    }

    public Iterator values () {
        return new ParserIterator (true);
    }

    public String toString () {
        Iterator k = keys();
        StringBuffer sbuf = new StringBuffer();
        sbuf.append ("{size="+asize+" nkeys="+nkeys+" ");
        for (int i=0; k.hasNext(); i++) {
            String key = (String)k.next();
            String val = findValue (i);
            if (val != null && "".equals (val)) {
                val = null;
            }
            sbuf.append (" {"+key+(val==null?"":","+val)+"}");
            if (k.hasNext()) {
                sbuf.append (",");
            }
        }
        sbuf.append (" }");
        return new String (sbuf);
    }

    public int findInt(String k, int Default) {
        try {
            return Integer.parseInt(findValue(k, String.valueOf(Default)));
        } catch (Throwable t) {
            return Default;
        }
    }
    /*
    public static void main(String[] a) throws Exception {
        System.out.print("enter line to parse> ");
        System.out.flush();
        DataInputStream dis = new DataInputStream(System.in);
        String line = dis.readLine();
        HeaderParser p = new HeaderParser(line);
        for (int i = 0; i < asize; ++i) {
            if (p.findKey(i) == null) break;
            String v = p.findValue(i);
            System.out.println(i + ") " +p.findKey(i) + "="+v);
        }
        System.out.println("Done!");

    }
    */
}
