All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aion.avm.ArrayRenamer Maven / Gradle / Ivy

There is a newer version: 0.9.6
Show newest version
package org.aion.avm;

import i.PackageConstants;
import i.RuntimeAssertionError;

public final class ArrayRenamer {
    private static final String BASIC_DOT_WRAPPER = PackageConstants.kArrayWrapperDotPrefix;
    private static final String BASIC_SLASH_WRAPPER = PackageConstants.kArrayWrapperSlashPrefix;
    private static final String UNIFYING_DOT_WRAPPER = PackageConstants.kArrayWrapperUnifyingDotPrefix;
    private static final String UNIFYING_SLASH_WRAPPER = PackageConstants.kArrayWrapperUnifyingSlashPrefix;

    /**
     * Returns {@code name} but with the array wrapper prefix prepended to it.
     *
     * This is the basic array wrapper prefix, not the prefix used for unifying-type object arrays.
     * Use the {@code prependUnifyingArrayWrapperPrefix()} method for that.
     *
     * @param style The naming convention of name.
     * @param name The name to prepend.
     * @return name prepended with the array wrapper prefix.
     */
    public static String prependArrayWrapperPrefix(NameStyle style, String name) {
        RuntimeAssertionError.assertTrue(style != null);
        RuntimeAssertionError.assertTrue(name != null);
        return ((style == NameStyle.DOT_NAME) ? BASIC_DOT_WRAPPER : BASIC_SLASH_WRAPPER) + name;
    }

    /**
     * Returns {@code name} but with the unifying-type object array wrapper prefix prepended to it.
     *
     * This is not the basic array wrapper prefix. Use the {@code prependArrayWrapperPrefix()}
     * method for that.
     *
     * @param style The naming convention of name.
     * @param name The name to prepend.
     * @return name prepended with the unifying-type object array wrapper prefix.
     */
    public static String prependUnifyingArrayWrapperPrefix(NameStyle style, String name) {
        RuntimeAssertionError.assertTrue(style != null);
        RuntimeAssertionError.assertTrue(name != null);
        return ((style == NameStyle.DOT_NAME) ? UNIFYING_DOT_WRAPPER : UNIFYING_SLASH_WRAPPER) + name;
    }

    /**
     * Returns the provided underlyingType prepended with a prefix that denotes the following:
     *
     * 1. the dimension of the array is equal to {@code dimension}.
     * 2. the array is a 'concrete type' object array.
     *
     * @param style The naming convention of name.
     * @param underlyingType The underlying type to be wrapped in the array.
     * @param dimension The dimension of the array.
     * @return underlyingType prepended with the concrete-type object array wrapper prefix denoting dimensionality.
     */
    public static String wrapAsConcreteObjectArray(NameStyle style, String underlyingType, int dimension) {
        RuntimeAssertionError.assertTrue(underlyingType != null);

        if (dimension > 0) {
            String unwrappedName = stringOfSameCharacter('$', dimension) + "L" + underlyingType;
            return prependArrayWrapperPrefix(style, unwrappedName);
        } else {
            throw RuntimeAssertionError.unreachable("Expected dimension of at least 1: " + dimension);
        }
    }

    /**
     * Returns the provided underlyingType prepended with a prefix that denotes the following:
     *
     * 1. the dimension of the array is equal to {@code dimension}.
     * 2. the array is a 'unifying type' object array.
     *
     * @param style The naming convention of name.
     * @param underlyingType The underlying type to be wrapped in the array.
     * @param dimension The dimension of the array.
     * @return underlyingType prepended with the unifying-type object array wrapper prefix denoting dimensionality.
     */
    public static String wrapAsUnifyingObjectArray(NameStyle style, String underlyingType, int dimension) {
        RuntimeAssertionError.assertTrue(underlyingType != null);

        if (dimension > 0) {
            String unwrappedName = stringOfSameCharacter('_', dimension) + "L" + underlyingType;
            return prependUnifyingArrayWrapperPrefix(style, unwrappedName);
        } else {
            throw RuntimeAssertionError.unreachable("Expected dimension of at least 1: " + dimension);
        }
    }

