/* ** constant.c ** Series of routines to minimize memory usage through the use ** of shared strings */ #include "odieInt.h" #include 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; }