Package.avt

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

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

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

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

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

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

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

package avt.lang;

import avt.io.*;

public final class Package(/*Reflective*/Object)
{
    public static Package get(String canonicalName) throws PackageNotFoundException {
        Package result = find(canonicalName);
        if(result == null)
        {
            throw new PackageNotFoundException("пакет не найден");
        }
        return result;
    }

    public static Package[] enumerate() {
        int length = 1;
        Package[] result = new Package[15];
        for(Package current = (result[0] = boolean.class.ownedPackage).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 = boolean.class.ownedPackage;
        if(canonicalName == null || canonicalName.isEmpty()) return start;
        for(Package current = start.getNext(); current != null; current = current.getNext())
        {
            if(canonicalName.equals(current.getCanonicalName())) return current;
        }
        return null;
    }


    private final int fldModifiers;
    private final int fldCanonicalNameIndex;
    private final int fldReserved28;
    private final int fldReserved2C;
    private final int fldTypesCount;
    private final int fldReserved34;
    private final int fldReserved38;
    private final int fldReserved3C;
    private final int fldTypesOffset;
    private final int fldReserved44;
    private final int fldReserved48;
    private final int fldReserved4C;
    private final long fldNextPackageOffset;
    private int fldAddedTypesCount;
    private int fldReserved5C;
    private Class[] fldAddedTypes;
    private String fldCanonicalName;

    private () {  }

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

    public Class[] enumerateTypes() {
        int count = fldTypesCount;
        int length = 0;
        Class[] result = new Class[count];
        for(int index = 0; index < count; index++)
        {
            Class type = getType(index);
            if(type.isArray())
            {
                Class componentType = type.componentType;
                if(!componentType.isPrimitive() && componentType != Object.class) continue;
            }
            result[length++] = type;
        }
        if(length != count)
        {
            Array.copy(result, 0, result = new Class[length], 0, length);
        }
        return result;
    }

    public String[] enumerateResources() {
        int length = 0;
        String[] result = new String[15];
        for(String prefix = getResourcePrefix(), int offset = prefix.length, ResourceEnumerator e = new ResourceEnumerator(); e.hasMoreResources(); e.nextResource())
        {
            String current = e.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 ByteReader openResource(String name) {
        if(name == null)
        {
            throw new NullPointerException("аргумент name равен нулевой ссылке");
        }
        for(String prefix = getResourcePrefix(), int offset = prefix.length, int length = offset + name.length, ResourceEnumerator e = new ResourceEnumerator(); e.hasMoreResources(); e.nextResource())
        {
            String current = e.getName();
            if(current != null && current.length == length && current.startsWith(prefix) && current.endsWith(name))
            {
                return new ByteArrayInputStream(e.getData());
            }
        }
        return null;
    }

    public String simpleName { read = getSimpleName }

    public String canonicalName { read = getCanonicalName }

    package void addType(Class type) {
        int count = fldAddedTypesCount;
        Class[] types = fldAddedTypes;
        if(types == null)
        {
            fldAddedTypes = types = new Class[15];
        }
        else if(count == types.length)
        {
            Array.copy(types, 0, fldAddedTypes = types = new Class[(count << 1) + 1], 0, count);
        }
        types[count++] = type;
        fldAddedTypesCount = count;
    }

    package Class getAddedArrayType(Class componentType) {
        for(int count = fldAddedTypesCount, Class[] types = fldAddedTypes, int index = 0; index < count; index++)
        {
            Class type = types[index];
            if(type.isArray() && type.componentType == componentType) return type;
        }
        return null;
    }

    package Class findType(String simpleName) {
        if(simpleName != null) for(int count = fldTypesCount, int index = 0; index < count; index++)
        {
            Class type = getType(index);
            if(simpleName.equals(type.simpleName)) return type;
        }
        return null;
    }

    private native Package getNext();

    private native Class getType(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(fldCanonicalNameIndex);
    }

    private String getResourcePrefix() { return (new StringBuilder() + '/' + getCanonicalName().replace('.', '/') + '/').toString(); }
}

final class ResourceEnumerator(Object)
{
    private int fldDataLength;
    private int fldNameLength;
    private long fldResourcePointer;

    public () { initialize(); }

    public native void nextResource();

    public boolean hasMoreResources() { return fldNameLength > 0; }

    public byte[] getData() {
        if(fldNameLength <= 0) return null;
        long dataPointer = fldResourcePointer + fldNameLength + 2L;
        dataPointer += (-dataPointer & 3L) + 4L;
        byte[] result = null;
        try
        {
            result = (byte[]) byte[].class.newArrayAt(dataPointer, fldDataLength);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return result;
    }

    public String getName() {
        if(fldNameLength <= 0) return null;
        long namePointer = fldResourcePointer + 2L;
        byte[] result = null;
        try
        {
            result = (byte[]) byte[].class.newArrayAt(namePointer, fldNameLength);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return result == null ? null : new String(result);
    }

    private native void initialize();
}