    /**
     * Returns array but with the array wrapper prefix stripped from it. Note that if the prefix is
     * the unifying-type array prefix or the basic prefix it does not matter, either one is eligible
     * for this method and either one will be removed if supplied.
     *
     * @param style The naming convention of name.
     * @param array The array whose wrapper prefix is to be stripped.
     * @return array without the array wrapper prefix.
     */
    public static String stripArrayWrapperPrefix(NameStyle style, String array) {
        RuntimeAssertionError.assertTrue(style != null);
        RuntimeAssertionError.assertTrue(array != null);

        String basicPrefix = (style == NameStyle.DOT_NAME) ? BASIC_DOT_WRAPPER : BASIC_SLASH_WRAPPER;
        String unifyingPrefix = (style == NameStyle.DOT_NAME) ? UNIFYING_DOT_WRAPPER : UNIFYING_SLASH_WRAPPER;

        // Check the unifying prefix first since the basic is a prefix itself of the unifying prefix!
        if (array.startsWith(unifyingPrefix)) {
            return array.substring(unifyingPrefix.length());
        } else if (array.startsWith(basicPrefix)) {
            return array.substring(basicPrefix.length());
        } else {
            throw RuntimeAssertionError.unreachable("Expected an array wrapper: " + array);
        }
    }

    /**
     * Returns name of the object that the given array is an array of. That is, if array is an array
     * of some type T then this method returns T (more precisely, the name of T).
     *
     * This is not equivalent to stripping the array wrapper prefix, since the stripped name may
     * still contain meta-data (for example, some leading tokens that describe the dimensionality
     * of the array) relating to the underlying type, whereas this method simply returns the
     * underlying type itself.
     *
     * Note that array must be an array wrapper (that is, a post-rename array).
     *
     * @param style The naming convention of name.
     * @param array The array whose underlying type's name is to be returned.
     * @return the underlying array type's name.
     */
    public static String getPostRenameObjectArrayWrapperUnderlyingTypeName(NameStyle style, String array) {
        RuntimeAssertionError.assertTrue(ArrayUtil.isPostRenameObjectArray(style, array));

        int dimension = ArrayUtil.dimensionOfPostRenameObjectArray(style, array);
        String strippedName = stripArrayWrapperPrefix(style, array);

        // Remove the leading dimension-characters and the 'L' character that follows them.
        return strippedName.substring(dimension + 1);
    }

    /**
     * Returns the name of the object that the given array is an array of. That is, if array is an
     * array of some type T then this method returns T (more precisely, the name of T).
     *
     * @param array The pre-rename object array.
     * @return the underlying type.
     */
    public static String getPreRenameObjectArrayWrapperUnderlyingTypeName(String array) {
        RuntimeAssertionError.assertTrue(ArrayUtil.isPreRenameObjectArray(array));

        int dimension = ArrayUtil.dimensionOfPreRenameObjectArray(array);

        // The +1 is to account for the 'L' preceding the type name.
        return array.substring(dimension + 1);
    }

    /**
     * Returns a pre-rename object array that is an array of the given base type, with the given
     * dimensionality.
     *
     * @param baseType The base type to make an array of.
     * @param dimension The dimension of the array.
     * @return the pre-rename object array.
     */
    public static String prependPreRenameObjectArrayPrefix(String baseType, int dimension) {
        String leadingDimensionChars = stringOfSameCharacter('[', dimension);
        return leadingDimensionChars + "L" + baseType;
    }

    /**
     * Returns a string of length {@code length}, each of whose characters is the same: namely, each
     * character is {@code character}.
     */
    private static String stringOfSameCharacter(char character, int length) {
        if (character == '$') {
            return new String(new char[length]).replaceAll("\0", "\\$");
        } else if (character == '[') {
            return new String(new char[length]).replaceAll("\0", "\\[");
        } else {
            return new String(new char[length]).replaceAll("\0", String.valueOf(character));
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy