Package.avt

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

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

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

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

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

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

package avt.lang;

import avt.io.*;
import avt.io.charset.*;

public final class Package(RequiredReflectiveObject)
{
    public static Package get(String canonicalName) throws PackageNotFoundException {
        Package result = find(canonicalName);
        if(result == null)
        {
            throw new PackageNotFoundException(String.format(package.getResourceString("not-found.package"), new Object[] { canonicalName }));
        }
        return result;
    }

    public static Package[] enumerate() {
        int length = 1;
        Package[] result = new Package[0x0fi];
        for(Package current = (result[0] = void.class.parentPackage).getNext(); current != null; current = current.getNext())
        {
            if(length == result.length)
            {
                Array.copy(result, 0, result = new Package[length << 1 | 1], 0, length);
            }
            result[length++] = current;
        }
        if(length != result.length)
        {
            Array.copy(result, 0, result = new Package[length], 0, length);
        }
        return result;
    }

    package static Package find(String canonicalName) {
        Package start = void.class.parentPackage;
        if(canonicalName == null || canonicalName.isEmpty())
        {
            return start;
        }
        for(Package current = start.getNext(); current != null; current = current.getNext()) if(canonicalName.equals(current.canonicalName))
        {
            return current;
        }
        return null;
    }

    private static void writeChar(StringBuilder dst, int b0, int b1, int b2) {
        switch(b0 >> 4)
        {
        default:
            dst + (char) b0;
            break;
        case 0x08:
        case 0x09:
        case 0x0a:
        case 0x0b:
            dst + (char) (b0 & 0x3f);
            break;
        case 0x0c:
        case 0x0d:
            dst + (char) ((b0 & 0x1f) << 6 | (b1 & 0x3f));
            break;
        case 0x0e:
        case 0x0f:
            dst + (char) ((b0 & 0x0f) << 12 | (b1 & 0x3f) << 6 | (b2 & 0x3f));
        }
    }

    private final int fldReserved28;
    private final int fldReserved2C;
    private final int fldReserved30;
    private final int fldReserved34;
    private final int fldReserved38;
    private final int fldDeclaredTypesCount;
    private final int fldReserved40;
    private final int fldReserved44;
    private final int fldReserved48;
    private final int fldReserved4C;
    private final int fldReserved50;
    private final int fldReserved54;
    private final int fldReserved58;
    private final int fldDeclaredTypesOffset;
    private final int fldReserved60;
    private final int fldReserved64;
    private final int fldReserved68;
    private final int fldReserved6C;
    private final int fldReserved70;
    private final int fldReserved74;
    private final int fldReserved78;
    private final int fldReserved7C;
    private final long fldReserved80;
    private final long fldReserved88;
    private final long fldNextPackageOffset;
    private final long fldReserved98;
    private final long fldReservedA0;
    private final long fldReservedA8;
    private final long fldReservedB0;
    private final int fldReservedB8;
    private final int fldRequiredReflectiveObjectSize;
    private int fldAddedTypesLength;
    private Class[] fldAddedTypesArray;
    private String fldCanonicalName;
    private String fldSimpleName;

    private () {  }

    public boolean isAbstract() { return false; }

    public boolean isFinal() { return false; }

    public String toString() { return "package " + getCanonicalName(); }

    public Class[] enumerateTypes() {
        int lengthDeclared = fldDeclaredTypesCount;
        int lengthResult = 0;
        Class[] result = new Class[lengthDeclared];
        for(int index = 0; index < lengthDeclared; index++)
        {
            Class current = getDeclaredType(index);
            if(current.isArray())
            {
                Class component = current.componentType;
                if(!component.isPrimitive() && component != Object.class) continue;
            }
            result[lengthResult++] = current;
        }
        if(lengthDeclared != lengthResult)
        {
            Array.copy(result, 0, result = new Class[lengthResult], 0, lengthResult);
        }
        return result;
    }

    public String[] enumerateResources() {
        int length = 0;
        String[] result = new String[0x0fi];
        for(String prefix = getResourcePrefix(), int offset = prefix.length, ResourceEnumerator resEnum = new ResourceEnumerator(); resEnum.hasMoreResources(); resEnum.nextResource())
        {
            String current = resEnum.getName();
            if(current != null && current.startsWith(prefix))
            {
                if(length == result.length)
                {
                    Array.copy(result, 0, result = new String[length << 1 | 1], 0, length);
                }
                result[length++] = current.substring(offset);
            }
        }
        if(length != result.length)
        {
            Array.copy(result, 0, result = new String[length], 0, length);
        }
        return result;
    }

