tclstringobj.c
来自「tcl是工具命令语言」· C语言 代码 · 共 1,878 行 · 第 1/4 页
C
1,878 行
stringPtr->hasUnicode = 0; memcpy((VOID *) (objPtr->bytes + oldLength), (VOID *) bytes, (size_t) numBytes); objPtr->bytes[newLength] = 0; objPtr->length = newLength;}/* *---------------------------------------------------------------------- * * Tcl_AppendStringsToObjVA -- * * This procedure appends one or more null-terminated strings * to an object. * * Results: * None. * * Side effects: * The contents of all the string arguments are appended to the * string representation of objPtr. * *---------------------------------------------------------------------- */voidTcl_AppendStringsToObjVA (objPtr, argList) Tcl_Obj *objPtr; /* Points to the object to append to. */ va_list argList; /* Variable argument list. */{#define STATIC_LIST_SIZE 16 String *stringPtr; int newLength, oldLength, attemptLength; register char *string, *dst; char *static_list[STATIC_LIST_SIZE]; char **args = static_list; int nargs_space = STATIC_LIST_SIZE; int nargs, i; if (Tcl_IsShared(objPtr)) { panic("Tcl_AppendStringsToObj called with shared object"); } SetStringFromAny(NULL, objPtr); /* * Figure out how much space is needed for all the strings, and * expand the string representation if it isn't big enough. If no * bytes would be appended, just return. Note that on some platforms * (notably OS/390) the argList is an array so we need to use memcpy. */ nargs = 0; newLength = 0; oldLength = objPtr->length; while (1) { string = va_arg(argList, char *); if (string == NULL) { break; } if (nargs >= nargs_space) { /* * Expand the args buffer */ nargs_space += STATIC_LIST_SIZE; if (args == static_list) { args = (void *)ckalloc(nargs_space * sizeof(char *)); for (i = 0; i < nargs; ++i) { args[i] = static_list[i]; } } else { args = (void *)ckrealloc((void *)args, nargs_space * sizeof(char *)); } } newLength += strlen(string); args[nargs++] = string; } if (newLength == 0) { goto done; } stringPtr = GET_STRING(objPtr); if (oldLength + newLength > (int) stringPtr->allocated) { /* * There isn't currently enough space in the string * representation, so allocate additional space. If the current * string representation isn't empty (i.e. it looks like we're * doing a series of appends) then try to allocate extra space to * accomodate future growth: first try to double the required memory; * if that fails, try a more modest allocation. See the "TCL STRING * GROWTH ALGORITHM" comment at the top of this file for an explanation * of this growth algorithm. Otherwise, if the current string * representation is empty, exactly enough memory is allocated. */ if (oldLength == 0) { Tcl_SetObjLength(objPtr, newLength); } else { attemptLength = 2 * (oldLength + newLength); if (Tcl_AttemptSetObjLength(objPtr, attemptLength) == 0) { attemptLength = oldLength + (2 * newLength) + TCL_GROWTH_MIN_ALLOC; Tcl_SetObjLength(objPtr, attemptLength); } } } /* * Make a second pass through the arguments, appending all the * strings to the object. */ dst = objPtr->bytes + oldLength; for (i = 0; i < nargs; ++i) { string = args[i]; if (string == NULL) { break; } while (*string != 0) { *dst = *string; dst++; string++; } } /* * Add a null byte to terminate the string. However, be careful: * it's possible that the object is totally empty (if it was empty * originally and there was nothing to append). In this case dst is * NULL; just leave everything alone. */ if (dst != NULL) { *dst = 0; } objPtr->length = oldLength + newLength; done: /* * If we had to allocate a buffer from the heap, * free it now. */ if (args != static_list) { ckfree((void *)args); }#undef STATIC_LIST_SIZE}/* *---------------------------------------------------------------------- * * Tcl_AppendStringsToObj -- * * This procedure appends one or more null-terminated strings * to an object. * * Results: * None. * * Side effects: * The contents of all the string arguments are appended to the * string representation of objPtr. * *---------------------------------------------------------------------- */voidTcl_AppendStringsToObj TCL_VARARGS_DEF(Tcl_Obj *,arg1){ register Tcl_Obj *objPtr; va_list argList; objPtr = TCL_VARARGS_START(Tcl_Obj *,arg1,argList); Tcl_AppendStringsToObjVA(objPtr, argList); va_end(argList);}/* *--------------------------------------------------------------------------- * * FillUnicodeRep -- * * Populate the Unicode internal rep with the Unicode form of its string * rep. The object must alread have a "String" internal rep. * * Results: * None. * * Side effects: * Reallocates the String internal rep. * *--------------------------------------------------------------------------- */static voidFillUnicodeRep(objPtr) Tcl_Obj *objPtr; /* The object in which to fill the unicode rep. */{ String *stringPtr; size_t uallocated; char *src, *srcEnd; Tcl_UniChar *dst; src = objPtr->bytes; stringPtr = GET_STRING(objPtr); if (stringPtr->numChars == -1) { stringPtr->numChars = Tcl_NumUtfChars(src, objPtr->length); } stringPtr->hasUnicode = (stringPtr->numChars > 0); uallocated = STRING_UALLOC(stringPtr->numChars); if (uallocated > stringPtr->uallocated) { /* * If not enough space has been allocated for the unicode rep, * reallocate the internal rep object. */ /* * There isn't currently enough space in the Unicode * representation so allocate additional space. If the current * Unicode representation isn't empty (i.e. it looks like we've * done some appends) then overallocate the space so * that we won't have to do as much reallocation in the future. */ if (stringPtr->uallocated > 0) { uallocated *= 2; } stringPtr = (String *) ckrealloc((char*) stringPtr, STRING_SIZE(uallocated)); stringPtr->uallocated = uallocated; } /* * Convert src to Unicode and store the coverted data in "unicode". */ srcEnd = src + objPtr->length; for (dst = stringPtr->unicode; src < srcEnd; dst++) { src += TclUtfToUniChar(src, dst); } *dst = 0; SET_STRING(objPtr, stringPtr);}/* *---------------------------------------------------------------------- * * DupStringInternalRep -- * * Initialize the internal representation of a new Tcl_Obj to a * copy of the internal representation of an existing string object. * * Results: * None. * * Side effects: * copyPtr's internal rep is set to a copy of srcPtr's internal * representation. * *---------------------------------------------------------------------- */static voidDupStringInternalRep(srcPtr, copyPtr) register Tcl_Obj *srcPtr; /* Object with internal rep to copy. Must * have an internal rep of type "String". */ register Tcl_Obj *copyPtr; /* Object with internal rep to set. Must * not currently have an internal rep.*/{ String *srcStringPtr = GET_STRING(srcPtr); String *copyStringPtr = NULL; /* * If the src obj is a string of 1-byte Utf chars, then copy the * string rep of the source object and create an "empty" Unicode * internal rep for the new object. Otherwise, copy Unicode * internal rep, and invalidate the string rep of the new object. */ if (srcStringPtr->hasUnicode == 0) { copyStringPtr = (String *) ckalloc(STRING_SIZE(STRING_UALLOC(0))); copyStringPtr->uallocated = STRING_UALLOC(0); } else { copyStringPtr = (String *) ckalloc( STRING_SIZE(srcStringPtr->uallocated)); copyStringPtr->uallocated = srcStringPtr->uallocated; memcpy((VOID *) copyStringPtr->unicode, (VOID *) srcStringPtr->unicode, (size_t) srcStringPtr->numChars * sizeof(Tcl_UniChar)); copyStringPtr->unicode[srcStringPtr->numChars] = 0; } copyStringPtr->numChars = srcStringPtr->numChars; copyStringPtr->hasUnicode = srcStringPtr->hasUnicode; copyStringPtr->allocated = srcStringPtr->allocated; /* * Tricky point: the string value was copied by generic object * management code, so it doesn't contain any extra bytes that * might exist in the source object. */ copyStringPtr->allocated = copyPtr->length; SET_STRING(copyPtr, copyStringPtr); copyPtr->typePtr = &tclStringType;}/* *---------------------------------------------------------------------- * * SetStringFromAny -- * * Create an internal representation of type "String" for an object. * * Results: * This operation always succeeds and returns TCL_OK. * * Side effects: * Any old internal reputation for objPtr is freed and the * internal representation is set to "String". * *---------------------------------------------------------------------- */static intSetStringFromAny(interp, objPtr) Tcl_Interp *interp; /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr; /* The object to convert. */{ /* * The Unicode object is optimized for the case where each UTF char * in a string is only one byte. In this case, we store the value of * numChars, but we don't copy the bytes to the unicodeObj->unicode. */ if (objPtr->typePtr != &tclStringType) { String *stringPtr; if (objPtr->typePtr != NULL) { if (objPtr->bytes == NULL) { objPtr->typePtr->updateStringProc(objPtr); } if ((objPtr->typePtr->freeIntRepProc) != NULL) { (*objPtr->typePtr->freeIntRepProc)(objPtr); } } objPtr->typePtr = &tclStringType; /* * Allocate enough space for the basic String structure. */ stringPtr = (String *) ckalloc(STRING_SIZE(STRING_UALLOC(0))); stringPtr->numChars = -1; stringPtr->uallocated = STRING_UALLOC(0); stringPtr->hasUnicode = 0; if (objPtr->bytes != NULL) { stringPtr->allocated = objPtr->length; objPtr->bytes[objPtr->length] = 0; } else { objPtr->length = 0; } SET_STRING(objPtr, stringPtr); } return TCL_OK;}/* *---------------------------------------------------------------------- * * UpdateStringOfString -- * * Update the string representation for an object whose internal * representation is "String". * * Results: * None. * * Side effects: * The object's string may be set by converting its Unicode * represention to UTF format. * *---------------------------------------------------------------------- */static voidUpdateStringOfString(objPtr) Tcl_Obj *objPtr; /* Object with string rep to update. */{ int i, size; Tcl_UniChar *unicode; char dummy[TCL_UTF_MAX]; char *dst; String *stringPtr; stringPtr = GET_STRING(objPtr); if ((objPtr->bytes == NULL) || (stringPtr->allocated == 0)) { if (stringPtr->numChars <= 0) { /* * If there is no Unicode rep, or the string has 0 chars, * then set the string rep to an empty string. */ objPtr->bytes = tclEmptyStringRep; objPtr->length = 0; return; } unicode = stringPtr->unicode; /* * Translate the Unicode string to UTF. "size" will hold the * amount of space the UTF string needs. */ size = 0; for (i = 0; i < stringPtr->numChars; i++) { size += Tcl_UniCharToUtf((int) unicode[i], dummy); } dst = (char *) ckalloc((unsigned) (size + 1)); objPtr->bytes = dst; objPtr->length = size; stringPtr->allocated = size; for (i = 0; i < stringPtr->numChars; i++) { dst += Tcl_UniCharToUtf(unicode[i], dst); } *dst = '\0'; } return;}/* *---------------------------------------------------------------------- * * FreeStringInternalRep -- * * Deallocate the storage associated with a String data object's * internal representation. * * Results: * None. * * Side effects: * Frees memory. * *---------------------------------------------------------------------- */static voidFreeStringInternalRep(objPtr) Tcl_Obj *objPtr; /* Object with internal rep to free. */{ ckfree((char *) GET_STRING(objPtr));}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?