📄 tcllistobj.c
字号:
if (first > 0) { memcpy((VOID *) newPtrs, (VOID *) elemPtrs, (size_t) (first * sizeof(Tcl_Obj *))); } /* * "Delete" count elements starting at first. */ for (i = 0, j = first; i < count; i++, j++) { victimPtr = elemPtrs[j]; TclDecrRefCount(victimPtr); } /* * Copy the elements after the last one removed, shifted to * their new locations. */ start = (first + count); numAfterLast = (numElems - start); if (numAfterLast > 0) { memcpy((VOID *) &(newPtrs[first + objc]), (VOID *) &(elemPtrs[start]), (size_t) (numAfterLast * sizeof(Tcl_Obj *))); } /* * Insert the new elements before "first" and update the * count of elements. */ for (i = 0, j = first; i < objc; i++, j++) { newPtrs[j] = objv[i]; Tcl_IncrRefCount(objv[i]); } listRepPtr->elemCount = numRequired; listRepPtr->maxElemCount = newMax; listRepPtr->elements = newPtrs; ckfree((char *) elemPtrs); } /* * Invalidate and free any old string representation since it no longer * reflects the list's internal representation. */ Tcl_InvalidateStringRep(listPtr); return TCL_OK;}/* *---------------------------------------------------------------------- * * FreeListInternalRep -- * * Deallocate the storage associated with a list object's internal * representation. * * Results: * None. * * Side effects: * Frees listPtr's List* internal representation and sets listPtr's * internalRep.otherValuePtr to NULL. Decrements the ref counts * of all element objects, which may free them. * *---------------------------------------------------------------------- */static voidFreeListInternalRep(listPtr) Tcl_Obj *listPtr; /* List object with internal rep to free. */{ register List *listRepPtr = (List *) listPtr->internalRep.otherValuePtr; register Tcl_Obj **elemPtrs = listRepPtr->elements; register Tcl_Obj *objPtr; int numElems = listRepPtr->elemCount; int i; for (i = 0; i < numElems; i++) { objPtr = elemPtrs[i]; Tcl_DecrRefCount(objPtr); } ckfree((char *) elemPtrs); ckfree((char *) listRepPtr);}/* *---------------------------------------------------------------------- * * DupListInternalRep -- * * Initialize the internal representation of a list Tcl_Obj to a * copy of the internal representation of an existing list object. * * Results: * None. * * Side effects: * "srcPtr"s list internal rep pointer should not be NULL and we assume * it is not NULL. We set "copyPtr"s internal rep to a pointer to a * newly allocated List structure that, in turn, points to "srcPtr"s * element objects. Those element objects are not actually copied but * are shared between "srcPtr" and "copyPtr". The ref count of each * element object is incremented. * *---------------------------------------------------------------------- */static voidDupListInternalRep(srcPtr, copyPtr) Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ Tcl_Obj *copyPtr; /* Object with internal rep to set. */{ List *srcListRepPtr = (List *) srcPtr->internalRep.otherValuePtr; int numElems = srcListRepPtr->elemCount; int maxElems = srcListRepPtr->maxElemCount; register Tcl_Obj **srcElemPtrs = srcListRepPtr->elements; register Tcl_Obj **copyElemPtrs; register List *copyListRepPtr; int i; /* * Allocate a new List structure that points to "srcPtr"s element * objects. Increment the ref counts for those (now shared) element * objects. */ copyElemPtrs = (Tcl_Obj **) ckalloc((unsigned) maxElems * sizeof(Tcl_Obj *)); for (i = 0; i < numElems; i++) { copyElemPtrs[i] = srcElemPtrs[i]; Tcl_IncrRefCount(copyElemPtrs[i]); } copyListRepPtr = (List *) ckalloc(sizeof(List)); copyListRepPtr->maxElemCount = maxElems; copyListRepPtr->elemCount = numElems; copyListRepPtr->elements = copyElemPtrs; copyPtr->internalRep.otherValuePtr = (VOID *) copyListRepPtr; copyPtr->typePtr = &tclListType;}/* *---------------------------------------------------------------------- * * SetListFromAny -- * * Attempt to generate a list internal form for the Tcl object * "objPtr". * * Results: * The return value is TCL_OK or TCL_ERROR. If an error occurs during * conversion, an error message is left in the interpreter's result * unless "interp" is NULL. * * Side effects: * If no error occurs, a list is stored as "objPtr"s internal * representation. * *---------------------------------------------------------------------- */static intSetListFromAny(interp, objPtr) Tcl_Interp *interp; /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr; /* The object to convert. */{ Tcl_ObjType *oldTypePtr = objPtr->typePtr; char *string, *elemStart, *nextElem, *s; int lenRemain, length, estCount, elemSize, hasBrace, i, j, result; char *limit; /* Points just after string's last byte. */ register char *p; register Tcl_Obj **elemPtrs; register Tcl_Obj *elemPtr; List *listRepPtr; /* * Get the string representation. Make it up-to-date if necessary. */ string = TclGetStringFromObj(objPtr, &length); /* * Parse the string into separate string objects, and create a List * structure that points to the element string objects. We use a * modified version of Tcl_SplitList's implementation to avoid one * malloc and a string copy for each list element. First, estimate the * number of elements by counting the number of space characters in the * list. */ limit = (string + length); estCount = 1; for (p = string; p < limit; p++) { if (isspace(UCHAR(*p))) { estCount++; } } /* * Allocate a new List structure with enough room for "estCount" * elements. Each element is a pointer to a Tcl_Obj with the appropriate * string rep. The initial "estCount" elements are set using the * corresponding "argv" strings. */ elemPtrs = (Tcl_Obj **) ckalloc((unsigned) (estCount * sizeof(Tcl_Obj *))); for (p = string, lenRemain = length, i = 0; lenRemain > 0; p = nextElem, lenRemain = (limit - nextElem), i++) { result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem, &elemSize, &hasBrace); if (result != TCL_OK) { for (j = 0; j < i; j++) { elemPtr = elemPtrs[j]; Tcl_DecrRefCount(elemPtr); } ckfree((char *) elemPtrs); return result; } if (elemStart >= limit) { break; } if (i > estCount) { panic("SetListFromAny: bad size estimate for list"); } /* * Allocate a Tcl object for the element and initialize it from the * "elemSize" bytes starting at "elemStart". */ s = ckalloc((unsigned) elemSize + 1); if (hasBrace) { memcpy((VOID *) s, (VOID *) elemStart, (size_t) elemSize); s[elemSize] = 0; } else { elemSize = TclCopyAndCollapse(elemSize, elemStart, s); } TclNewObj(elemPtr); elemPtr->bytes = s; elemPtr->length = elemSize; elemPtrs[i] = elemPtr; Tcl_IncrRefCount(elemPtr); /* since list now holds ref to it */ } listRepPtr = (List *) ckalloc(sizeof(List)); listRepPtr->maxElemCount = estCount; listRepPtr->elemCount = i; listRepPtr->elements = elemPtrs; /* * Free the old internalRep before setting the new one. We do this as * late as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ if ((oldTypePtr != NULL) && (oldTypePtr->freeIntRepProc != NULL)) { oldTypePtr->freeIntRepProc(objPtr); } objPtr->internalRep.otherValuePtr = (VOID *) listRepPtr; objPtr->typePtr = &tclListType; return TCL_OK;}/* *---------------------------------------------------------------------- * * UpdateStringOfList -- * * Update the string representation for a list object. * Note: This procedure does not invalidate an existing old string rep * so storage will be lost if this has not already been done. * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from * the list-to-string conversion. This string will be empty if the * list has no elements. The list internal representation * should not be NULL and we assume it is not NULL. * *---------------------------------------------------------------------- */static voidUpdateStringOfList(listPtr) Tcl_Obj *listPtr; /* List object with string rep to update. */{# define LOCAL_SIZE 20 int localFlags[LOCAL_SIZE], *flagPtr; List *listRepPtr = (List *) listPtr->internalRep.otherValuePtr; int numElems = listRepPtr->elemCount; register int i; char *elem, *dst; int length; /* * Convert each element of the list to string form and then convert it * to proper list element form, adding it to the result buffer. */ /* * Pass 1: estimate space, gather flags. */ if (numElems <= LOCAL_SIZE) { flagPtr = localFlags; } else { flagPtr = (int *) ckalloc((unsigned) numElems*sizeof(int)); } listPtr->length = 1; for (i = 0; i < numElems; i++) { elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length); listPtr->length += Tcl_ScanCountedElement(elem, length, &flagPtr[i]) + 1; } /* * Pass 2: copy into string rep buffer. */ listPtr->bytes = ckalloc((unsigned) listPtr->length); dst = listPtr->bytes; for (i = 0; i < numElems; i++) { elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length); dst += Tcl_ConvertCountedElement(elem, length, dst, flagPtr[i]); *dst = ' '; dst++; } if (flagPtr != localFlags) { ckfree((char *) flagPtr); } if (dst == listPtr->bytes) { *dst = 0; } else { dst--; *dst = 0; } listPtr->length = dst - listPtr->bytes;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -