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

import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.Externalizable;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import com.ibm.icu.impl.Utility;
import com.ibm.icu.text.UTF16;
import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.text.UnicodeSetIterator;
import com.ibm.icu.util.Freezable;
/**
 * Class for mapping Unicode characters to values
 * Much smaller storage than using HashMap, and much faster and more compact than
 * a list of UnicodeSets.
 * @author Davis
 */

public final class UnicodeMap implements Cloneable, Freezable, Externalizable {
    static final boolean ASSERTIONS = false;
    static final long GROWTH_PERCENT = 200; // 100 is no growth!
    static final long GROWTH_GAP = 10; // extra bump!

    private int length;
    // two parallel arrays to save memory. Wish Java had structs.
    private int[] transitions;
    private Object[] values;
    
    private LinkedHashSet availableValues = new LinkedHashSet();
    private transient boolean staleAvailableValues;

    private transient boolean errorOnReset;
    private transient boolean locked;
    private int lastIndex;
    
    { clear(); }
    
    public UnicodeMap clear() {
        if (locked) throw new UnsupportedOperationException("Attempt to modify locked object");
        length = 2;
        transitions = new int[] {0,0x110000,0,0,0,0,0,0,0,0};
        values = new Object[10];
        
        availableValues.clear();
        staleAvailableValues = false;

        errorOnReset = false;
        lastIndex = 0;
    	return this;
    }
    
    /* Boilerplate */
    public boolean equals(Object other) {
        if (other == null) return false;
        try {
            UnicodeMap that = (UnicodeMap) other;
            if (length != that.length) return false;
            for (int i = 0; i < length-1; ++i) {
                if (transitions[i] != that.transitions[i]) return false;
                if (!areEqual(values[i], that.values[i])) return false;
            }
            return true;
        } catch (ClassCastException e) {
            return false;
        }
    }
    
    public int getHashCode(Object o) {
    	return o.hashCode();
    	//equator.getHashCode
    }
    
    public static boolean areEqual(Object a , Object b) {
    	if (a == b) return true;
    	if (a == null || b == null) return false;
    	return a.equals(b);
    }
    
    public int hashCode() {
        int result = length;
        // TODO might want to abbreviate this for speed.
        for (int i = 0; i < length-1; ++i) {
            result = 37*result + transitions[i];
            result = 37*result + getHashCode(values[i]);
        }
        return result;
    }
    
    /**
     * Standard clone. Warning, as with Collections, does not do deep clone.
     */
    public Object cloneAsThawed() {
        UnicodeMap that = new UnicodeMap();
        that.length = length;
        that.transitions = (int[]) transitions.clone();
        that.values = (Object[]) values.clone();
        that.availableValues = new LinkedHashSet(availableValues);
        that.locked = false;
        return that;
    }
    
    /* for internal consistency checking */
    
    void _checkInvariants() {
        if (length < 2
          || length > transitions.length
          || transitions.length != values.length) {
              throw new IllegalArgumentException("Invariant failed: Lengths bad");
          }
        for (int i = 1; i < length-1; ++i) {
            if (areEqual(values[i-1], values[i])) {
                throw new IllegalArgumentException("Invariant failed: values shared at " 
                    + "\t" + Utility.hex(i-1) + ": <" + values[i-1] + ">"
                    + "\t" + Utility.hex(i) + ": <" + values[i] + ">"
                    );
            }
        }
        if (transitions[0] != 0 || transitions[length-1] != 0x110000) {
            throw new IllegalArgumentException("Invariant failed: bounds set wrong");
        }
        for (int i = 1; i < length-1; ++i) {
            if (transitions[i-1] >= transitions[i]) {
                throw new IllegalArgumentException("Invariant failed: not monotonic"
                + "\t" + Utility.hex(i-1) + ": " + transitions[i-1]
                + "\t" + Utility.hex(i) + ": " + transitions[i]
                    );
            }
        }
    }
    
    /**
     * Finds an index such that inversionList[i] <= codepoint < inversionList[i+1]
     * Assumes that 0 <= codepoint <= 0x10FFFF
     * @param codepoint
     * @return the index
     */
    private int _findIndex(int c) {
        int lo = 0;
        int hi = length - 1;
        int i = (lo + hi) >>> 1;
        // invariant: c >= list[lo]
        // invariant: c < list[hi]
        while (i != lo) {
            if (c < transitions[i]) {
                hi = i;
            } else {
                lo = i;
            }
            i = (lo + hi) >>> 1;
        }
        if (ASSERTIONS) _checkFind(c, lo);
        return lo;
    }
    
