diff options
Diffstat (limited to 'blt/src/bltArrayObj.c')
-rw-r--r-- | blt/src/bltArrayObj.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/blt/src/bltArrayObj.c b/blt/src/bltArrayObj.c new file mode 100644 index 00000000000..b76dd479528 --- /dev/null +++ b/blt/src/bltArrayObj.c @@ -0,0 +1,244 @@ + +/* + * bltArrayObj.c -- + * + * Copyright 2000 Silicon Metrics, Inc. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and warranty + * disclaimer appear in supporting documentation, and that the names + * of Lucent Technologies or any of their entities not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. + * + * Lucent Technologies disclaims all warranties with regard to this + * software, including all implied warranties of merchantability and + * fitness. In no event shall Lucent Technologies be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in + * an action of contract, negligence or other tortuous action, arising + * out of or in connection with the use or performance of this + * software. + * + * The array Tcl object was created by George A. Howlett. + */ + +#include "bltInt.h" + +#ifndef NO_ARRAY +#include "bltHash.h" + +static Tcl_DupInternalRepProc DupArrayInternalRep; +static Tcl_FreeInternalRepProc FreeArrayInternalRep; +static Tcl_UpdateStringProc UpdateStringOfArray; +static Tcl_SetFromAnyProc SetArrayFromAny; + +static Tcl_ObjType arrayObjType = { + "array", + FreeArrayInternalRep, /* Called when an object is freed. */ + DupArrayInternalRep, /* Copies an internal representation + * from one object to another. */ + UpdateStringOfArray, /* Creates string representation from + * an object's internal representation. */ + SetArrayFromAny, /* Creates valid internal representation + * from an object's string representation. */ +}; + +static int +SetArrayFromAny(interp, objPtr) + Tcl_Interp *interp; + Tcl_Obj *objPtr; +{ + Blt_HashEntry *hPtr; + Blt_HashTable *tablePtr; + Tcl_Obj *elemObjPtr; + Tcl_ObjType *oldTypePtr = objPtr->typePtr; + char **elemArr; + char *string; + int isNew; + int nElem; + register int i; + + if (objPtr->typePtr == &arrayObjType) { + return TCL_OK; + } + /* + * Get the string representation. Make it up-to-date if necessary. + */ + string = Tcl_GetString(objPtr); + if (Tcl_SplitList(interp, string, &nElem, &elemArr) != TCL_OK) { + return TCL_ERROR; + } + tablePtr = Blt_Malloc(sizeof(Blt_HashTable)); + assert(tablePtr); + Blt_InitHashTable(tablePtr, BLT_STRING_KEYS); + for (i = 0; i < nElem; i += 2) { + hPtr = Blt_CreateHashEntry(tablePtr, elemArr[i], &isNew); + elemObjPtr = Tcl_NewStringObj(elemArr[i + 1], -1); + Blt_SetHashValue(hPtr, elemObjPtr); + + /* Make sure we increment the reference count */ + Tcl_IncrRefCount(elemObjPtr); + } + + if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) { + oldTypePtr->freeIntRepProc(objPtr); + } + objPtr->internalRep.otherValuePtr = (VOID *)tablePtr; + objPtr->typePtr = &arrayObjType; + Blt_Free(elemArr); + + return TCL_OK; +} + +static void +DupArrayInternalRep(srcPtr, destPtr) + Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ + Tcl_Obj *destPtr; /* Object with internal rep to set. */ +{ + Blt_HashEntry *hPtr; + Blt_HashSearch cursor; + Blt_HashTable *srcTablePtr, *destTablePtr; + Tcl_Obj *valueObjPtr; + char *key; + int isNew; + + srcTablePtr = (Blt_HashTable *)srcPtr->internalRep.otherValuePtr; + destTablePtr = Blt_Malloc(sizeof(Blt_HashTable)); + assert(destTablePtr); + Blt_InitHashTable(destTablePtr, BLT_STRING_KEYS); + for (hPtr = Blt_FirstHashEntry(srcTablePtr, &cursor); hPtr != NULL; + hPtr = Blt_NextHashEntry(&cursor)) { + key = Blt_GetHashKey(srcTablePtr, hPtr); + Blt_CreateHashEntry(destTablePtr, key, &isNew); + valueObjPtr = (Tcl_Obj *)Blt_GetHashValue(hPtr); + Blt_SetHashValue(hPtr, valueObjPtr); + + /* Make sure we increment the reference count now that both + * array objects are using the same elements. */ + Tcl_IncrRefCount(valueObjPtr); + } + Tcl_InvalidateStringRep(destPtr); + destPtr->internalRep.otherValuePtr = (VOID *)destTablePtr; + destPtr->typePtr = &arrayObjType; +} + +static void +UpdateStringOfArray(objPtr) + Tcl_Obj *objPtr; /* Array object whose string rep to update. */ +{ + Tcl_DString dString; + Blt_HashTable *tablePtr; + Blt_HashEntry *hPtr; + Blt_HashSearch cursor; + Tcl_Obj *elemObjPtr; + + tablePtr = (Blt_HashTable *)objPtr->internalRep.otherValuePtr; + Tcl_DStringInit(&dString); + for (hPtr = Blt_FirstHashEntry(tablePtr, &cursor); hPtr != NULL; + hPtr = Blt_NextHashEntry(&cursor)) { + elemObjPtr = (Tcl_Obj *)Blt_GetHashValue(hPtr); + Tcl_DStringAppendElement(&dString, Blt_GetHashKey(tablePtr, hPtr)); + Tcl_DStringAppendElement(&dString, Tcl_GetString(elemObjPtr)); + } + objPtr->bytes = Blt_Strdup(Tcl_DStringValue(&dString)); + objPtr->length = strlen(Tcl_DStringValue(&dString)); + Tcl_DStringFree(&dString); +} + +static void +FreeArrayInternalRep(objPtr) + Tcl_Obj *objPtr; /* Array object to release. */ +{ + Blt_HashEntry *hPtr; + Blt_HashSearch cursor; + Blt_HashTable *tablePtr; + Tcl_Obj *elemObjPtr; + + Tcl_InvalidateStringRep(objPtr); + tablePtr = (Blt_HashTable *)objPtr->internalRep.otherValuePtr; + for (hPtr = Blt_FirstHashEntry(tablePtr, &cursor); hPtr != NULL; + hPtr = Blt_NextHashEntry(&cursor)) { + elemObjPtr = (Tcl_Obj *)Blt_GetHashValue(hPtr); + Tcl_DecrRefCount(elemObjPtr); + } + Blt_DeleteHashTable(tablePtr); + Blt_Free(tablePtr); +} + +int +Blt_GetArrayFromObj(interp, objPtr, tablePtrPtr) + Tcl_Interp *interp; + Tcl_Obj *objPtr; + Blt_HashTable **tablePtrPtr; +{ + if (objPtr->typePtr == &arrayObjType) { + *tablePtrPtr = (Blt_HashTable *)objPtr->internalRep.otherValuePtr; + return TCL_OK; + } + if (SetArrayFromAny(interp, objPtr) == TCL_OK) { + *tablePtrPtr = (Blt_HashTable *)objPtr->internalRep.otherValuePtr; + return TCL_OK; + } + return TCL_ERROR; +} + +Tcl_Obj * +Blt_NewArrayObj(objc, objv) + int objc; + Tcl_Obj *objv[]; +{ + Blt_HashEntry *hPtr; + Blt_HashTable *tablePtr; + Tcl_Obj *arrayObjPtr, *objPtr; + int isNew; + register int i; + + tablePtr = Blt_Malloc(sizeof(Blt_HashTable)); + assert(tablePtr); + Blt_InitHashTable(tablePtr, BLT_STRING_KEYS); + + for (i = 0; i < objc; i += 2) { + hPtr = Blt_CreateHashEntry(tablePtr, Tcl_GetString(objv[i]), &isNew); + if ((i + 1) == objc) { + objPtr = Tcl_NewStringObj("", -1); + } else { + objPtr = objv[i+1]; + } + Tcl_IncrRefCount(objPtr); + if (!isNew) { + Tcl_DecrRefCount((Tcl_Obj *)Blt_GetHashValue(hPtr)); + } + Blt_SetHashValue(hPtr, objPtr); + } + arrayObjPtr = Tcl_NewObj(); + /* + * Reference counts for entry objects are initialized to 0. They + * are incremented as they are inserted into the tree via the + * Blt_TreeSetValue call. + */ + arrayObjPtr->refCount = 0; + arrayObjPtr->internalRep.otherValuePtr = (VOID *)tablePtr; + arrayObjPtr->bytes = NULL; + arrayObjPtr->length = 0; + arrayObjPtr->typePtr = &arrayObjType; + return arrayObjPtr; +} + +int +Blt_IsArrayObj(objPtr) + Tcl_Obj *objPtr; +{ + return (objPtr->typePtr == &arrayObjType); +} + +/*ARGSUSED*/ +void +Blt_RegisterArrayObj(interp) + Tcl_Interp *interp; /* Not used. */ +{ + Tcl_RegisterObjType(&arrayObjType); +} +#endif /* NO_ARRAY */ |