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

📄 tclbinary.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 3 页
字号:
				 * Initialized to avoid compiler warning. */    char cmd;			/* Current format character. */    int count;			/* Count associated with current format				 * character. */    char *format;		/* Pointer to current position in format				 * string. */    Tcl_Obj *resultPtr;		/* Object holding result buffer. */    unsigned char *buffer;	/* Start of result buffer. */    unsigned char *cursor;	/* Current position within result buffer. */    unsigned char *maxPos;	/* Greatest position within result buffer that				 * cursor has visited.*/    char *errorString, *errorValue, *str;    int offset, size, length, index;    static CONST char *options[] = { 	"format",	"scan",		NULL     };    enum options { 	BINARY_FORMAT,	BINARY_SCAN    };    if (objc < 2) {    	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");	return TCL_ERROR;    }    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,	    &index) != TCL_OK) {    	return TCL_ERROR;    }    switch ((enum options) index) {	case BINARY_FORMAT: {	    if (objc < 3) {		Tcl_WrongNumArgs(interp, 2, objv, "formatString ?arg arg ...?");		return TCL_ERROR;	    }	    /*	     * To avoid copying the data, we format the string in two passes.	     * The first pass computes the size of the output buffer.  The	     * second pass places the formatted data into the buffer.	     */	    format = Tcl_GetString(objv[2]);	    arg = 3;	    offset = 0;	    length = 0;	    while (*format != '\0') {		str = format;		if (!GetFormatSpec(&format, &cmd, &count)) {		    break;		}		switch (cmd) {		    case 'a':		    case 'A':		    case 'b':		    case 'B':		    case 'h':		    case 'H': {			/*			 * For string-type specifiers, the count corresponds			 * to the number of bytes in a single argument.			 */			if (arg >= objc) {			    goto badIndex;			}			if (count == BINARY_ALL) {			    Tcl_GetByteArrayFromObj(objv[arg], &count);			} else if (count == BINARY_NOCOUNT) {			    count = 1;			}			arg++;			if (cmd == 'a' || cmd == 'A') {			    offset += count;			} else if (cmd == 'b' || cmd == 'B') {			    offset += (count + 7) / 8;			} else {			    offset += (count + 1) / 2;			}			break;		    }		    case 'c': {			size = 1;			goto doNumbers;		    }		    case 's':		    case 'S': {			size = 2;			goto doNumbers;		    }		    case 'i':		    case 'I': {			size = 4;			goto doNumbers;		    }		    case 'w':		    case 'W': {			size = 8;			goto doNumbers;		    }		    case 'f': {			size = sizeof(float);			goto doNumbers;		    }		    case 'd': {			size = sizeof(double);						doNumbers:			if (arg >= objc) {			    goto badIndex;			}			/*			 * For number-type specifiers, the count corresponds			 * to the number of elements in the list stored in			 * a single argument.  If no count is specified, then			 * the argument is taken as a single non-list value.			 */			if (count == BINARY_NOCOUNT) {			    arg++;			    count = 1;			} else {			    int listc;			    Tcl_Obj **listv;			    if (Tcl_ListObjGetElements(interp, objv[arg++],				    &listc, &listv) != TCL_OK) {				return TCL_ERROR;			    }			    if (count == BINARY_ALL) {				count = listc;			    } else if (count > listc) {			        Tcl_AppendResult(interp, 					"number of elements in list does not match count",					(char *) NULL);				return TCL_ERROR;			    }			}			offset += count*size;			break;		    }		    case 'x': {			if (count == BINARY_ALL) {			    Tcl_AppendResult(interp, 				    "cannot use \"*\" in format string with \"x\"",				    (char *) NULL);			    return TCL_ERROR;			} else if (count == BINARY_NOCOUNT) {			    count = 1;			}			offset += count;			break;		    }		    case 'X': {			if (count == BINARY_NOCOUNT) {			    count = 1;			}			if ((count > offset) || (count == BINARY_ALL)) {			    count = offset;			}			if (offset > length) {			    length = offset;			}			offset -= count;			break;		    }		    case '@': {			if (offset > length) {			    length = offset;			}			if (count == BINARY_ALL) {			    offset = length;			} else if (count == BINARY_NOCOUNT) {			    goto badCount;			} else {			    offset = count;			}			break;		    }		    default: {			errorString = str;			goto badfield;		    }		}	    }	    if (offset > length) {		length = offset;	    }	    if (length == 0) {		return TCL_OK;	    }	    /*	     * Prepare the result object by preallocating the caclulated	     * number of bytes and filling with nulls.	     */	    resultPtr = Tcl_GetObjResult(interp);	    buffer = Tcl_SetByteArrayLength(resultPtr, length);	    memset((VOID *) buffer, 0, (size_t) length);	    /*	     * Pack the data into the result object.  Note that we can skip	     * the error checking during this pass, since we have already	     * parsed the string once.	     */	    arg = 3;	    format = Tcl_GetString(objv[2]);	    cursor = buffer;	    maxPos = cursor;	    while (*format != 0) {		if (!GetFormatSpec(&format, &cmd, &count)) {		    break;		}		if ((count == 0) && (cmd != '@')) {		    arg++;		    continue;		}		switch (cmd) {		    case 'a':		    case 'A': {			char pad = (char) (cmd == 'a' ? '\0' : ' ');			unsigned char *bytes;			bytes = Tcl_GetByteArrayFromObj(objv[arg++], &length);			if (count == BINARY_ALL) {			    count = length;			} else if (count == BINARY_NOCOUNT) {			    count = 1;			}			if (length >= count) {			    memcpy((VOID *) cursor, (VOID *) bytes,				    (size_t) count);			} else {			    memcpy((VOID *) cursor, (VOID *) bytes,				    (size_t) length);			    memset((VOID *) (cursor + length), pad,			            (size_t) (count - length));			}			cursor += count;			break;		    }		    case 'b':		    case 'B': {			unsigned char *last;						str = Tcl_GetStringFromObj(objv[arg++], &length);			if (count == BINARY_ALL) {			    count = length;			} else if (count == BINARY_NOCOUNT) {			    count = 1;			}			last = cursor + ((count + 7) / 8);			if (count > length) {			    count = length;			}			value = 0;			errorString = "binary";			if (cmd == 'B') {			    for (offset = 0; offset < count; offset++) {				value <<= 1;				if (str[offset] == '1') {				    value |= 1;				} else if (str[offset] != '0') {				    errorValue = str;				    goto badValue;				}				if (((offset + 1) % 8) == 0) {				    *cursor++ = (unsigned char) value;				    value = 0;				}			    }			} else {			    for (offset = 0; offset < count; offset++) {				value >>= 1;				if (str[offset] == '1') {				    value |= 128;				} else if (str[offset] != '0') {				    errorValue = str;				    goto badValue;				}				if (!((offset + 1) % 8)) {				    *cursor++ = (unsigned char) value;				    value = 0;				}			    }			}			if ((offset % 8) != 0) {			    if (cmd == 'B') {				value <<= 8 - (offset % 8);			    } else {				value >>= 8 - (offset % 8);			    }			    *cursor++ = (unsigned char) value;			}			while (cursor < last) {			    *cursor++ = '\0';			}			break;		    }		    case 'h':		    case 'H': {			unsigned char *last;			int c;						str = Tcl_GetStringFromObj(objv[arg++], &length);			if (count == BINARY_ALL) {			    count = length;			} else if (count == BINARY_NOCOUNT) {			    count = 1;			}			last = cursor + ((count + 1) / 2);			if (count > length) {			    count = length;			}			value = 0;			errorString = "hexadecimal";			if (cmd == 'H') {			    for (offset = 0; offset < count; offset++) {				value <<= 4;				if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */				    errorValue = str;				    goto badValue;				}				c = str[offset] - '0';				if (c > 9) {				    c += ('0' - 'A') + 10;				}				if (c > 16) {				    c += ('A' - 'a');				}				value |= (c & 0xf);				if (offset % 2) {				    *cursor++ = (char) value;				    value = 0;				}			    }			} else {			    for (offset = 0; offset < count; offset++) {				value >>= 4;				if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */				    errorValue = str;				    goto badValue;				}				c = str[offset] - '0';				if (c > 9) {				    c += ('0' - 'A') + 10;				}				if (c > 16) {				    c += ('A' - 'a');				}				value |= ((c << 4) & 0xf0);				if (offset % 2) {				    *cursor++ = (unsigned char)(value & 0xff);				    value = 0;				}			    }			}			if (offset % 2) {			    if (cmd == 'H') {				value <<= 4;			    } else {				value >>= 4;			    }			    *cursor++ = (unsigned char) value;			}			while (cursor < last) {			    *cursor++ = '\0';			}			break;		    }		    case 'c':		    case 's':		    case 'S':		    case 'i':		    case 'I':		    case 'w':		    case 'W':		    case 'd':		    case 'f': {			int listc, i;			Tcl_Obj **listv;			if (count == BINARY_NOCOUNT) {			    /*			     * Note that we are casting away the const-ness of			     * objv, but this is safe since we aren't going to			     * modify the array.			     */			    listv = (Tcl_Obj**)(objv + arg);			    listc = 1;			    count = 1;			} else {			    Tcl_ListObjGetElements(interp, objv[arg],				    &listc, &listv);			    if (count == BINARY_ALL) {				count = listc;			    }			}			arg++;			for (i = 0; i < count; i++) {			    if (FormatNumber(interp, cmd, listv[i], &cursor)				    != TCL_OK) {				return TCL_ERROR;			    }			}			break;		    }		    case 'x': {			if (count == BINARY_NOCOUNT) {			    count = 1;			}			memset(cursor, 0, (size_t) count);			cursor += count;			break;		    }		    case 'X': {			if (cursor > maxPos) {			    maxPos = cursor;			}			if (count == BINARY_NOCOUNT) {			    count = 1;			}			if ((count == BINARY_ALL)				|| (count > (cursor - buffer))) {			    cursor = buffer;			} else {			    cursor -= count;			}			break;		    }		    case '@': {			if (cursor > maxPos) {			    maxPos = cursor;			}			if (count == BINARY_ALL) {			    cursor = maxPos;			} else {			    cursor = buffer + count;			}			break;		    }		}	    }	    break;	}	case BINARY_SCAN: {	    int i;	    Tcl_Obj *valuePtr, *elementPtr;	    Tcl_HashTable numberCacheHash;	    Tcl_HashTable *numberCachePtr;	    if (objc < 4) {		Tcl_WrongNumArgs(interp, 2, objv,			"value formatString ?varName varName ...?");		return TCL_ERROR;	    }	    numberCachePtr = &numberCacheHash;	    Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS);	    buffer = Tcl_GetByteArrayFromObj(objv[2], &length);	    format = Tcl_GetString(objv[3]);	    cursor = buffer;	    arg = 4;	    offset = 0;	    while (*format != '\0') {		str = format;		if (!GetFormatSpec(&format, &cmd, &count)) {		    goto done;		}		switch (cmd) {		    case 'a':		    case 'A': {			unsigned char *src;			if (arg >= objc) {			    if (numberCachePtr != NULL) {				Tcl_DeleteHashTable(numberCachePtr);			    }			    goto badIndex;			}			if (count == BINARY_ALL) {			    count = length - offset;			} else {			    if (count == BINARY_NOCOUNT) {				count = 1;			    }			    if (count > (length - offset)) {				goto done;			    }			}			src = buffer + offset;			size = count;			/*			 * Trim trailing nulls and spaces, if necessary.			 */			if (cmd == 'A') {			    while (size > 0) {				if (src[size-1] != '\0' && src[size-1] != ' ') {				    break;				}				size--;			    }			}			valuePtr = Tcl_NewByteArrayObj(src, size);			resultPtr = Tcl_ObjSetVar2(interp, objv[arg],				NULL, valuePtr, TCL_LEAVE_ERR_MSG);			arg++;			if (resultPtr == NULL) {			    if (numberCachePtr != NULL) {				Tcl_DeleteHashTable(numberCachePtr);			    }			    Tcl_DecrRefCount(valuePtr);	/* unneeded */			    return TCL_ERROR;			}			offset += count;			break;		    }		    case 'b':		    case 'B': {			unsigned char *src;			char *dest;			if (arg >= objc) {			    if (numberCachePtr != NULL) {				Tcl_DeleteHashTable(numberCachePtr);			    }			    goto badIndex;			}			if (count == BINARY_ALL) {			    count = (length - offset) * 8;			} else {			    if (count == BINARY_NOCOUNT) {				count = 1;			    }			    if (count > (length - offset) * 8) {				goto done;			    }			}			src = buffer + offset;			valuePtr = Tcl_NewObj();			Tcl_SetObjLength(valuePtr, count);			dest = Tcl_GetString(valuePtr);			if (cmd == 'b') {			    for (i = 0; i < count; i++) {				if (i % 8) {				    value >>= 1;				} else {				    value = *src++;				}				*dest++ = (char) ((value & 1) ? '1' : '0');			    }			} else {			    for (i = 0; i < count; i++) {				if (i % 8) {				    value <<= 1;				} else {				    value = *src++;				}				*dest++ = (char) ((value & 0x80) ? '1' : '0');			    }			}

⌨️ 快捷键说明

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