/* ** OSSP act - Abstract Container Types ** Copyright (c) 1999-2003 Ralf S. Engelschall ** Copyright (c) 1999-2003 The OSSP Project ** ** 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; }