ossp-pkg/act/act_ctx.c
/*
** OSSP act - Abstract Container Types
** Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 1999-2003 The OSSP Project <http://www.ossp.org/>
**
** This file is part of OSSP act, an abstract container type library
** which can be found at http://www.ossp.org/pkg/lib/act/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** act_ctx.c: context structure (implementation)
*/
#include "act_p.h"
/* the value of a context entry */
typedef union act_ctx_value_un {
void *v_ptr;
int v_int;
long v_long;
double v_double;
} act_ctx_value_t;
/* the context entry */
typedef struct act_ctx_entry_st {
unsigned int e_id;
act_ctx_value_t e_value;
} act_ctx_entry_t;
/* the context (already typedef'd in public header) */
struct act_ctx_st {
act_ctx_entry_t c_entry[ACT_CTX_ENTRY_MAX+1];
};
/* the default context */
act_ctx_t *act_ctx_default = NULL;
/* initialize the context module */
intern int act_ctx_init(void)
{
if (act_ctx_default != NULL)
act_ctx_free(act_ctx_default);
act_ctx_default = act_ctx_new();
return TRUE;
}
/* kill the context module */
intern int act_ctx_kill(void)
{
if (act_ctx_default != NULL) {
act_ctx_free(act_ctx_default);
act_ctx_default = NULL;
}
return TRUE;
}
/* allocate a new context structure */
act_ctx_t *act_ctx_new(void)
{
act_ctx_t *ctx;
int i;
if ((ctx = (act_ctx_t *)act_mem_alloc(sizeof(struct act_ctx_st))) == NULL)
return NULL;
for (i = 0; i < ACT_CTX_ENTRY_MAX; i++) {
ctx->c_entry[i].e_id = ACT_CTX_ID_NULL;
ctx->c_entry[i].e_value.v_long = 0;
}
return ctx;
}
/* duplicate a new context structure
(optionally with the help of a template) */
act_ctx_t *act_ctx_dup(act_ctx_t *ctx, act_ctx_t *ctx_template)
{
act_ctx_t *ctx_new;
act_ctx_t *ctx_from;
int sp, lk, ty, no;
int i;
if (ctx == NULL)
return NULL;
if (ctx_template != NULL)
ctx_from = ctx_template;
else
ctx_from = ctx;
if ((ctx_new = (act_ctx_t *)act_mem_alloc(sizeof(struct act_ctx_st))) == NULL)
return NULL;
act_mem_move(ctx_new->c_entry, ctx_from->c_entry,
sizeof(act_ctx_entry_t)*(ACT_CTX_ENTRY_MAX+1));
if (ctx_template != NULL) {
for (i = 0; i <= ACT_CTX_ENTRY_MAX; i++) {
ACT_CTX_ID_SPLIT(sp, lk, ty, no, ctx_new->c_entry[i].e_id);
if (!lk) {
ctx_new->c_entry[i].e_id = ctx->c_entry[i].e_id;
act_mem_move(&(ctx_new->c_entry[i].e_value), &(ctx->c_entry[i].e_value),
sizeof(act_ctx_value_t));
}
}
}
return ctx_new;
}
/* common function for both set and get context entries */
static int act_ctx_setget(act_ctx_t *ctx, int set, unsigned int id, va_list ap)
{
int sp,lk,ty,no;
int csp,clk,cty,cno;
ACT_CTX_ID_SPLIT(sp, lk, ty, no, id);
ACT_CTX_ID_SPLIT(csp, clk, cty, cno, ctx->c_entry[no].e_id);
if (set && clk)
return FALSE;
switch (ty) {
case act_type_ptr:
if (set)
ctx->c_entry[no].e_value.v_ptr = va_arg(ap, void *);
else {
void **v = va_arg(ap, void **);
*v = ctx->c_entry[no].e_value.v_ptr;
}
break;
case act_type_int:
if (set)
ctx->c_entry[no].e_value.v_int = va_arg(ap, int);
else {
int *v = va_arg(ap, int *);
*v = ctx->c_entry[no].e_value.v_int;
}
break;
case act_type_long:
if (set)
ctx->c_entry[no].e_value.v_long = va_arg(ap, long);
else {
long *v = va_arg(ap, long *);
*v = ctx->c_entry[no].e_value.v_long;
}
break;
case act_type_double:
if (set)
ctx->c_entry[no].e_value.v_double = va_arg(ap, double);
else {
double *v = va_arg(ap, double *);
*v = ctx->c_entry[no].e_value.v_double;
}
break;
default:
return FALSE;
break;
}
ctx->c_entry[no].e_id = id;
return TRUE;
}
/* set an entry in a context structure */
int act_ctx_set(act_ctx_t *ctx, unsigned int id, ...)
{
va_list ap;
int rc;
if (ctx == NULL)
return FALSE;
va_start(ap, id);
rc = act_ctx_setget(ctx, TRUE, id, ap);
va_end(ap);
return rc;
}
/* get an entry from a context structure */
int act_ctx_get(act_ctx_t *ctx, unsigned int id, ...)
{
va_list ap;
int rc;
if (ctx == NULL)
return FALSE;
va_start(ap, id);
rc = act_ctx_setget(ctx, FALSE, id, ap);
va_end(ap);
return rc;
}
/* get the address of an entry from a context structure */
void *act_ctx_var(act_ctx_t *ctx, unsigned int id)
{
int sp,lk,ty,no;
if (ctx == NULL)
return FALSE;
ACT_CTX_ID_SPLIT(sp, lk, ty, no, id);
return &(ctx->c_entry[no].e_value);
}
/* lock an entry of the context structure */
int act_ctx_lock(act_ctx_t *ctx, unsigned int id)
{
int rsp,rlk,rty,rno;
int csp,clk,cty,cno;
if (ctx == NULL)
return FALSE;
ACT_CTX_ID_SPLIT(rsp,rlk,rty,rno,id);
ACT_CTX_ID_SPLIT(csp,clk,cty,cno,ctx->c_entry[rno].e_id);
ctx->c_entry[rno].e_id = ACT_CTX_ID_CONS(csp,1,cty,cno);
return TRUE;
}
/* unlock an entry of the context structure */
int act_ctx_unlock(act_ctx_t *ctx, unsigned int id)
{
int rsp,rlk,rty,rno;
int csp,clk,cty,cno;
if (ctx == NULL)
return FALSE;
ACT_CTX_ID_SPLIT(rsp,rlk,rty,rno,id);
ACT_CTX_ID_SPLIT(csp,clk,cty,cno,ctx->c_entry[rno].e_id);
ctx->c_entry[rno].e_id = ACT_CTX_ID_CONS(csp,0,cty,cno);
return TRUE;
}
/* free a context structure */
int act_ctx_free(act_ctx_t *ctx)
{
void *ptr;
if (ctx == NULL)
return FALSE;
if (act_ctx_get(ctx, ACT_CTX_CTX_BINDING, &ptr))
if (ptr != NULL)
return FALSE;
act_mem_free(ctx);
return TRUE;
}