/*
  attr.c
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif

#include "iiimcfint.h"

IIIMF_status
iiimcf_create_attr(
    IIIMCF_attr *pattr
)
{
    IIIMCF_attr_rec *pa;

    pa = (IIIMCF_attr_rec*) malloc(sizeof(*pa));
    if (!pa) return IIIMF_STATUS_MALLOC;
    memset(pa, 0, sizeof(*pa));

    *pattr = pa;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_destroy_attr(
    IIIMCF_attr attr
)
{
    IIIMCF_attr_rec *pa = (IIIMCF_attr_rec*) attr;

    if (pa->pslots) free(pa->pslots);
    free(pa);
    return IIIMF_STATUS_SUCCESS;
}

/* Find the slots that correcpoinds to "property".
   If it fails, return NULL.  */
static IIIMCF_attr_slot*
find_slot(
    IIIMCF_attr_rec *pa,
    int property
)
{
    int i, size;
    IIIMCF_attr_slot *pst;

    if (!pa) return NULL;
    size = pa->nprops;
    pst = pa->pslots;
    for (i = 0; i < size; i++, pst++) {
	if (pst->idx == property) {
	    return pst;
	}
    }

    return NULL;
}

/* allocate a new slot.  If it can do so, return a pointer of the slot;
   otherwise, return NULL */
static IIIMCF_attr_slot*
alloc_slot(
    IIIMCF_attr_rec *pa,
    int property
)
{
    int i, size;
    IIIMCF_attr_slot *pst;

    size = pa->nprops;
    pst = pa->pslots;
    for (i = 0; i < size; i++, pst++) {
	if (pst->idx == property) {
	    return pst;
	}
    }

    pst = (IIIMCF_attr_slot*) realloc(pa->pslots, sizeof(*pst) * (size + 1));
    if (!pst) return NULL;
    pa->pslots = pst;
    pst += size;
    memset(pst, 0, sizeof(*pst));
    pa->nprops++;
    pst->idx = property;

    return pst;
}
   
IIIMF_status
iiimcf_attr_put_string_value(
    IIIMCF_attr attr,
    int property,
    const char *str
)
{
    IIIMCF_attr_slot *ps;
    IIIMCF_attr_rec *pa = (IIIMCF_attr_rec*) attr;

    ps = alloc_slot(pa, property);
    if (!ps) return IIIMF_STATUS_MALLOC;
    if ((ps->type != IIIMCF_ATTR_TYPE_NONE) 
	&& (ps->type != IIIMCF_ATTR_TYPE_STRING))
	return IIIMF_STATUS_ARGUMENT;
    ps->type = IIIMCF_ATTR_TYPE_STRING;
    ps->v.str = str;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_attr_get_string_value(
    IIIMCF_attr attr,
    int property,
    const char **pstr
)
{
    IIIMCF_attr_slot *ps;
    IIIMCF_attr_rec *pa = (IIIMCF_attr_rec*) attr;

    ps = find_slot(pa, property);
    if (!ps) return IIIMF_STATUS_NO_ATTR_VALUE;
    if (ps->type != IIIMCF_ATTR_TYPE_STRING)
	return IIIMF_STATUS_ARGUMENT;

    *pstr = ps->v.str;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_attr_put_integer_value(
    IIIMCF_attr attr,
    int property,
    int number
)
{
    IIIMCF_attr_slot *ps;
    IIIMCF_attr_rec *pa = (IIIMCF_attr_rec*) attr;

    ps = alloc_slot(pa, property);
    if (!ps) return IIIMF_STATUS_MALLOC;
    if ((ps->type != IIIMCF_ATTR_TYPE_NONE) 
	&& (ps->type != IIIMCF_ATTR_TYPE_INTEGER))
	return IIIMF_STATUS_ARGUMENT;
    ps->type = IIIMCF_ATTR_TYPE_INTEGER;
    ps->v.number = number;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_attr_get_integer_value(
    IIIMCF_attr attr,
    int property,
    int *pnumber
)
{
    IIIMCF_attr_slot *ps;
    IIIMCF_attr_rec *pa = (IIIMCF_attr_rec*) attr;

    ps = find_slot(pa, property);
    if (!ps) return IIIMF_STATUS_NO_ATTR_VALUE;
    if (ps->type != IIIMCF_ATTR_TYPE_INTEGER)
	return IIIMF_STATUS_ARGUMENT;

    *pnumber = ps->v.number;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_attr_put_ptr_value(
    IIIMCF_attr attr,
    int property,
    void *ptr
)
{
    IIIMCF_attr_slot *ps;
    IIIMCF_attr_rec *pa = (IIIMCF_attr_rec*) attr;

    ps = alloc_slot(pa, property);
    if (!ps) return IIIMF_STATUS_MALLOC;
    if ((ps->type != IIIMCF_ATTR_TYPE_NONE) 
	&& (ps->type != IIIMCF_ATTR_TYPE_POINTER))
	return IIIMF_STATUS_ARGUMENT;
    ps->type = IIIMCF_ATTR_TYPE_POINTER;
    ps->v.ptr = ptr;

    return IIIMF_STATUS_SUCCESS;
}

IIIMF_status
iiimcf_attr_get_ptr_value(
    IIIMCF_attr attr,
    int property,
    void **pptr
)
{
    IIIMCF_attr_slot *ps;
    IIIMCF_attr_rec *pa = (IIIMCF_attr_rec*) attr;

    ps = find_slot(pa, property);
    if (!ps) return IIIMF_STATUS_NO_ATTR_VALUE;
    if (ps->type != IIIMCF_ATTR_TYPE_POINTER)
	return IIIMF_STATUS_ARGUMENT;

    *pptr = ps->v.ptr;

    return IIIMF_STATUS_SUCCESS;
}

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */

