/*
** constant.c
** Series of routines to minimize memory usage through the use
** of shared strings
*/
#include "odieInt.h"
#include <strings.h>
Tcl_HashTable constant_strings;
Tcl_Obj *irmStatic[14];
typedef struct constObj {
char *string;
Tcl_Obj *tclobj;
} constObj;
Tcl_Obj *Odie_shared_tclobj(int which) {
if(which > ODIE_STATIC_MAX || which < 0) {
Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NULL]);
return irmStatic[ODIE_STATIC_NULL];
}
Tcl_IncrRefCount(irmStatic[which]);
return irmStatic[which];
}
Tcl_Obj *Odie_NewBooleanObj(int value) {
if(value) {
return Odie_shared_tclobj(ODIE_STATIC_ONE);
}
return Odie_shared_tclobj(ODIE_STATIC_ZERO);
}
Tcl_Obj *Odie_NewIntObj(int value) {
if(value>=0 && value < 10) {
int idx=ODIE_STATIC_ZERO+value;
Tcl_IncrRefCount(irmStatic[idx]);
return irmStatic[idx];
}
if(value==-1) {
Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NEG1]);
return irmStatic[ODIE_STATIC_NEG1];
}
return Tcl_NewIntObj(value);
}
static constObj *Odie_constant(const char *zName,int create) {
int len,isNew=0;
Tcl_HashEntry *pEntry;
constObj *p;
if(zName==NULL) {
return NULL;
}
if(create) {
pEntry=Tcl_CreateHashEntry(&constant_strings,zName,&isNew);
} else {
pEntry=Tcl_FindHashEntry(&constant_strings,zName);
}
if(isNew) {
len = strlen(zName);
p =(constObj*)Odie_Alloc(sizeof(*p)+len+1);
p->string=p+1;
strncpy(p->string, zName, len+1);
p->tclobj=Tcl_NewStringObj(zName,len);
Tcl_IncrRefCount(p->tclobj);
Tcl_SetHashValue(pEntry,(ClientData)p);
return p;
}
if(pEntry) {
p=(constObj*)Tcl_GetHashValue(pEntry);
return p;
}
return NULL;
}
int Odie_SameString(char *aPtr,char *bPtr) {
if(aPtr==bPtr) {
return 1;
}
if(!bPtr || !aPtr) {
return 0;
}
if(strcmp(aPtr,bPtr)==0) {
return 1;
}
return 0;
}
char *Odie_constant_string(const char *zName) {
constObj *p;
p=Odie_constant(zName,1);
return p->string;
}
Tcl_Obj *Odie_constant_tclobj(const char *zName) {
constObj *p;
p=Odie_constant(zName,1);
Tcl_IncrRefCount(p->tclobj);
return p->tclobj;
}
Tcl_Obj *Odie_NewStringObj(const char *str) {
/*
if(!str) {
return Tcl_NewObj();
}
return Tcl_NewStringObj(str,-1);
*/
return Odie_constant_tclobj(str);
}
static int constantMapCmd(
void *pArg,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
char *newName;
Tcl_Obj *result;
if(objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "string");
return TCL_ERROR;
}
newName=Tcl_GetString(objv[1]);
result=Odie_constant_tclobj(newName);
if (!result) return TCL_ERROR;
Tcl_SetObjResult(interp,result);
return TCL_OK;
}
DLLEXPORT int Odie_Constant_Init(Tcl_Interp *interp) {
static int once = 1;
if( once ){
int i;
once = 0;
irmStatic[ODIE_STATIC_NULL]=Tcl_NewObj();
Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NULL]);
irmStatic[ODIE_STATIC_ZERO] = Tcl_NewBooleanObj(0);
Tcl_IncrRefCount(irmStatic[ODIE_STATIC_ZERO]);
irmStatic[ODIE_STATIC_ONE] = Tcl_NewBooleanObj(1);
Tcl_IncrRefCount(irmStatic[ODIE_STATIC_ONE]);
for(i=2;i<10;i++) {
int idx=ODIE_STATIC_ZERO+i;
irmStatic[idx] = Tcl_NewIntObj(i);
Tcl_IncrRefCount(irmStatic[idx]);
}
irmStatic[ODIE_STATIC_FZERO] = Tcl_NewDoubleObj(0.0);
Tcl_IncrRefCount(irmStatic[ODIE_STATIC_FZERO]);
irmStatic[ODIE_STATIC_NEG1] = Tcl_NewIntObj(-1);
Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NEG1]);
Tcl_InitHashTable(&constant_strings,TCL_STRING_KEYS);
}
return TCL_OK;
}