    private void _checkFind(int codepoint, int value) {
        int other = __findIndex(codepoint);
        if (other != value) {
            throw new IllegalArgumentException("Invariant failed: binary search"
                + "\t" + Utility.hex(codepoint) + ": " + value
                + "\tshould be: " + other);            
        }
    }
    
    private int __findIndex(int codepoint) {
        // TODO use binary search
        for (int i = length-1; i > 0; --i) {
            if (transitions[i] <= codepoint) return i;
        }
        return 0;
    }
    
    /*
     * Try indexed lookup
     
    static final int SHIFT = 8;
    int[] starts = new int[0x10FFFF>>SHIFT]; // lowest transition index where codepoint>>x can be found
    boolean startsValid = false;
    private int findIndex(int codepoint) {
        if (!startsValid) {
            int start = 0;
            for (int i = 1; i < length; ++i) {
                
            }
        }
        for (int i = length-1; i > 0; --i) {
           if (transitions[i] <= codepoint) return i;
       }
       return 0;
   }
   */
   
    /**
     * Remove the items from index through index+count-1.
     * Logically reduces the size of the internal arrays.
     * @param index
     * @param count
     */
    private void _removeAt(int index, int count) {
        for (int i = index + count; i < length; ++i) {
            transitions[i-count] = transitions[i];
            values[i-count] = values[i];
        }
        length -= count;
    }
    /**
     * Add a gap from index to index+count-1.
     * The values there are undefined, and must be set.
     * Logically grows arrays to accomodate. Actual growth is limited
     * @param index
     * @param count
     */
    private void _insertGapAt(int index, int count) {
        int newLength = length + count;
        int[] oldtransitions = transitions;
        Object[] oldvalues = values;
        if (newLength > transitions.length) {
            int allocation = (int) (GROWTH_GAP + (newLength * GROWTH_PERCENT) / 100);
            transitions = new int[allocation];
            values = new Object[allocation];
            for (int i = 0; i < index; ++i) {
                transitions[i] = oldtransitions[i];
                values[i] = oldvalues[i];
            }
        } 
        for (int i = length - 1; i >= index; --i) {
            transitions[i+count] = oldtransitions[i];
            values[i+count] = oldvalues[i];
        }
        length = newLength;
    }
    
    /**
     * Associates code point with value. Removes any previous association.
     * @param codepoint
     * @param value
     * @return this, for chaining
     */
    private UnicodeMap _put(int codepoint, Object value) {
        // Warning: baseIndex is an invariant; must
        // be defined such that transitions[baseIndex] < codepoint
        // at end of this routine.
        int baseIndex;
        if (transitions[lastIndex] <= codepoint 
          && codepoint < transitions[lastIndex+1]) {
            baseIndex = lastIndex;
        } else { 
            baseIndex = _findIndex(codepoint);
        }
        int limitIndex = baseIndex + 1;
        // cases are (a) value is already set
        if (areEqual(values[baseIndex], value)) return this;
        if (locked) throw new UnsupportedOperationException("Attempt to modify locked object");
        if (errorOnReset && values[baseIndex] != null) {
        	throw new IllegalArgumentException("Attempt to reset value for " + Utility.hex(codepoint)
        			+ " when that is disallowed. Old: " + values[baseIndex] + "; New: " + value);
        }

        // adjust the available values
        staleAvailableValues = true;
        availableValues.add(value); // add if not there already      

        int baseCP = transitions[baseIndex];
        int limitCP = transitions[limitIndex];
        // we now start walking through the difference case,
        // based on whether we are at the start or end of range
        // and whether the range is a single character or multiple
        
        if (baseCP == codepoint) {
            // CASE: At very start of range
            boolean connectsWithPrevious = 
                baseIndex != 0 && areEqual(value, values[baseIndex-1]);               
                
            if (limitCP == codepoint + 1) {
                // CASE: Single codepoint range
                boolean connectsWithFollowing =
                    baseIndex < length - 1 && areEqual(value, values[limitIndex]);
                
                if (connectsWithPrevious) {
                    // A1a connects with previous & following, so remove index
                    if (connectsWithFollowing) {
                        _removeAt(baseIndex, 2);
                     } else {
                        _removeAt(baseIndex, 1); // extend previous
                    }
                    --baseIndex; // fix up
                } else if (connectsWithFollowing) {
                    _removeAt(baseIndex, 1); // extend following backwards
                    transitions[baseIndex] = codepoint; 
                } else {
                    // doesn't connect on either side, just reset
                    values[baseIndex] = value;
                }
            } else if (connectsWithPrevious) {             
            // A.1: start of multi codepoint range
            // if connects
                ++transitions[baseIndex]; // extend previous
            } else {
                // otherwise insert new transition
                transitions[baseIndex] = codepoint+1; // fix following range
                _insertGapAt(baseIndex, 1);
                values[baseIndex] = value;
                transitions[baseIndex] = codepoint;
            }
        } else if (limitCP == codepoint + 1) {
            // CASE: at end of range        
            // if connects, just back up range
            boolean connectsWithFollowing =
                baseIndex < length - 1 && areEqual(value, values[limitIndex]);

            if (connectsWithFollowing) {
                --transitions[limitIndex]; 
                return this;                
            } else {
                _insertGapAt(limitIndex, 1);
                transitions[limitIndex] = codepoint;
                values[limitIndex] = value;
            }
        } else {
            // CASE: in middle of range
            // insert gap, then set the new range
            _insertGapAt(++baseIndex,2);
            transitions[baseIndex] = codepoint;
            values[baseIndex] = value;
            transitions[baseIndex+1] = codepoint + 1;
            values[baseIndex+1] = values[baseIndex-1]; // copy lower range values
        }
        lastIndex = baseIndex; // store for next time
        return this;
    }
    private UnicodeMap _putAll(int startCodePoint, int endCodePoint, Object value) {
        for (int i = startCodePoint; i <= endCodePoint; ++i) {
            _put(i, value);
        }
        return this;
    }
    /**
     * Sets the codepoint value.
     * @param codepoint
     * @param value
     * @return this (for chaining)
     */
    public UnicodeMap put(int codepoint, Object value) {
        if (codepoint < 0 || codepoint > 0x10FFFF) {
            throw new IllegalArgumentException("Codepoint out of range: " + codepoint);
        }
        _put(codepoint, value);
        if (ASSERTIONS) _checkInvariants();
        return this;
    }
    /**
     * Adds bunch o' codepoints; otherwise like put.
     * @param codepoints
     * @param value
     * @return this (for chaining)
     */
    public UnicodeMap putAll(UnicodeSet codepoints, Object value) {
        // TODO optimize
        UnicodeSetIterator it = new UnicodeSetIterator(codepoints);
        while (it.nextRange()) {
            _putAll(it.codepoint, it.codepointEnd, value);
        }
        return this;
    }
    
    /**
     * Adds bunch o' codepoints; otherwise like add.
     * @param startCodePoint
     * @param endCodePoint
     * @param value
     * @return this (for chaining)
     */
    public UnicodeMap putAll(int startCodePoint, int endCodePoint, Object value) {
        if (startCodePoint < 0 || endCodePoint > 0x10FFFF) {
            throw new IllegalArgumentException("Codepoint out of range: "
             + Utility.hex(startCodePoint) + ".." + Utility.hex(endCodePoint));
        }
        // TODO optimize
        for (int i = startCodePoint; i <= endCodePoint; ++i) {
            _put(i, value);
        }
        return this;
    }
    /**
     * Add all the (main) values from a Unicode property
     * @param prop the property to add to the map
     * @return this (for chaining)
     */
    public UnicodeMap putAll(UnicodeProperty prop) {
        // TODO optimize
        for (int i = 0; i <= 0x10FFFF; ++i) {
            _put(i, prop.getValue(i));
        }
        return this;
    }

    /**
     * Add all the (main) values from a Unicode property
     * @param prop the property to add to the map
     * @return this (for chaining)
     */
    public UnicodeMap putAll(UnicodeMap prop) {
        // TODO optimize
        for (int i = 0; i <= 0x10FFFF; ++i) {
            _put(i, prop.getValue(i));
        }
        return this;
    }

    /**
     * Set the currently unmapped Unicode code points to the given value.
     * @param value the value to set
     * @return this (for chaining)
     */
    public UnicodeMap setMissing(Object value) {
    	// fast path, if value not yet present
    	if (!getAvailableValues().contains(value)) {
        	staleAvailableValues = true;
	    	availableValues.add(value);
	        for (int i = 0; i < length; ++i) {
	            if (values[i] == null) values[i] = value;
	        }
	        return this;
	    } else {
	    	return putAll(getSet(null), value);
	    }
    }
    /**
     * Returns the set associated with a given value. Deposits into
     * result if it is not null. Remember to clear if you just want
     * the new values.
     * @param value
     * @param result
     * @return result
     */
    public UnicodeSet getSet(Object value, UnicodeSet result) {
        if (result == null) result = new UnicodeSet();
        for (int i = 0; i < length - 1; ++i) {
            if (areEqual(value, values[i])) {
                result.add(transitions[i], transitions[i+1]-1);
            } 
        }
        return result;
    }
    public UnicodeSet getSet(Object value) {
        return getSet(value,null);
    }

    public UnicodeSet keySet() {
        return getSet(null,null).complement();
    }
    /**
     * Returns the list of possible values. Deposits each non-null value into
     * result. Creates result if it is null. Remember to clear result if
     * you are not appending to existing collection.
     * @param result
     * @return result
     */
    public Collection getAvailableValues(Collection result) {
    	if (staleAvailableValues) {
    		// collect all the current values
    		// retain them in the availableValues
    		Set temp = new HashSet();
            for (int i = 0; i < length - 1; ++i) {
                if (values[i] != null) temp.add(values[i]);
            }
            availableValues.retainAll(temp);
            staleAvailableValues = false;
    	}
    	if (result == null) result = new ArrayList(availableValues.size());
        result.addAll(availableValues);
        return result;
    }
    
    /**
     * Convenience method
     */
    public Collection getAvailableValues() {
        return getAvailableValues(null);
    }
    /**
     * Gets the value associated with a given code point.
     * Returns null, if there is no such value.
     * @param codepoint
     * @return the value
     */
    public Object getValue(int codepoint) {
        if (codepoint < 0 || codepoint > 0x10FFFF) {
            throw new IllegalArgumentException("Codepoint out of range: " + codepoint);
        }
        return values[_findIndex(codepoint)];
    }
    
    public interface Composer {
    	Object compose(int codePoint, Object a, Object b);
    }
    
    public UnicodeMap composeWith(UnicodeMap other, Composer composer) {
    	for (int i = 0; i <= 0x10FFFF; ++i) {
    		Object v1 = getValue(i);
    		Object v2 = other.getValue(i);
    		Object v3 = composer.compose(i, v1, v2);
    		if (v1 != v3 && (v1 == null || !v1.equals(v3))) put(i, v3);
    	}
    	return this;
    }
    
    /**
     * Follow the style used by UnicodeSetIterator
     */
    public static class MapIterator {
        public int codepoint;
        public int codepointEnd;
        public Object value;
        
        private UnicodeMap map;
        private int index;
        private int startRange;
        private int endRange;
        private Object lastValue;
        
        public MapIterator(UnicodeMap map) {
            reset(map);
        }
        // note: length of 2 means {0, 110000}. Only want to index up to 0!
        public boolean nextRange() {
            if (index < 0 || index >= map.length - 1) return false;
            value = map.values[index];
            codepoint = startRange = map.transitions[index++];
            codepointEnd = endRange = map.transitions[index] - 1; // -1 to make limit into end
            return true;
        }
        public boolean next() {
            if (startRange > endRange) {
                //System.out.println("***" + Utility.hex(startRange) + ".." + Utility.hex(endRange));
                if (!nextRange()) return false;
                // index now points AFTER the start of the range
                lastValue = map.values[index-1];
                //System.out.println("***" + Utility.hex(codepoint) + ".." + Utility.hex(codepointEnd) + " => " + lastValue);
            }
            value = lastValue;
            codepoint = codepointEnd = startRange++; // set to first, and iterate
            return true;
        }

        public MapIterator reset() {
            index = 0;
            startRange = 0;
            endRange = -1;
            return this;
        }
        public MapIterator reset(UnicodeMap map) {
            this.map = map;
            return reset();
        }
    }
    
    public String toString() {
        return toString(null);
    }
    public String toString(Comparator collected) {
        StringBuffer result = new StringBuffer();       
        if (collected == null) {
            for (int i = 0; i < length-1; ++i) {
                Object value = values[i];
                if (value == null) continue;
                int start = transitions[i];
                int end = transitions[i+1]-1;
                result.append(Utility.hex(start));
                if (start != end) result.append("..")
                .append(Utility.hex(end));
                result.append("\t=> ")
                .append(values[i] == null ? "null" : values[i].toString())
                .append("\r\n");
            }
        } else {
            Set set = (Set) getAvailableValues(new TreeSet(collected));
            for (Iterator it = set.iterator(); it.hasNext();) {
                Object value = it.next();
                UnicodeSet s = getSet(value);
                result.append(value)
                .append("\t=> ")
                .append(s.toPattern(true))
                .append("\r\n");
            }
        }
        return result.toString();
    }
	/**
	 * @return Returns the errorOnReset.
	 */
	public boolean getErrorOnReset() {
		return errorOnReset;
	}
	/**
	 * @param errorOnReset The errorOnReset to set.
	 */
	public void setErrorOnReset(boolean errorOnReset) {
		this.errorOnReset = errorOnReset;
	}

	/* (non-Javadoc)
	 * @see com.ibm.icu.dev.test.util.Lockable#isLocked()
	 */
	public boolean isFrozen() {
		// TODO Auto-generated method stub
		return locked;
	}

	/* (non-Javadoc)
	 * @see com.ibm.icu.dev.test.util.Lockable#lock()
	 */
	public Object freeze() {
		locked = true;
		return this;
	}
    
    static final boolean DEBUG_WRITE = false;
    
    // TODO Fix to serialize more than just strings.
    // Only if all the items are strings will we do the following compression
    // Otherwise we'll just use Java Serialization, bulky as it is
    public void writeExternal(ObjectOutput out1) throws IOException {
        DataOutputCompressor sc = new DataOutputCompressor(out1);
        // if all objects are strings
        Collection availableValues = getAvailableValues();
        boolean allStrings = allAreString(availableValues);
        sc.writeBoolean(allStrings);
        Map object_index = new LinkedHashMap();
        if (allAreString(availableValues)) {
            sc.writeStringSet(new TreeSet(availableValues), object_index);
        } else {
            sc.writeCollection(availableValues, object_index);           
        }
        sc.writeUInt(length);
        int lastTransition = -1;
        int lastValueNumber = 0;
        if (DEBUG_WRITE) System.out.println("Trans count: " + length);
        for (int i = 0; i < length; ++i) {
            int valueNumber = ((Integer)object_index.get(values[i])).intValue();
            if (DEBUG_WRITE) System.out.println("Trans: " + transitions[i] + ",\t" + valueNumber);
            
            int deltaTransition = transitions[i] - lastTransition;
            lastTransition = transitions[i];
            int deltaValueNumber = valueNumber - lastValueNumber;
            lastValueNumber = valueNumber;
            
            deltaValueNumber <<= 1; // make room for one bit
            boolean canCombine = deltaTransition == 1;
            if (canCombine) deltaValueNumber |= 1;
            sc.writeInt(deltaValueNumber);
            if (DEBUG_WRITE) System.out.println("deltaValueNumber: " + deltaValueNumber);
            if (!canCombine) {
            	sc.writeUInt(deltaTransition);           	
            	if (DEBUG_WRITE) System.out.println("deltaTransition: " + deltaTransition);
            }
        }
        sc.flush();
    }

    /**
     * 
     */
    private boolean allAreString(Collection availableValues2) {
        //if (true) return false;
        for (Iterator it = availableValues2.iterator(); it.hasNext();) {
            if (!(it.next() instanceof String)) return false;
        }
        return true;
    }

    public void readExternal(ObjectInput in1) throws IOException, ClassNotFoundException {
        DataInputCompressor sc = new DataInputCompressor(in1);
        boolean allStrings = sc.readBoolean();
        Object[] valuesList;
        availableValues = new LinkedHashSet();
        if (allStrings) {
            valuesList = sc.readStringSet(availableValues);
        } else {
            valuesList = sc.readCollection(availableValues);            
        }
        length = sc.readUInt();
        transitions = new int[length];
        if (DEBUG_WRITE) System.out.println("Trans count: " + length);
        values = new Object[length];
        int currentTransition = -1;
        int currentValue = 0;
        int deltaTransition;
        for (int i = 0; i < length; ++i) {
            int temp = sc.readInt();
            if (DEBUG_WRITE) System.out.println("deltaValueNumber: " + temp);
            boolean combined = (temp & 1) != 0;
            temp >>= 1;
            values[i] = valuesList[currentValue += temp];
            if (!combined) {
                deltaTransition = sc.readUInt();
                if (DEBUG_WRITE) System.out.println("deltaTransition: " + deltaTransition);
            } else {
                deltaTransition = 1;
            }
            transitions[i] = currentTransition += deltaTransition; // delta value
            if (DEBUG_WRITE) System.out.println("Trans: " + transitions[i] + ",\t" + currentValue);
        }
    }

