summaryrefslogtreecommitdiff
path: root/blt/src/bltArrayObj.c
diff options
context:
space:
mode:
Diffstat (limited to 'blt/src/bltArrayObj.c')
-rw-r--r--blt/src/bltArrayObj.c244
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 */