nexmon – Rev 1

Subversion Repositories:
Rev:
/*
 * Copyright 2008-2009 Katholieke Universiteit Leuven
 *
 * Use of this software is governed by the GNU LGPLv2.1 license
 *
 * Written by Sven Verdoolaege, K.U.Leuven, Departement
 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
 */

#include <string.h>
#include <isl_ctx_private.h>
#include <isl_id_private.h>

/* A special, static isl_id to use as domains (and ranges)
 * of sets and parameters domains.
 * The user should never get a hold on this isl_id.
 */
isl_id isl_id_none = {
        .ref = -1,
        .ctx = NULL,
        .name = "#none",
        .user = NULL
};

isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id)
{
        return id ? id->ctx : NULL;
}

void *isl_id_get_user(__isl_keep isl_id *id)
{
        return id ? id->user : NULL;
}

const char *isl_id_get_name(__isl_keep isl_id *id)
{
        return id ? id->name : NULL;
}

static __isl_give isl_id *id_alloc(isl_ctx *ctx, const char *name, void *user)
{
        const char *copy = name ? strdup(name) : NULL;
        isl_id *id;

        if (name && !copy)
                return NULL;
        id = isl_alloc_type(ctx, struct isl_id);
        if (!id)
                goto error;

        id->ctx = ctx;
        isl_ctx_ref(id->ctx);
        id->ref = 1;
        id->name = copy;
        id->user = user;

        id->hash = isl_hash_init();
        if (name)
                id->hash = isl_hash_string(id->hash, name);
        else
                id->hash = isl_hash_builtin(id->hash, user);

        return id;
error:
        free((char *)copy);
        return NULL;
}

struct isl_name_and_user {
        const char *name;
        void *user;
};

static int isl_id_has_name_and_user(const void *entry, const void *val)
{
        isl_id *id = (isl_id *)entry;
        struct isl_name_and_user *nu = (struct isl_name_and_user *) val;

        if (id->user != nu->user)
                return 0;
        if (!id->name && !nu->name)
                return 1;

        return !strcmp(id->name, nu->name);
}

__isl_give isl_id *isl_id_alloc(isl_ctx *ctx, const char *name, void *user)
{
        struct isl_hash_table_entry *entry;
        uint32_t id_hash;
        struct isl_name_and_user nu = { name, user };

        id_hash = isl_hash_init();
        if (name)
                id_hash = isl_hash_string(id_hash, name);
        else
                id_hash = isl_hash_builtin(id_hash, user);
        entry = isl_hash_table_find(ctx, &ctx->id_table, id_hash,
                                        isl_id_has_name_and_user, &nu, 1);
        if (!entry)
                return NULL;
        if (entry->data)
                return isl_id_copy(entry->data);
        entry->data = id_alloc(ctx, name, user);
        if (!entry->data)
                ctx->id_table.n--;
        return entry->data;
}

/* If the id has a negative refcount, then it is a static isl_id
 * which should not be changed.
 */
__isl_give isl_id *isl_id_copy(isl_id *id)
{
        if (!id)
                return NULL;

        if (id->ref < 0)
                return id;

        id->ref++;
        return id;
}

static int isl_id_eq(const void *entry, const void *name)
{
        return entry == name;
}

uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id)
{
        if (id)
                isl_hash_hash(hash, id->hash);

        return hash;
}

/* If the id has a negative refcount, then it is a static isl_id
 * and should not be freed.
 */
void *isl_id_free(__isl_take isl_id *id)
{
        struct isl_hash_table_entry *entry;

        if (!id)
                return NULL;

        if (id->ref < 0)
                return NULL;

        if (--id->ref > 0)
                return NULL;

        entry = isl_hash_table_find(id->ctx, &id->ctx->id_table, id->hash,
                                        isl_id_eq, id, 0);
        if (!entry)
                isl_die(id->ctx, isl_error_unknown,
                        "unable to find id", (void)0);
        else
                isl_hash_table_remove(id->ctx, &id->ctx->id_table, entry);

        free((char *)id->name);
        isl_ctx_deref(id->ctx);
        free(id);

        return NULL;
}

__isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p,
        __isl_keep isl_id *id)
{
        if (!id)
                goto error;

        if (id->name)
                p = isl_printer_print_str(p, id->name);
        if (id->user) {
                char buffer[50];
                snprintf(buffer, sizeof(buffer), "@%p", id->user);
                p = isl_printer_print_str(p, buffer);
        }
        return p;
error:
        isl_printer_free(p);
        return NULL;
}