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

📄 tclbinary.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * tclBinary.c -- * *	This file contains the implementation of the "binary" Tcl built-in *	command . * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclBinary.c 1.26 97/11/05 13:02:05 */#include <math.h>#include "tclInt.h"#include "tclPort.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. *//* * Prototypes for local procedures defined in this file: */static int		GetFormatSpec _ANSI_ARGS_((char **formatPtr,			    char *cmdPtr, int *countPtr));static int		FormatNumber _ANSI_ARGS_((Tcl_Interp *interp, int type,			    Tcl_Obj *src, char **cursorPtr));static Tcl_Obj *	ScanNumber _ANSI_ARGS_((char *buffer, int type));/* *---------------------------------------------------------------------- * * 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.				 * 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. */    char *cursor;		/* Current position within result buffer. */    char *maxPos;		/* Greatest position within result buffer that				 * cursor has visited.*/    char *buffer;		/* Start of data buffer. */    char *errorString, *errorValue, *str;    int offset, size, length;    Tcl_Obj *resultPtr;        static char *subCmds[] = { "format", "scan", (char *) NULL };    enum { BinaryFormat, BinaryScan } index;    if (objc < 2) {    	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");	return TCL_ERROR;    }    if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", 0,	    (int *) &index) != TCL_OK) {    	return TCL_ERROR;    }    switch (index) {	case BinaryFormat:	    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_GetStringFromObj(objv[2], NULL);	    arg = 3;	    offset = length = 0;	    while (*format != 0) {		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 characters in a single argument.			 */			if (arg >= objc) {			    goto badIndex;			}			if (count == BINARY_ALL) {			    (void)Tcl_GetStringFromObj(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 '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) {				errorString = "number of elements in list does not match count";				goto error;			    }			}			offset += count*size;			break;					    case 'x':			if (count == BINARY_ALL) {			    errorString = "cannot use \"*\" in format string with \"x\"";			    goto 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: {			char buf[2];						Tcl_ResetResult(interp);			buf[0] = cmd;			buf[1] = '\0';			Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),				"bad field specifier \"", buf, "\"", NULL);			return TCL_ERROR;		    }		}	    }	    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);	    Tcl_SetObjLength(resultPtr, length);	    buffer = Tcl_GetStringFromObj(resultPtr, NULL);	    memset(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_GetStringFromObj(objv[2], NULL);	    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' : ' ');			str = Tcl_GetStringFromObj(objv[arg++], &length);			if (count == BINARY_ALL) {			    count = length;			} else if (count == BINARY_NOCOUNT) {			    count = 1;			}			if (length >= count) {			    memcpy((VOID *) cursor, (VOID *) str,				    (size_t) count);			} else {			    memcpy((VOID *) cursor, (VOID *) str,				    (size_t) length);			    memset(cursor+length, pad,			            (size_t) (count - length));			}			cursor += count;			break;		    }		    case 'b':		    case 'B': {			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++ = (char)(value & 0xff);				    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++ = (char)(value & 0xff);				    value = 0;				}			    }			}			if ((offset % 8) != 0) {			    if (cmd == 'B') {				value <<= 8 - (offset % 8);			    } else {				value >>= 8 - (offset % 8);			    }			    *cursor++ = (char)(value & 0xff);			}			while (cursor < last) {			    *cursor++ = '\0';			}			break;		    }		    case 'h':		    case 'H': {			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;				c = tolower(((unsigned char *) str)[offset]);				if ((c >= 'a') && (c <= 'f')) {				    value |= ((c - 'a' + 10) & 0xf);				} else if ((c >= '0') && (c <= '9')) {				    value |= (c - '0') & 0xf;				} else {				    errorValue = str;				    goto badValue;				}				if (offset % 2) {				    *cursor++ = (char) value;				    value = 0;				}			    }			} else {			    for (offset = 0; offset < count; offset++) {				value >>= 4;				c = tolower(((unsigned char *) str)[offset]);				if ((c >= 'a') && (c <= 'f')) {				    value |= ((c - 'a' + 10) << 4) & 0xf0;				} else if ((c >= '0') && (c <= '9')) {				    value |= ((c - '0') << 4) & 0xf0;				} else {				    errorValue = str;				    goto badValue;				}				if (offset % 2) {				    *cursor++ = (char)(value & 0xff);				    value = 0;				}			    }			}			if (offset % 2) {			    if (cmd == 'H') {				value <<= 4;			    } else {				value >>= 4;			    }			    *cursor++ = (char) value;			}			while (cursor < last) {			    *cursor++ = '\0';			}			break;		    }		    case 'c':		    case 's':		    case 'S':		    case 'i':		    case 'I':		    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 BinaryScan: {	    int i;	    Tcl_Obj *valuePtr, *elementPtr;	    if (objc < 4) {		Tcl_WrongNumArgs(interp, 2, objv,			"value formatString ?varName varName ...?");		return TCL_ERROR;	    }	    buffer = Tcl_GetStringFromObj(objv[2], &length);	    format = Tcl_GetStringFromObj(objv[3], NULL);	    cursor = buffer;	    arg = 4;	    offset = 0;	    while (*format != 0) {		if (!GetFormatSpec(&format, &cmd, &count)) {		    goto done;		}		switch (cmd) {		    case 'a':		    case 'A':			if (arg >= objc) {			    goto badIndex;

⌨️ 快捷键说明

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