Charset.avt

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

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

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

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

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

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

package avt.io.charset;

import avt.lang.array.*;
import avt.lang.table.*;
import platform.dependent.*;

public abstract class Charset(Object, Comparable)
{
    private static int count;
    private static Charset[] charsets;

    private static final Charset utf8;
    private static final Charset consoleInput;
    private static final Charset consoleOutput;
    private static final String inputCharsetName;
    private static final String outputCharsetName;
    private static final KeyValueTable registered;

    public static {
        registered = new KeyValueTable();
        charsets = new Charset[0x0fi];
        for(String packPrefix = "avt.io.charset.", Package[] packs = Package.enumerate(), int packIndex = packs.length; packIndex-- > 0; )
        {
            Package pack = packs[packIndex];
            if(pack.canonicalName.startsWith(packPrefix)) for(Class[] types = pack.enumerateTypes(), int typeIndex = types.length; typeIndex-- > 0; )
            {
                Class type = types[typeIndex];
                if(!type.isAbstract() && type.visibility >= ReflectiveObject.PUBLIC && Charset.class.isAssignableFrom(type))
                {
                    try
                    {
                        registerCharset((Charset) type.newInstance());
                    }
                    catch(Exception exception)
                    {
                        exception.printStackTrace();
                    }
                }
            }
        }
        utf8 = getCharset("UTF-8");
        ProcessEnvironment env = System.getCurrentProcessEnv();
        consoleInput = getCharset(inputCharsetName = env.consoleInputCharsetName);
        consoleOutput = getCharset(outputCharsetName = env.consoleOutputCharsetName);
    }

    public static void register(Charset charset) throws RegisteredCharsetNameException {
        if(charset == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "charset" }));
        }
        String charsetName = null;
        synchronized(registered)
        {
            label0:
            {
                String currentName;
                if(registered.contains(currentName = charset.fldName))
                {
                    charsetName = currentName;
                    break label0;
                }
                for(String[] aliases = charset.fldAliases, int index = aliases.length; index-- > 0; ) if(registered.contains(currentName = aliases[index]))
                {
                    charsetName = currentName;
                    break label0;
                }
                registerCharset(charset);
            }
        }
        if(charsetName != null)
        {
            throw new RegisteredCharsetNameException(package.getResourceString("registered-charset-name")) { charsetName = charsetName };
        }
    }

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

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

    public static Charset getDefault() { return utf8; }

    public static Charset getConsoleInput() throws UnsupportedCharsetNameException {
        if(consoleInput == null)
        {
            throw new UnsupportedCharsetNameException(package.getResourceString("unsupported-charset-name")) { charsetName = inputCharsetName };
        }
        return consoleInput;
    }

    public static Charset getConsoleOutput() throws UnsupportedCharsetNameException {
        if(consoleOutput == null)
        {
            throw new UnsupportedCharsetNameException(package.getResourceString("unsupported-charset-name")) { charsetName = outputCharsetName };
        }
        return consoleOutput;
    }

    public static Charset get(String charsetName) throws UnsupportedCharsetNameException {
        if(charsetName == null) charsetName = "";
        Charset result = (Charset) registered[charsetName];
        if(result == null)
        {
            throw new UnsupportedCharsetNameException(package.getResourceString("unsupported-charset-name")) { charsetName = charsetName };
        }
        return result;
    }

    private static void registerCharset(Charset charset) {
        if(count == Int.MAX_VALUE)
        {
            throw new BufferTooLargeError(avt.lang.package.getResourceString("!error.buffer-too-large"));
        }
        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 index = aliases.length; index-- > 0; ) registered[aliases[index]] = charset;
    }

    private static Charset getCharset(String charsetName) { return (Charset) registered[charsetName == null ? "" : charsetName]; }

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

    protected (String name, String[] aliases) {
        int alength = aliases == null ? 0 : aliases.length;
        String charsetName = name == null ? "" : name;
        String[] charsetAliases = new String[alength];
        label0: for(int length = alength, alength = 0, int ali = 0; ali < length; ali++)
        {
            String alias = aliases[ali];
            if(alias == null || alias.equals(charsetName))
            {
                continue label0;
            }
            for(int alj = alength; alj-- > 0; ) if(alias.equals(charsetAliases[alj]))
            {
                continue label0;
            }
            charsetAliases[alength++] = alias;
        }
        if(alength != charsetAliases.length)
        {
            Array.copy(charsetAliases, 0, charsetAliases = new String[alength], 0, alength);
        }
        charsetAliases.finalize();
        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(charsetName == null)
        {
            charsetName = "";
        }
        if(fldName.equals(charsetName))
        {
            return true;
        }
        for(String[] aliases = fldAliases, int index = aliases.length; index-- > 0; ) if(aliases[index].equals(charsetName))
        {
            return true;
        }
        return false;
    }

    public final char[] decode(ByteArray src) {
        try
        {
            return newDecoder().decode(src);
        }
        catch(Exception exception)
        {
            throw exception instanceof RuntimeException ? (RuntimeException) exception : new UnsupportedOperationException(exception.message, exception);
        }
    }

    public final char[] decode(ByteArray src, int offset, int length) {
        try
        {
            return newDecoder().decode(src, offset, length);
        }
        catch(Exception exception)
        {
            throw exception instanceof RuntimeException ? (RuntimeException) exception : new UnsupportedOperationException(exception.message, exception);
        }
    }

    public final byte[] encode(CharArray src) {
        try
        {
            return newEncoder().encode(src);
        }
        catch(Exception exception)
        {
            throw exception instanceof RuntimeException ? (RuntimeException) exception : new UnsupportedOperationException(exception.message, exception);
        }
    }

    public final byte[] encode(CharArray src, int offset, int length) {
        try
        {
            return newEncoder().encode(src, offset, length);
        }
        catch(Exception exception)
        {
            throw exception instanceof RuntimeException ? (RuntimeException) exception : new UnsupportedOperationException(exception.message, exception);
        }
    }

    public final String[] aliases { read = fldAliases }

    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); }
}