    public String getResourceString(String name) {
        if(name == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "name" }));
        }
        ByteArrayInputStream stream = createResourceStream(name + ".txt");
        if(stream == null) return null;
        StringBuilder result = new StringBuilder();
        label0: for(int b0 = 0, int b1 = 0, int br = 0; ; )
        {
            int bt = stream.read();
            switch(bt >> 4)
            {
            default:
                if(br > 0) writeChar(result, b0, br > 1 ? b1 : 0, 0);
                break label0;
            case 0x00:
            case 0x01:
            case 0x02:
            case 0x03:
            case 0x04:
            case 0x05:
            case 0x06:
            case 0x07:
                if(br > 0) writeChar(result, b0, br > 1 ? b1 : 0, 0);
                writeChar(result, bt, 0, 0);
                br = 0;
                break;
            case 0x0c:
            case 0x0d:
            case 0x0e:
            case 0x0f:
                if(br > 0) writeChar(result, b0, br > 1 ? b1 : 0, 0);
                b0 = bt;
                br = 1;
                break;
            case 0x08:
            case 0x09:
            case 0x0a:
            case 0x0b:
                switch(br)
                {
                default:
                    writeChar(result, bt, 0, 0);
                    break;
                case 1:
                    if((b0 >> 4) < 0x0e)
                    {
                        writeChar(result, b0, bt, 0);
                        br = 0;
                        break;
                    }
                    b1 = bt;
                    br = 2;
                    break;
                case 2:
                    br = 0;
                    if((b0 >> 4) < 0x0e)
                    {
                        writeChar(result, b0, b1, 0);
                        writeChar(result, bt, 0, 0);
                        break;
                    }
                    writeChar(result, b0, b1, bt);
                }
            }
        }
        return result.toString();
    }

    public String getResourceString(String name, Charset charset) {
        if(name == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "name" }));
        }
        ByteArrayInputStream stream = createResourceStream(name + ".txt");
        if(stream == null) return null;
        int length = (int) stream.size();
        byte[] bytes = new byte[length];
        stream.read(bytes, 0, length);
        return new String((charset != null ? charset : Charset.getDefault()).decode(bytes, 0, length));
    }

    public String getResourceString(String name, CharDecoder decoder) throws CharacterDecodingException {
        if(name == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "name" }));
        }
        ByteArrayInputStream stream = createResourceStream(name + ".txt");
        if(stream == null) return null;
        int length = (int) stream.size();
        byte[] bytes = new byte[length];
        stream.read(bytes, 0, length);
        return new String((decoder != null ? decoder : Charset.getDefault().newDecoder()).decode(bytes, 0, length));
    }

    public ByteReader openResource(String name) {
        if(name == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "name" }));
        }
        return createResourceStream(name);
    }

    public String simpleName { read = getSimpleName }

    public String canonicalName { read = getCanonicalName }

    package void addArrayType(Class type) {
        int length = fldAddedTypesLength;
        Class[] array = fldAddedTypesArray;
        if(array == null)
        {
            fldAddedTypesArray = array = new Class[0x0fi];
        }
        else if(length == array.length)
        {
            Array.copy(array, 0, fldAddedTypesArray = array = new Class[length << 1 | 1], 0, length);
        }
        array[length++] = type;
        fldAddedTypesLength = length;
    }

    package Class findAddedArrayType(Class componentType) {
        if(componentType != null) for(Class[] array = fldAddedTypesArray, int length = fldAddedTypesLength, int index = 0; index < length; index++)
        {
            Class current = array[index];
            if(componentType == current.componentType) return current;
        }
        return null;
    }

    package Class findDeclaredType(String simpleName) {
        if(simpleName != null) for(int length = fldDeclaredTypesCount, int index = 0; index < length; index++)
        {
            Class current = getDeclaredType(index);
            if(simpleName.equals(current.simpleName)) return current;
        }
        return null;
    }

    private native Class getDeclaredType(int index);

    private String getSimpleName() {
        String canonicalName = getCanonicalName();
        return canonicalName.substring(canonicalName.lastIndexOf('.') + 1);
    }

    private String getCanonicalName() {
        String result = fldCanonicalName;
        return result != null ? result : fldCanonicalName = String.getConstant(fldNameIndex);
    }

    private String getResourcePrefix() {
        String canonicalName = getCanonicalName();
        return canonicalName.isEmpty() ? "/" : (new StringBuilder() + '/' + canonicalName.replaceAll('.', '/') + '/').toString();
    }

    private native Package getNext();

    private ByteArrayInputStream createResourceStream(String name) {
        if(!name.startsWith("/"))
        {
            name = getResourcePrefix() + name;
        }
        for(int nameLength = name.length, int nameHash = name.hashCode(), ResourceEnumerator resEnum = new ResourceEnumerator(); resEnum.hasMoreResources(); resEnum.nextResource())
        {
            if(nameLength == resEnum.nameLength && nameHash == resEnum.nameHash && name.equals(resEnum.getName())) return new ByteArrayInputStream(resEnum.getData());
        }
        return null;
    }
}

class ResourceEnumerator(Object)
{
    private int fldNameHash;
    private int fldNameLength;
    private int fldDataLength;
    private long fldNamePointer;
    private long fldDataPointer;
    private long fldResourcePointer;

    public () { initialize(); }

    public native void nextResource();

    public boolean hasMoreResources() { return fldNameHash != 0; }

    public byte[] getData() {
        if(fldNameHash == 0) return null;
        byte[] result = null;
        try
        {
            result = (byte[]) byte[].class.newArrayAt(fldDataPointer, fldDataLength);
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }
        return result;
    }

    public String getName() {
        if(fldNameHash == 0) return null;
        char[] nameChars = null;
        try
        {
            for(byte[] nameBytes = (byte[]) byte[].class.newArrayAt(fldNamePointer, fldNameLength), int index = nameBytes.length, nameChars = new char[index]; index-- > 0; )
            {
                nameChars[index] = (char) (nameBytes[index] & 0xffi);
            }
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }
        return nameChars == null ? null : new String(nameChars);
    }

    public int nameHash { read = fldNameHash }

    public int nameLength { read = fldNameLength }

    public int dataLength { read = fldDataLength }

    private native void initialize();
}