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 + -
显示快捷键?