//##header
/*
 *******************************************************************************
 * Copyright (C) 1996-2006, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
//#ifndef FOUNDATION
package com.ibm.icu.dev.test.util;

import java.io.DataInput;
import java.io.IOException;
import java.io.ObjectInput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

import com.ibm.icu.impl.Utility;
import com.ibm.icu.text.UTF16;

/**
 * Simple data input compressor. Nothing fancy, but much smaller footprint for
 * ints and many strings.
 */
public final class DataInputCompressor implements ObjectInput {
    static final boolean SHOW = false;

    private ObjectInput dataInput;

    private transient StringBuffer stringBuffer = new StringBuffer();

    public DataInputCompressor(ObjectInput dataInput) {
        this.dataInput = dataInput;
    }

    public DataInput getDataInput() {
        return dataInput;
    }

    public void setDataInput(ObjectInput dataInput) {
        this.dataInput = dataInput;
    }

    public boolean readBoolean() throws IOException {
        return dataInput.readBoolean();
    }

    public byte readByte() throws IOException {
        return dataInput.readByte();
    }

    public int readUnsignedByte() throws IOException {
        return dataInput.readUnsignedByte();
    }

    public double readDouble() throws IOException {
        return dataInput.readDouble();
    }

    public float readFloat() throws IOException {
        return dataInput.readFloat();
    }

    public void readFully(byte[] b) throws IOException {
        dataInput.readFully(b);
    }

    public void readFully(byte[] b, int off, int len) throws IOException {
        dataInput.readFully(b, off, len);
    }

    public int skipBytes(int n) throws IOException {
        return dataInput.skipBytes(n);
    }

    public String readLine() throws IOException {
        return dataInput.readLine();
    }

    public int available() throws IOException {
        return dataInput.available();
    }
    public void close() throws IOException {
        dataInput.close();
    }
    public int read() throws IOException {
        return dataInput.read();
    }
    public int read(byte[] b) throws IOException {
        return dataInput.read(b);
    }
    public int read(byte[] b, int off, int len) throws IOException {
        return dataInput.read(b, off, len);
    }
    public Object readObject() throws ClassNotFoundException, IOException {
        return dataInput.readObject();
    }
    public long skip(long n) throws IOException {
        return dataInput.skip(n);
    }
    public String toString() {
        return dataInput.toString();
    }
    // ==== New Routines ====

    public char readChar() throws IOException {
        return (char) readULong();
    }

    public short readShort() throws IOException {
        return (short) readLong();
    }

    public int readUnsignedShort() throws IOException {
        return (int) readULong();
    }

    public int readUShort() throws IOException {
        return (int) readULong();
    }

    public int readInt() throws IOException {
        return (int) readLong();
    }

    public int readUInt() throws IOException {
        return (int) readULong();
    }

    public String readChars(int len) throws IOException {
        stringBuffer.setLength(0);
        for (int i = 0; i < len; ++i) {
            int cp = (int) readULong();
            UTF16.append(stringBuffer, cp);
        }
        return stringBuffer.toString();
    }

    public String readUTF() throws IOException {
        int len = (int) readULong();
        return readChars(len);
    }

    public long readLong() throws IOException {
        long result = 0;
        int offset = 0;
        while (true) {
            long input = readByte();
            result |= (input & 0x7F) << offset;
            if ((input & 0x80) == 0)
                break;
            offset += 7;
        }
        boolean negative = (result & 1) != 0; // get sign bit from the bottom,
                                              // and invert
        result >>>= 1;
        if (negative)
            result = ~result;
        return result;
    }

    public long readULong() throws IOException {
        long result = 0;
        int offset = 0;
        while (true) { // read sequence of 7 bits, with top bit = 1 for
                       // continuation
            int input = readByte();
            result |= (input & 0x7F) << offset;
            if ((input & 0x80) == 0)
                return result;
            offset += 7;
        }
    }

    /**
     *  
     */
    public Object[] readStringSet(Collection availableValues)
            throws IOException {
        int size = readUInt();
        if (SHOW) System.out.println("readStringSet");
        Object[] valuesList = new Object[size + 1];
        // first item is null
        String lastString = "";
        ReadPool trailingPool = new ReadPool();
        for (int i = 0; i < size; ++i) {
            int common = readUInt();
            boolean inPool = (common & 1) != 0;
            common >>>= 1;
            if (SHOW) System.out.println(common);
            String current;
            if (inPool) {
                int poolIndex = readUInt();
                if (SHOW) System.out.println("\t" + poolIndex);
                current = (String) trailingPool.get(poolIndex);
            } else {
                current = readUTF();
                trailingPool.add(current);
            }
            valuesList[i + 1] = lastString = lastString.substring(0, common)
                    + current;
            if (SHOW) System.out.println("\t\t" + lastString);
            if (availableValues != null) availableValues.add(current);
        }
        return valuesList;
    }
    
    public static class ReadPool {
        private List trailingPool = new ArrayList();
        public Object get(int index) {
            return trailingPool.get(index);
        }
        public void add(Object o) {
            trailingPool.add(o);
        }
    }

    /**
     * @throws IOException
     * @throws ClassNotFoundException
     * 
     */
    public Object[] readCollection(LinkedHashSet availableValues) throws ClassNotFoundException, IOException {
        int size = readUInt();
        Object[] valuesList = new Object[size + 1];
        for (int i = 0; i < size; ++i) {
            valuesList[i + 1] = readObject();
        }
       return valuesList;
    }
}
//#endif
