/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * java.lang.reflect.Array
 */
#include "Dalvik.h"
#include "native/InternalNativePriv.h"


/*
 * private static Object createObjectArray(Class<?> componentType,
 *     int length) throws NegativeArraySizeException;
 *
 * Create a one-dimensional array of Objects.
 */
static void Dalvik_java_lang_reflect_Array_createObjectArray(const u4* args,
    JValue* pResult)
{
    ClassObject* elementClass = (ClassObject*) args[0];
    int length = args[1];
    ArrayObject* newArray;

    assert(elementClass != NULL);       // tested by caller
    if (length < 0) {
        dvmThrowException("Ljava/lang/NegativeArraySizeException;", NULL);
        RETURN_VOID();
    }

    newArray = dvmAllocObjectArray(elementClass, length, ALLOC_DEFAULT);
    if (newArray == NULL) {
        assert(dvmCheckException(dvmThreadSelf()));
        RETURN_VOID();
    }
    dvmReleaseTrackedAlloc((Object*) newArray, NULL);

    RETURN_PTR(newArray);
}

/*
 * private static Object createMultiArray(Class<?> componentType,
 *     int[] dimensions) throws NegativeArraySizeException;
 *
 * Create a multi-dimensional array of Objects or primitive types.
 *
 * We have to generate the names for X[], X[][], X[][][], and so on.  The
 * easiest way to deal with that is to create the full name once and then
 * subtract pieces off.  Besides, we want to start with the outermost
 * piece and work our way in.
 */
static void Dalvik_java_lang_reflect_Array_createMultiArray(const u4* args,
    JValue* pResult)
{
    static const char kPrimLetter[] = PRIM_TYPE_TO_LETTER;
    ClassObject* elementClass = (ClassObject*) args[0];
    ArrayObject* dimArray = (ArrayObject*) args[1];
    ClassObject* arrayClass;
    ArrayObject* newArray;
    char* acDescriptor;
    int numDim, i;
    int* dimensions;

    LOGV("createMultiArray: '%s' [%d]\n",
        elementClass->descriptor, dimArray->length);

    assert(elementClass != NULL);       // verified by caller

    /*
     * Verify dimensions.
     *
     * The caller is responsible for verifying that "dimArray" is non-null
     * and has a length > 0 and <= 255.
     */
    assert(dimArray != NULL);           // verified by caller
    numDim = dimArray->length;
    assert(numDim > 0 && numDim <= 255);

    dimensions = (int*) dimArray->contents;
    for (i = 0; i < numDim; i++) {
        if (dimensions[i] < 0) {
            dvmThrowException("Ljava/lang/NegativeArraySizeException;", NULL);
            RETURN_VOID();
        }
        LOGVV("DIM %d: %d\n", i, dimensions[i]);
    }

    /*
     * Generate the full name of the array class.
     */
    acDescriptor =
        (char*) malloc(strlen(elementClass->descriptor) + numDim + 1);
    memset(acDescriptor, '[', numDim);

    LOGVV("#### element name = '%s'\n", elementClass->descriptor);
    if (dvmIsPrimitiveClass(elementClass)) {
        assert(elementClass->primitiveType >= 0);
        acDescriptor[numDim] = kPrimLetter[elementClass->primitiveType];
        acDescriptor[numDim+1] = '\0';
    } else {
        strcpy(acDescriptor+numDim, elementClass->descriptor);
    }
    LOGVV("#### array name = '%s'\n", acDescriptor);

    /*
     * Find/generate the array class.
     */
    arrayClass = dvmFindArrayClass(acDescriptor, elementClass->classLoader);
    if (arrayClass == NULL) {
        LOGW("Unable to find or generate array class '%s'\n", acDescriptor);
        assert(dvmCheckException(dvmThreadSelf()));
        free(acDescriptor);
        RETURN_VOID();
    }
    free(acDescriptor);

    /* create the array */
    newArray = dvmAllocMultiArray(arrayClass, numDim-1, dimensions);
    if (newArray == NULL) {
        assert(dvmCheckException(dvmThreadSelf()));
        RETURN_VOID();
    }

    dvmReleaseTrackedAlloc((Object*) newArray, NULL);
    RETURN_PTR(newArray);
}

const DalvikNativeMethod dvm_java_lang_reflect_Array[] = {
    { "createObjectArray",  "(Ljava/lang/Class;I)Ljava/lang/Object;",
        Dalvik_java_lang_reflect_Array_createObjectArray },
    { "createMultiArray",   "(Ljava/lang/Class;[I)Ljava/lang/Object;",
        Dalvik_java_lang_reflect_Array_createMultiArray },
    { NULL, NULL, NULL },
};

