⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclbinary.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * tclBinary.c -- * *	This file contains the implementation of the "binary" Tcl built-in *	command and the Tcl binary data object. * * Copyright (c) 1997 by Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclBinary.c,v 1.13 2003/02/21 21:54:11 dkf Exp $ */#include "tclInt.h"#include "tclPort.h"#include <math.h>/* * The following constants are used by GetFormatSpec to indicate various * special conditions in the parsing of a format specifier. */#define BINARY_ALL -1		/* Use all elements in the argument. */#define BINARY_NOCOUNT -2	/* No count was specified in format. *//* * The following defines the maximum number of different (integer) * numbers placed in the object cache by 'binary scan' before it bails * out and switches back to Plan A (creating a new object for each * value.)  Theoretically, it would be possible to keep the cache * about for the values that are already in it, but that makes the * code slower in practise when overflow happens, and makes little * odds the rest of the time (as measured on my machine.)  It is also * slower (on the sample I tried at least) to grow the cache to hold * all items we might want to put in it; presumably the extra cost of * managing the memory for the enlarged table outweighs the benefit * from allocating fewer objects.  This is probably because as the * number of objects increases, the likelihood of reuse of any * particular one drops, and there is very little gain from larger * maximum cache sizes (the value below is chosen to allow caching to * work in full with conversion of bytes.) - DKF */#define BINARY_SCAN_MAX_CACHE	260/* * Prototypes for local procedures defined in this file: */static void		DupByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,			    Tcl_Obj *copyPtr));static int		FormatNumber _ANSI_ARGS_((Tcl_Interp *interp, int type,			    Tcl_Obj *src, unsigned char **cursorPtr));static void		FreeByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));static int		GetFormatSpec _ANSI_ARGS_((char **formatPtr,			    char *cmdPtr, int *countPtr));static Tcl_Obj *	ScanNumber _ANSI_ARGS_((unsigned char *buffer,			    int type, Tcl_HashTable **numberCachePtr));static int		SetByteArrayFromAny _ANSI_ARGS_((Tcl_Interp *interp,			    Tcl_Obj *objPtr));static void		UpdateStringOfByteArray _ANSI_ARGS_((Tcl_Obj *listPtr));/* * The following object type represents an array of bytes.  An array of * bytes is not equivalent to an internationalized string.  Conceptually, a * string is an array of 16-bit quantities organized as a sequence of properly * formed UTF-8 characters, while a ByteArray is an array of 8-bit quantities. * Accessor functions are provided to convert a ByteArray to a String or a * String to a ByteArray.  Two or more consecutive bytes in an array of bytes * may look like a single UTF-8 character if the array is casually treated as * a string.  But obtaining the String from a ByteArray is guaranteed to * produced properly formed UTF-8 sequences so that there is a one-to-one * map between bytes and characters. * * Converting a ByteArray to a String proceeds by casting each byte in the * array to a 16-bit quantity, treating that number as a Unicode character, * and storing the UTF-8 version of that Unicode character in the String. * For ByteArrays consisting entirely of values 1..127, the corresponding * String representation is the same as the ByteArray representation. * * Converting a String to a ByteArray proceeds by getting the Unicode * representation of each character in the String, casting it to a * byte by truncating the upper 8 bits, and then storing the byte in the * ByteArray.  Converting from ByteArray to String and back to ByteArray * is not lossy, but converting an arbitrary String to a ByteArray may be. */Tcl_ObjType tclByteArrayType = {    "bytearray",    FreeByteArrayInternalRep,    DupByteArrayInternalRep,    UpdateStringOfByteArray,    SetByteArrayFromAny};/* * The following structure is the internal rep for a ByteArray object. * Keeps track of how much memory has been used and how much has been * allocated for the byte array to enable growing and shrinking of the * ByteArray object with fewer mallocs.   */typedef struct ByteArray {    int used;			/* The number of bytes used in the byte				 * array. */    int allocated;		/* The amount of space actually allocated				 * minus 1 byte. */    unsigned char bytes[4];	/* The array of bytes.  The actual size of				 * this field depends on the 'allocated' field				 * above. */} ByteArray;#define BYTEARRAY_SIZE(len)	\		((unsigned) (sizeof(ByteArray) - 4 + (len)))#define GET_BYTEARRAY(objPtr) \		((ByteArray *) (objPtr)->internalRep.otherValuePtr)#define SET_BYTEARRAY(objPtr, baPtr) \		(objPtr)->internalRep.otherValuePtr = (VOID *) (baPtr)/* *--------------------------------------------------------------------------- * * Tcl_NewByteArrayObj -- * *	This procedure is creates a new ByteArray object and initializes *	it from the given array of bytes. * * Results: *	The newly create object is returned.  This object will have no *	initial string representation.  The returned object has a ref count *	of 0. * * Side effects: *	Memory allocated for new object and copy of byte array argument. * *--------------------------------------------------------------------------- */#ifdef TCL_MEM_DEBUG#undef Tcl_NewByteArrayObjTcl_Obj *Tcl_NewByteArrayObj(bytes, length)    CONST unsigned char *bytes;	/* The array of bytes used to initialize				 * the new object. */    int length;			/* Length of the array of bytes, which must				 * be >= 0. */{    return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0);}#else /* if not TCL_MEM_DEBUG */Tcl_Obj *Tcl_NewByteArrayObj(bytes, length)    CONST unsigned char *bytes;	/* The array of bytes used to initialize				 * the new object. */    int length;			/* Length of the array of bytes, which must				 * be >= 0. */{    Tcl_Obj *objPtr;    TclNewObj(objPtr);    Tcl_SetByteArrayObj(objPtr, bytes, length);    return objPtr;}#endif /* TCL_MEM_DEBUG *//* *--------------------------------------------------------------------------- * * Tcl_DbNewByteArrayObj -- * *	This procedure is normally called when debugging: i.e., when *	TCL_MEM_DEBUG is defined. It is the same as the Tcl_NewByteArrayObj *	above except that it calls Tcl_DbCkalloc directly with the file name *	and line number from its caller. This simplifies debugging since then *	the [memory active] command will report the correct file name and line *	number when reporting objects that haven't been freed. * *	When TCL_MEM_DEBUG is not defined, this procedure just returns the *	result of calling Tcl_NewByteArrayObj. * * Results: *	The newly create object is returned.  This object will have no *	initial string representation.  The returned object has a ref count *	of 0. * * Side effects: *	Memory allocated for new object and copy of byte array argument. * *--------------------------------------------------------------------------- */#ifdef TCL_MEM_DEBUGTcl_Obj *Tcl_DbNewByteArrayObj(bytes, length, file, line)    CONST unsigned char *bytes;	/* The array of bytes used to initialize				 * the new object. */    int length;			/* Length of the array of bytes, which must				 * be >= 0. */    CONST char *file;		/* The name of the source file calling this				 * procedure; used for debugging. */    int line;			/* Line number in the source file; used				 * for debugging. */{    Tcl_Obj *objPtr;    TclDbNewObj(objPtr, file, line);    Tcl_SetByteArrayObj(objPtr, bytes, length);    return objPtr;}#else /* if not TCL_MEM_DEBUG */Tcl_Obj *Tcl_DbNewByteArrayObj(bytes, length, file, line)    CONST unsigned char *bytes;	/* The array of bytes used to initialize				 * the new object. */    int length;			/* Length of the array of bytes, which must				 * be >= 0. */    CONST char *file;		/* The name of the source file calling this				 * procedure; used for debugging. */    int line;			/* Line number in the source file; used				 * for debugging. */{    return Tcl_NewByteArrayObj(bytes, length);}#endif /* TCL_MEM_DEBUG *//* *--------------------------------------------------------------------------- * * Tcl_SetByteArrayObj -- * *	Modify an object to be a ByteArray object and to have the specified *	array of bytes as its value. * * Results: *	None. * * Side effects: *	The object's old string rep and internal rep is freed. *	Memory allocated for copy of byte array argument. * *---------------------------------------------------------------------- */voidTcl_SetByteArrayObj(objPtr, bytes, length)    Tcl_Obj *objPtr;		/* Object to initialize as a ByteArray. */    CONST unsigned char *bytes;	/* The array of bytes to use as the new				 * value. */    int length;			/* Length of the array of bytes, which must				 * be >= 0. */{    Tcl_ObjType *typePtr;    ByteArray *byteArrayPtr;    if (Tcl_IsShared(objPtr)) {	panic("Tcl_SetByteArrayObj called with shared object");    }    typePtr = objPtr->typePtr;    if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {	(*typePtr->freeIntRepProc)(objPtr);    }    Tcl_InvalidateStringRep(objPtr);    byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));    byteArrayPtr->used = length;    byteArrayPtr->allocated = length;    memcpy((VOID *) byteArrayPtr->bytes, (VOID *) bytes, (size_t) length);    objPtr->typePtr = &tclByteArrayType;    SET_BYTEARRAY(objPtr, byteArrayPtr);}/* *---------------------------------------------------------------------- * * Tcl_GetByteArrayFromObj -- * *	Attempt to get the array of bytes from the Tcl object.  If the *	object is not already a ByteArray object, an attempt will be *	made to convert it to one. * * Results: *	Pointer to array of bytes representing the ByteArray object. * * Side effects: *	Frees old internal rep.  Allocates memory for new internal rep. * *---------------------------------------------------------------------- */unsigned char *Tcl_GetByteArrayFromObj(objPtr, lengthPtr)    Tcl_Obj *objPtr;		/* The ByteArray object. */    int *lengthPtr;		/* If non-NULL, filled with length of the				 * array of bytes in the ByteArray object. */{    ByteArray *baPtr;        SetByteArrayFromAny(NULL, objPtr);    baPtr = GET_BYTEARRAY(objPtr);    if (lengthPtr != NULL) {	*lengthPtr = baPtr->used;    }    return (unsigned char *) baPtr->bytes;}/* *---------------------------------------------------------------------- * * Tcl_SetByteArrayLength -- * *	This procedure changes the length of the byte array for this *	object.  Once the caller has set the length of the array, it *	is acceptable to directly modify the bytes in the array up until *	Tcl_GetStringFromObj() has been called on this object. * * Results: *	The new byte array of the specified length. * * Side effects: *	Allocates enough memory for an array of bytes of the requested *	size.  When growing the array, the old array is copied to the *	new array; new bytes are undefined.  When shrinking, the *	old array is truncated to the specified length. * *--------------------------------------------------------------------------- */unsigned char *Tcl_SetByteArrayLength(objPtr, length)    Tcl_Obj *objPtr;		/* The ByteArray object. */    int length;			/* New length for internal byte array. */{    ByteArray *byteArrayPtr, *newByteArrayPtr;        if (Tcl_IsShared(objPtr)) {	panic("Tcl_SetObjLength called with shared object");    }    if (objPtr->typePtr != &tclByteArrayType) {	SetByteArrayFromAny(NULL, objPtr);    }    byteArrayPtr = GET_BYTEARRAY(objPtr);    if (length > byteArrayPtr->allocated) {	newByteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));	newByteArrayPtr->used = length;	newByteArrayPtr->allocated = length;	memcpy((VOID *) newByteArrayPtr->bytes,		(VOID *) byteArrayPtr->bytes, (size_t) byteArrayPtr->used);	ckfree((char *) byteArrayPtr);	byteArrayPtr = newByteArrayPtr;	SET_BYTEARRAY(objPtr, byteArrayPtr);    }    Tcl_InvalidateStringRep(objPtr);    byteArrayPtr->used = length;    return byteArrayPtr->bytes;}/* *--------------------------------------------------------------------------- * * SetByteArrayFromAny -- * *	Generate the ByteArray internal rep from the string rep. * * Results: *	The return value is always TCL_OK. * * Side effects: *	A ByteArray object is stored as the internal rep of objPtr. * *--------------------------------------------------------------------------- */static intSetByteArrayFromAny(interp, objPtr)    Tcl_Interp *interp;		/* Not used. */    Tcl_Obj *objPtr;		/* The object to convert to type ByteArray. */{    Tcl_ObjType *typePtr;    int length;    char *src, *srcEnd;    unsigned char *dst;    ByteArray *byteArrayPtr;    Tcl_UniChar ch;        typePtr = objPtr->typePtr;    if (typePtr != &tclByteArrayType) {	src = Tcl_GetStringFromObj(objPtr, &length);	srcEnd = src + length;	byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));	for (dst = byteArrayPtr->bytes; src < srcEnd; ) {	    src += Tcl_UtfToUniChar(src, &ch);	    *dst++ = (unsigned char) ch;	}	byteArrayPtr->used = dst - byteArrayPtr->bytes;	byteArrayPtr->allocated = length;	if ((typePtr != NULL) && (typePtr->freeIntRepProc) != NULL) {	    (*typePtr->freeIntRepProc)(objPtr);	}	objPtr->typePtr = &tclByteArrayType;	SET_BYTEARRAY(objPtr, byteArrayPtr);    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * FreeByteArrayInternalRep -- * *	Deallocate the storage associated with a ByteArray data object's *	internal representation. * * Results: *	None. * * Side effects: *	Frees memory.  * *---------------------------------------------------------------------- */static voidFreeByteArrayInternalRep(objPtr)    Tcl_Obj *objPtr;		/* Object with internal rep to free. */{    ckfree((char *) GET_BYTEARRAY(objPtr));}/* *--------------------------------------------------------------------------- * * DupByteArrayInternalRep -- * *	Initialize the internal representation of a ByteArray Tcl_Obj *	to a copy of the internal representation of an existing ByteArray *	object.  * * Results: *	None. * * Side effects: *	Allocates memory. * *--------------------------------------------------------------------------- */static voidDupByteArrayInternalRep(srcPtr, copyPtr)    Tcl_Obj *srcPtr;		/* Object with internal rep to copy. */    Tcl_Obj *copyPtr;		/* Object with internal rep to set. */{    int length;    ByteArray *srcArrayPtr, *copyArrayPtr;        srcArrayPtr = GET_BYTEARRAY(srcPtr);    length = srcArrayPtr->used;    copyArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));    copyArrayPtr->used = length;    copyArrayPtr->allocated = length;    memcpy((VOID *) copyArrayPtr->bytes, (VOID *) srcArrayPtr->bytes,	    (size_t) length);    SET_BYTEARRAY(copyPtr, copyArrayPtr);    copyPtr->typePtr = &tclByteArrayType;}/* *--------------------------------------------------------------------------- * * UpdateStringOfByteArray -- * *	Update the string representation for a ByteArray data 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 ByteArray-to-string conversion. * *	The object becomes a string object -- the internal rep is *	discarded and the typePtr becomes NULL. * *--------------------------------------------------------------------------- */static voidUpdateStringOfByteArray(objPtr)    Tcl_Obj *objPtr;		/* ByteArray object whose string rep to				 * update. */{    int i, length, size;    unsigned char *src;    char *dst;    ByteArray *byteArrayPtr;    byteArrayPtr = GET_BYTEARRAY(objPtr);    src = byteArrayPtr->bytes;    length = byteArrayPtr->used;    /*     * How much space will string rep need?     */         size = length;    for (i = 0; i < length; i++) {	if ((src[i] == 0) || (src[i] > 127)) {	    size++;	}    }    dst = (char *) ckalloc((unsigned) (size + 1));    objPtr->bytes = dst;    objPtr->length = size;    if (size == length) {	memcpy((VOID *) dst, (VOID *) src, (size_t) size);	dst[size] = '\0';    } else {	for (i = 0; i < length; i++) {	    dst += Tcl_UniCharToUtf(src[i], dst);	}	*dst = '\0';    }}/* *---------------------------------------------------------------------- * * Tcl_BinaryObjCmd -- * *	This procedure implements the "binary" Tcl command. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */intTcl_BinaryObjCmd(dummy, interp, objc, objv)    ClientData dummy;		/* Not used. */    Tcl_Interp *interp;		/* Current interpreter. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument objects. */{    int arg;			/* Index of next argument to consume. */    int value = 0;		/* Current integer value to be packed.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -