/*
 * Copyright 2010 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package java.lang;

import java.io.DataInputStream;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.zip.InflaterInputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;

class CharacterName1 {

    // TODO: if, then cache persistent instead by SoftReference
    private static SoftReference<HashMap<Integer,String>> refNames;

    private static synchronized HashMap<Integer,String> getNames() {
        HashMap<Integer,String> names = null;
        DataInputStream dis = null;
        try {
            dis = new DataInputStream(new InflaterInputStream(
                AccessController.doPrivileged(new PrivilegedAction<InputStream>()
                {
                    public InputStream run() {
                        return getClass().getResourceAsStream("uniName.dat");
                    }
                })));
            byte[] str = new byte[dis.readInt()]; // read string part length
            dis.readFully(str);
            String allNames = new String(str, 0, str.length, "ASCII");
            str = null; // help GC
            names = new HashMap<>(dis.readInt()); // read numbers part length
            dis.mark(1);
            for (int len, i=0, cp=0; (len = dis.read()) >= 0; dis.mark(1)) {
                if (len < 0x80) // allows maximum character name length of 127
                    cp++;
                else {
                    len &= 0x7F; // allows maximum character name length of 126
                    dis.reset();
                    cp = dis.readInt() & 0xFFFFFF;
                }
                names.put(cp, allNames.substring(i, i += len));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                dis.close();
            } catch (Exception ee) {
                ee.printStackTrace();
            }
        }
        return names;
    }

    public static String get(int cp) {
        HashMap<Integer,String> names;
        if (refNames == null || (names = refNames.get()) == null)
            refNames = new SoftReference<>(names = getNames());
        return names.get(cp);
    }
}
