summaryrefslogblamecommitdiffstats
path: root/amend/symtab.c
blob: 835d2fc4092770f3f5f8ed18388591af5e07456a (plain) (tree)



































































































































                                                                           
/*
 * Copyright (C) 2007 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.
 */

#include <stdlib.h>
#include <string.h>
#include "symtab.h"

#define DEFAULT_TABLE_SIZE 16

typedef struct {
    char *symbol;
    const void *cookie;
    unsigned int flags;
} SymbolTableEntry;

struct SymbolTable {
    SymbolTableEntry *table;
    int numEntries;
    int maxSize;
};

SymbolTable *
createSymbolTable()
{
    SymbolTable *tab;

    tab = (SymbolTable *)malloc(sizeof(SymbolTable));
    if (tab != NULL) {
        tab->numEntries = 0;
        tab->maxSize = DEFAULT_TABLE_SIZE;
        tab->table = (SymbolTableEntry *)malloc(
                            tab->maxSize * sizeof(SymbolTableEntry));
        if (tab->table == NULL) {
            free(tab);
            tab = NULL;
        }
    }
    return tab;
}

void
deleteSymbolTable(SymbolTable *tab)
{
    if (tab != NULL) {
        while (tab->numEntries > 0) {
            free(tab->table[--tab->numEntries].symbol);
        }
        free(tab->table);
    }
}

void *
findInSymbolTable(SymbolTable *tab, const char *symbol, unsigned int flags)
{
    int i;

    if (tab == NULL || symbol == NULL) {
        return NULL;
    }

    // TODO: Sort the table and binary search
    for (i = 0; i < tab->numEntries; i++) {
        if (strcmp(tab->table[i].symbol, symbol) == 0 &&
                tab->table[i].flags == flags)
        {
            return (void *)tab->table[i].cookie;
        }
    }

    return NULL;
}

int
addToSymbolTable(SymbolTable *tab, const char *symbol, unsigned int flags,
        const void *cookie)
{
    if (tab == NULL || symbol == NULL || cookie == NULL) {
        return -1;
    }

    /* Make sure that this symbol isn't already in the table.
     */
    if (findInSymbolTable(tab, symbol, flags) != NULL) {
        return -2;
    }

    /* Make sure there's enough space for the new entry.
     */
    if (tab->numEntries == tab->maxSize) {
        SymbolTableEntry *newTable;
        int newSize;

        newSize = tab->numEntries * 2;
        if (newSize < DEFAULT_TABLE_SIZE) {
            newSize = DEFAULT_TABLE_SIZE;
        }
        newTable = (SymbolTableEntry *)realloc(tab->table,
                            newSize * sizeof(SymbolTableEntry));
        if (newTable == NULL) {
            return -1;
        }
        tab->maxSize = newSize;
        tab->table = newTable;
    }

    /* Insert the new entry.
     */
    symbol = strdup(symbol);
    if (symbol == NULL) {
        return -1;
    }
    // TODO: Sort the table
    tab->table[tab->numEntries].symbol = (char *)symbol;
    tab->table[tab->numEntries].cookie = cookie;
    tab->table[tab->numEntries].flags = flags;
    tab->numEntries++;

    return 0;
}