    /**
     * 
     */
    static int findCommon(String last, String s) {
        int minLen = Math.min(last.length(), s.length());
        for (int i = 0; i < minLen; ++i) {
            if (last.charAt(i) != s.charAt(i)) return i;
        }
        return minLen;
    }


//    /**
//     * @param sc
//     * @throws IOException
//     * 
//     */
//    private void showSize(String title, ObjectOutput out, StreamCompressor sc) throws IOException {
//        sc.showSize(this, title, out);
//    }
//    //public void readObject(ObjectInputStream in) throws IOException {
//    public static class StreamCompressor {
//    	transient byte[] buffer = new byte[1];
//        transient StringBuffer stringBuffer = new StringBuffer();
//        
//        transient byte[] readWriteBuffer = new byte[8];
//        int position = 0;
//        DataOutput out;
//        DataInput in;
//
//        /**
//         * Format is:
//         * @throws IOException
//         */
//        public void writeInt(int i) throws IOException {
//            while (true) {
//                if (position == readWriteBuffer.length) {
//                	out.write(readWriteBuffer);
//                    position = 0;
//                }
//            	if ((i & ~0x7F) == 0) {
//                    readWriteBuffer[position++] = (byte)i;
//                    break;
//                }
//                readWriteBuffer[position++] = (byte)(0x80 | i);
//                i >>>= 7;
//            }
//        }
//		/**
//		 * @throws IOException
//		 * 
//		 */
//		public int readNInt(ObjectInput in) throws IOException {
//			int result = readInt(in);
//            boolean negative = (result & 1) != 0;
//            result >>>= 1;
//            if (negative) result = ~result;
//            return result;
//		}
//		/**
//		 * @throws IOException
//		 * 
//		 */
//		public void writeNInt(int input) throws IOException {
//            int flag = 0;
//            if (input < 0) {
//                input = ~input;
//                flag = 1;
//            }
//			input = (input << 1) | flag;
//			writeInt(out, input);
//		}
//		/**
//		 * @throws IOException
//		 * 
//		 */
//		public void flush() throws IOException {
//            out.write(readWriteBuffer);
//            position = 0;
//		}
//        
//        int readPosition = readWriteBuffer.length;
//        
//		public int readInt(ObjectInput in) throws IOException {
//            int result = 0;
//            int offset = 0;
//            while (true) {
//                if (readPosition == readWriteBuffer.length) {
//                	in.read(readWriteBuffer);
//                    readPosition = 0;
//                }
//                //in.read(buffer);
//                int input = readWriteBuffer[readPosition++]; // buffer[0];
//                result |= (input & 0x7F) << offset;
//                if ((input & 0x80) == 0) {
//                    return result;
//                }
//                offset += 7;
//            }  
//        }
//
//        /**
//         * @throws IOException
//         * 
//         */
//        public void writeString(String s) throws IOException {
//            writeInt(UTF16.countCodePoint(s));
//            writeCodePoints(s);
//        }
//        /**
//		 * 
//		 */
//		private void writeCodePoints(String s) throws IOException {
//			int cp = 0;
//            for (int i = 0; i < s.length(); i += UTF16.getCharCount(cp)) {
//                cp = UTF16.charAt(s, i);
//                writeInt(cp);
//            }
//		}
//		/**
//         * @throws IOException
//         * 
//         */
//        public String readString() throws IOException {
//            int len = readInt(in);
//            return readCodePoints(in, len);
//        }
//		/**
//		 * 
//		 */
//		private String readCodePoints(int len) throws IOException {
//			stringBuffer.setLength(0);
//            for (int i = 0; i < len; ++i) {
//            	int cp = readInt(in);
//                UTF16.append(stringBuffer, cp);
//            }
//            return stringBuffer.toString();
//		}
//		/**
//		 * @param this
//		 * @throws IOException
//		 * 
//		 */
//		private void showSize(UnicodeMap map, String title, ObjectOutput out) throws IOException {
//		    out.flush();
//			System.out.println(title + ": " + (map.debugOut.size() + position));
//		}
//    }
}
