/*
 * 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.
 */

/*
 * Functions for dealing with try-catch info.
 */

#ifndef _LIBDEX_DEXCATCH
#define _LIBDEX_DEXCATCH

#include "DexFile.h"
#include "Leb128.h"

/*
 * Catch handler entry, used while iterating over catch_handler_items.
 */
typedef struct DexCatchHandler {
    u4          typeIdx;    /* type index of the caught exception type */
    u4          address;    /* handler address */
} DexCatchHandler;

/* Get the first handler offset for the given DexCode. 
 * It's not 0 because the handlers list is prefixed with its size
 * (in entries) as a uleb128. */
u4 dexGetFirstHandlerOffset(const DexCode* pCode);

/* Get count of handler lists for the given DexCode. */
u4 dexGetHandlersSize(const DexCode* pCode);

/*
 * Iterator over catch handler data. This structure should be treated as
 * opaque.
 */
typedef struct DexCatchIterator {
    const u1* pEncodedData;
    bool catchesAll;
    u4 countRemaining;
    DexCatchHandler handler;
} DexCatchIterator;

/* Initialize a DexCatchIterator to emptiness. This mostly exists to
 * squelch innocuous warnings. */
DEX_INLINE void dexCatchIteratorClear(DexCatchIterator* pIterator) {
    pIterator->pEncodedData = NULL;
    pIterator->catchesAll = false;
    pIterator->countRemaining = 0;
    pIterator->handler.typeIdx = 0;
    pIterator->handler.address = 0;
}

/* Initialize a DexCatchIterator with a direct pointer to encoded handlers. */
DEX_INLINE void dexCatchIteratorInitToPointer(DexCatchIterator* pIterator,
    const u1* pEncodedData)
{
    s4 count = readSignedLeb128(&pEncodedData);

    if (count <= 0) {
        pIterator->catchesAll = true;
        count = -count;
    } else {
        pIterator->catchesAll = false;
    }

    pIterator->pEncodedData = pEncodedData;
    pIterator->countRemaining = count;
}

/* Initialize a DexCatchIterator to a particular handler offset. */
DEX_INLINE void dexCatchIteratorInit(DexCatchIterator* pIterator,
    const DexCode* pCode, u4 offset)
{
    dexCatchIteratorInitToPointer(pIterator,
            dexGetCatchHandlerData(pCode) + offset);
}    

/* Get the next item from a DexCatchIterator. Returns NULL if at end. */
DEX_INLINE DexCatchHandler* dexCatchIteratorNext(DexCatchIterator* pIterator) {
    if (pIterator->countRemaining == 0) {
        if (! pIterator->catchesAll) {
            return NULL;
        }

        pIterator->catchesAll = false;
        pIterator->handler.typeIdx = kDexNoIndex;
    } else {
        u4 typeIdx = readUnsignedLeb128(&pIterator->pEncodedData);
        pIterator->handler.typeIdx = typeIdx;
        pIterator->countRemaining--;
    }

    pIterator->handler.address = readUnsignedLeb128(&pIterator->pEncodedData);
    return &pIterator->handler;
}

/* Get the handler offset just past the end of the one just iterated over.
 * This ends the iteration if it wasn't already. */
u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator,
    const DexCode* pCode);

/* Helper for dexFindCatchHandler(). Do not call directly. */
int dexFindCatchHandlerOffset0(u2 triesSize, const DexTry* pTries,
        u4 address);

/* Find the handler associated with a given address, if any.
 * Initializes the given iterator and returns true if a match is
 * found. Returns false if there is no applicable handler. */
DEX_INLINE bool dexFindCatchHandler(DexCatchIterator *pIterator,
        const DexCode* pCode, u4 address) {
    u2 triesSize = pCode->triesSize; 
    int offset = -1;

    // Short-circuit the overwhelmingly common cases.
    switch (triesSize) {
        case 0: {
            break;
        }
        case 1: {
            const DexTry* tries = dexGetTries(pCode);
            u4 start = tries[0].startAddr;

            if (address < start) {
                break;
            }
        
            u4 end = start + tries[0].insnCount;

            if (address >= end) {
                break;
            }
        
            offset = tries[0].handlerOff;
            break;
        }
        default: {
            offset = dexFindCatchHandlerOffset0(triesSize, dexGetTries(pCode),
                    address);
        }
    }

    if (offset < 0) {
        dexCatchIteratorClear(pIterator); // This squelches warnings.
        return false;
    } else {
        dexCatchIteratorInit(pIterator, pCode, offset);
        return true;
    }
}    

#endif
