Charset.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Исходный код среды исполнения ПВТ-ОО.

    Этот исходный код является частью проекта ПВТ-ОО.

    Copyright © 2021 Малик Разработчик

    Это свободная программа: вы можете перераспространять её и/или
    изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она может быть полезна,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <http://www.gnu.org/licenses/>.
*/

package avt.io.charset;

import avt.lang.array.*;
import avt.util.*;

public abstract class Charset(Object, Comparable)
{
    private static int count;
    private static Charset[] charsets;
    private static final Charset utf8;
    private static final Charset console;
    private static final Hashtable registered;

    public static {
        charsets = new Charset[15];
        registered = new Hashtable();
        for(String packName = "avt.io.charset.", Package[] packs = Package.enumerate(), int i = packs.length; i-- > 0; )
        {
            Package pack = packs[i];
            if(!pack.canonicalName.startsWith(packName)) continue;
            for(Class[] types = pack.enumerateTypes(), int j = types.length; j-- > 0; )
            {
                Class type = types[j];
                if(!Charset.class.isAssignableFrom(type) || type.isAbstract()) continue;
                try
                {
                    registerCharset((Charset) type.newInstance());
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
        console = getCharset("CP-866");
        utf8 = getCharset("UTF-8");
    }

    public static void register(Charset charset) throws RegisteredCharsetNameException {
        if(charset == null)
        {
            throw new NullPointerException("аргумент charset равен нулевой ссылке");
        }
        String charsetName = null;
        synchronized(registered)
        {
            label0:
            {
                String current;
                if(registered.containsKey(current = charset.fldName))
                {
                    charsetName = current;
                    break label0;
                }
                for(String[] aliases = charset.fldAliases, int i = aliases.length; i-- > 0; )
                {
                    if(registered.containsKey(current = aliases[i]))
                    {
                        charsetName = current;
                        break label0;
                    }
                }
                registerCharset(charset);
            }
        }
        if(charsetName != null)
        {
            throw new RegisteredCharsetNameException("набор символов с таким названием или псевдонимом уже зарегистрирован") { charsetName = charsetName };
        }
    }

    public static boolean isSupported(String charsetName) { return registered.containsKey(charsetName); }

    public static Charset[] enumerate() {
        Charset[] result;
        synchronized(registered)
        {
            Array.copy(charsets, 0, result = new Charset[count], 0, count);
        }
        return result;
    }

    public static Charset getConsole() { return console; }

    public static Charset getDefault() { return utf8; }

    public static Charset get(String charsetName) throws UnsupportedCharsetNameException {
        if(charsetName == null) charsetName = "";
        Charset result = (Charset) registered[charsetName];
        if(result == null)
        {
            throw new UnsupportedCharsetNameException("набор символов с таким названием или псевдонимом не поддерживается") { charsetName = charsetName };
        }
        return result;
    }

    private static void registerCharset(Charset charset) {
        if(count >= Int.MAX_VALUE)
        {
            throw new BufferTooLargeError("объём буфера очень велик");
        }
        if(count == charsets.length)
        {
            Array.copy(charsets, 0, charsets = new Charset[(count << 1) + 1], 0, count);
        }
        charsets[count++] = charset;
        registered[charset.fldName] = charset;
        for(String[] aliases = charset.fldAliases, int i = aliases.length; i-- > 0; registered[aliases[i]] = charset);
    }

    private static Charset getCharset(String charsetName) {
        Charset result = (Charset) registered[charsetName];
        if(result == null)
        {
            throw new CharsetNotFoundError(String.format("Важная системная кодировка %0% не реализована в этой среде исполнения.", new Object[] { charsetName }));
        }
        return result;
    }


    private final String[] fldAliases;
    private final String fldName;

    protected (String name, String[] aliases) {
        int length = aliases == null ? 0 : aliases.length;
        String charsetName = name == null ? "" : name;
        String[] charsetAliases = new String[length];
        label0: for(int len = length, length = 0, int i = 0; i < len; i++)
        {
            String charsetAlias = aliases[i];
            if(charsetAlias == null || charsetAlias.equals(charsetName)) continue label0;
            for(int j = length; j-- > 0; )
            {
                if(charsetAlias.equals(charsetAliases[j])) continue label0;
            }
            charsetAliases[length++] = charsetAlias;
        }
        if(length != charsetAliases.length)
        {
            Array.copy(charsetAliases, 0, charsetAliases = new String[length], 0, length);
        }
        fldAliases = charsetAliases;
        fldName = charsetName;
    }

    public abstract CharDecoder newDecoder();

    public abstract CharEncoder newEncoder();

    public boolean contains(Charset charset) { return false; }

    public String displayName() { return fldName; }

    public final boolean equals(Object anot) { return anot == this || anot instanceof Charset && ((Charset) anot).fldName.equals(fldName); }

    public final int hashCode() { return ((Object) fldName).hashCode(); }

    public final long hashCodeAsLong() { return ((Object) fldName).hashCodeAsLong(); }

    public final long2 hashCodeAsLong2() { return ((Object) fldName).hashCodeAsLong2(); }

    public final long4 hashCodeAsLong4() { return ((Object) fldName).hashCodeAsLong4(); }

    public final long8 hashCodeAsLong8() { return ((Object) fldName).hashCodeAsLong8(); }

    public final String toString() { return "charset " + fldName; }

    public final int compareTo(Comparable anot) { return !(anot instanceof Charset) ? INDEFINITE : -((Charset) anot).fldName.compareTo(fldName); }

    public final boolean isRegistered() {
        boolean result;
        synchronized(registered)
        {
            result = count > 0 && Array.indexOf(this, charsets, 0, count) >= 0;
        }
        return result;
    }

    public final boolean isName(String charsetName) {
        if(fldName.equals(charsetName)) return true;
        for(String[] aliases = fldAliases, int i = aliases.length; i-- > 0; )
        {
            if(aliases[i].equals(name)) return true;
        }
        return false;
    }

    public final char[] decode(ByteArray src) {
        char[] result = null;
        try
        {
            result = newDecoder().decode(src);
        }
        catch(Exception e)
        {
            throw new UnsupportedOperationException(e.message, e);
        }
        return result;
    }

    public final char[] decode(ByteArray src, int offset, int length) {
        char[] result = null;
        try
        {
            result = newDecoder().decode(src, offset, length);
        }
        catch(Exception e)
        {
            throw new UnsupportedOperationException(e.message, e);
        }
        return result;
    }

    public final byte[] encode(CharArray src) {
        byte[] result = null;
        try
        {
            result = newEncoder().encode(src);
        }
        catch(Exception e)
        {
            throw new UnsupportedOperationException(e.message, e);
        }
        return result;
    }

    public final byte[] encode(CharArray src, int offset, int length) {
        byte[] result = null;
        try
        {
            result = newEncoder().encode(src, offset, length);
        }
        catch(Exception e)
        {
            throw new UnsupportedOperationException(e.message, e);
        }
        return result;
    }

    public final String[] aliases { read = getAliases }

    public final String name { read = fldName }

    public final boolean operator >(Comparable anot) { return Comparable.super.operator >(anot); }

    public final boolean operator >=(Comparable anot) { return Comparable.super.operator >=(anot); }

    public final boolean operator <(Comparable anot) { return Comparable.super.operator <(anot); }

    public final boolean operator <=(Comparable anot) { return Comparable.super.operator <=(anot); }

    private String[] getAliases() {
        String[] result = fldAliases;
        int length = result.length;
        Array.copy(result, 0, result = new String[length], 0, length);
        return result;
    }
}