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

📄 tclbinary.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
			}			if (count == BINARY_ALL) {			    count = length - offset;			} else {			    if (count == BINARY_NOCOUNT) {				count = 1;			    }			    if (count > (length - offset)) {				goto done;			    }			}			str = buffer + offset;			size = count;			/*			 * Trim trailing nulls and spaces, if necessary.			 */			if (cmd == 'A') {			    while (size > 0) {				if (str[size-1] != '\0' && str[size-1] != ' ') {				    break;				}				size--;			    }			}			valuePtr = Tcl_NewStringObj(str, size);			resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL,				valuePtr,				TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1);			if (resultPtr == NULL) {			    Tcl_DecrRefCount(valuePtr);	/* unneeded */			    return TCL_ERROR;			}			offset += count;			break;		    case 'b':		    case 'B': {			char *dest;			if (arg >= objc) {			    goto badIndex;			}			if (count == BINARY_ALL) {			    count = (length - offset)*8;			} else {			    if (count == BINARY_NOCOUNT) {				count = 1;			    }			    if (count > (length - offset)*8) {				goto done;			    }			}			str = buffer + offset;			valuePtr = Tcl_NewObj();			Tcl_SetObjLength(valuePtr, count);			dest = Tcl_GetStringFromObj(valuePtr, NULL);			if (cmd == 'b') {			    for (i = 0; i < count; i++) {				if (i % 8) {				    value >>= 1;				} else {				    value = *str++;				}				*dest++ = (char) ((value & 1) ? '1' : '0');			    }			} else {			    for (i = 0; i < count; i++) {				if (i % 8) {				    value <<= 1;				} else {				    value = *str++;				}				*dest++ = (char) ((value & 0x80) ? '1' : '0');			    }			}						resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL,				valuePtr,				TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1);			if (resultPtr == NULL) {			    Tcl_DecrRefCount(valuePtr);	/* unneeded */			    return TCL_ERROR;			}			offset += (count + 7 ) / 8;			break;		    }		    case 'h':		    case 'H': {			char *dest;			int i;			static char hexdigit[] = "0123456789abcdef";			if (arg >= objc) {			    goto badIndex;			}			if (count == BINARY_ALL) {			    count = (length - offset)*2;			} else {			    if (count == BINARY_NOCOUNT) {				count = 1;			    }			    if (count > (length - offset)*2) {				goto done;			    }			}			str = buffer + offset;			valuePtr = Tcl_NewObj();			Tcl_SetObjLength(valuePtr, count);			dest = Tcl_GetStringFromObj(valuePtr, NULL);			if (cmd == 'h') {			    for (i = 0; i < count; i++) {				if (i % 2) {				    value >>= 4;				} else {				    value = *str++;				}				*dest++ = hexdigit[value & 0xf];			    }			} else {			    for (i = 0; i < count; i++) {				if (i % 2) {				    value <<= 4;				} else {				    value = *str++;				}				*dest++ = hexdigit[(value >> 4) & 0xf];			    }			}						resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL,				valuePtr,				TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1);			if (resultPtr == NULL) {			    Tcl_DecrRefCount(valuePtr);	/* unneeded */			    return TCL_ERROR;			}			offset += (count + 1) / 2;			break;		    }		    case 'c':			size = 1;			goto scanNumber;		    case 's':		    case 'S':			size = 2;			goto scanNumber;		    case 'i':		    case 'I':			size = 4;			goto scanNumber;		    case 'f':			size = sizeof(float);			goto scanNumber;		    case 'd':			size = sizeof(double);			/* fall through */		    scanNumber:			if (arg >= objc) {			    goto badIndex;			}			if (count == BINARY_NOCOUNT) {			    if ((length - offset) < size) {				goto done;			    }			    valuePtr = ScanNumber(buffer+offset, cmd);			    offset += size;			} else {			    if (count == BINARY_ALL) {				count = (length - offset) / size;			    }			    if ((length - offset) < (count * size)) {				goto done;			    }			    valuePtr = Tcl_NewObj();			    str = buffer+offset;			    for (i = 0; i < count; i++) {				elementPtr = ScanNumber(str, cmd);				str += size;				Tcl_ListObjAppendElement(NULL, valuePtr,					elementPtr);			    }			    offset += count*size;			}			resultPtr = Tcl_ObjSetVar2(interp, objv[arg++], NULL,				valuePtr,				TCL_LEAVE_ERR_MSG | TCL_PARSE_PART1);			if (resultPtr == NULL) {			    Tcl_DecrRefCount(valuePtr);	/* unneeded */			    return TCL_ERROR;			}			break;		    case 'x':			if (count == BINARY_NOCOUNT) {			    count = 1;			}			if ((count == BINARY_ALL)				|| (count > (length - offset))) {			    offset = length;			} else {			    offset += count;			}			break;		    case 'X':			if (count == BINARY_NOCOUNT) {			    count = 1;			}			if ((count == BINARY_ALL) || (count > offset)) {			    offset = 0;			} else {			    offset -= count;			}			break;		    case '@':			if (count == BINARY_NOCOUNT) {			    goto badCount;			}			if ((count == BINARY_ALL) || (count > length)) {			    offset = length;			} 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;		    }		}	    }	    /*	     * Set the result to the last position of the cursor.	     */	    done:	    Tcl_ResetResult(interp);	    Tcl_SetLongObj(Tcl_GetObjResult(interp), arg - 4);	    break;	}    }    return TCL_OK;    badValue:    Tcl_ResetResult(interp);    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "expected ", errorString,	    " string but got \"", errorValue, "\" instead", NULL);    return TCL_ERROR;    badCount:    errorString = "missing count for \"@\" field specifier";    goto error;    badIndex:    errorString = "not enough arguments for all format specifiers";    goto error;    error:    Tcl_ResetResult(interp);    Tcl_AppendToObj(Tcl_GetObjResult(interp), errorString, -1);    return TCL_ERROR;}/* *---------------------------------------------------------------------- * * GetFormatSpec -- * *	This function parses the format strings used in the binary *	format and scan commands. * * Results: *	Moves the formatPtr to the start of the next command. Returns *	the current command character and count in cmdPtr and countPtr. *	The count is set to BINARY_ALL if the count character was '*' *	or BINARY_NOCOUNT if no count was specified.  Returns 1 on *	success, or 0 if the string did not have a format specifier. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intGetFormatSpec(formatPtr, cmdPtr, countPtr)    char **formatPtr;		/* Pointer to format string. */    char *cmdPtr;		/* Pointer to location of command char. */    int *countPtr;		/* Pointer to repeat count value. */{    /*     * Skip any leading blanks.     */    while (**formatPtr == ' ') {	(*formatPtr)++;    }    /*     * The string was empty, except for whitespace, so fail.     */    if (!(**formatPtr)) {	return 0;    }    /*     * Extract the command character and any trailing digits or '*'.     */    *cmdPtr = **formatPtr;    (*formatPtr)++;    if (**formatPtr == '*') {	(*formatPtr)++;	(*countPtr) = BINARY_ALL;    } else if (isdigit(UCHAR(**formatPtr))) {	(*countPtr) = strtoul(*formatPtr, formatPtr, 10);    } else {	(*countPtr) = BINARY_NOCOUNT;    }    return 1;}/* *---------------------------------------------------------------------- * * FormatNumber -- * *	This routine is called by Tcl_BinaryObjCmd to format a number *	into a location pointed at by cursor. * * Results: *	 A standard Tcl result. * * Side effects: *	Moves the cursor to the next location to be written into. * *---------------------------------------------------------------------- */static intFormatNumber(interp, type, src, cursorPtr)    Tcl_Interp *interp;		/* Current interpreter, used to report				 * errors. */    int type;			/* Type of number to format. */    Tcl_Obj *src;		/* Number to format. */    char **cursorPtr;		/* Pointer to index into destination buffer. */{    int value;    double dvalue;    char cmd = (char)type;    if (cmd == 'd' || cmd == 'f') {	/*	 * For floating point types, we need to copy the data using	 * memcpy to avoid alignment issues.	 */	if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {	    return TCL_ERROR;	}	if (cmd == 'd') {	    memcpy((*cursorPtr), &dvalue, sizeof(double));	    (*cursorPtr) += sizeof(double);	} else {	    float fvalue;	    /*	     * Because some compilers will generate floating point exceptions	     * on an overflow cast (e.g. Borland), we restrict the values	     * to the valid range for float.	     */	    if (fabs(dvalue) > (double)FLT_MAX) {		fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;	    } else {		fvalue = (float) dvalue;	    }	    memcpy((*cursorPtr), &fvalue, sizeof(float));	    (*cursorPtr) += sizeof(float);	}    } else {	if (Tcl_GetIntFromObj(interp, src, &value) != TCL_OK) {	    return TCL_ERROR;	}	if (cmd == 'c') {	    *(*cursorPtr)++ = (char)(value & 0xff);	} else if (cmd == 's') {	    *(*cursorPtr)++ = (char)(value & 0xff);	    *(*cursorPtr)++ = (char)((value >> 8) & 0xff);	} else if (cmd == 'S') {	    *(*cursorPtr)++ = (char)((value >> 8) & 0xff);	    *(*cursorPtr)++ = (char)(value & 0xff);	} else if (cmd == 'i') {	    *(*cursorPtr)++ = (char)(value & 0xff);	    *(*cursorPtr)++ = (char)((value >> 8) & 0xff);	    *(*cursorPtr)++ = (char)((value >> 16) & 0xff);	    *(*cursorPtr)++ = (char)((value >> 24) & 0xff);	} else if (cmd == 'I') {	    *(*cursorPtr)++ = (char)((value >> 24) & 0xff);	    *(*cursorPtr)++ = (char)((value >> 16) & 0xff);	    *(*cursorPtr)++ = (char)((value >> 8) & 0xff);	    *(*cursorPtr)++ = (char)(value & 0xff);	}    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * ScanNumber -- * *	This routine is called by Tcl_BinaryObjCmd to scan a number *	out of a buffer. * * Results: *	Returns a newly created object containing the scanned number. *	This object has a ref count of zero. * * Side effects: *	None. * *---------------------------------------------------------------------- */static Tcl_Obj *ScanNumber(buffer, type)    char *buffer;		/* Buffer to scan number from. */    int type;			/* Format character from "binary scan" */{    int value;    /*     * We cannot rely on the compiler to properly sign extend integer values     * when we cast from smaller values to larger values because we don't know     * the exact size of the integer types.  So, we have to handle sign     * extension explicitly by checking the high bit and padding with 1's as     * needed.     */    switch ((char) type) {	case 'c':	    value = buffer[0];	    if (value & 0x80) {		value |= -0x100;	    }	    return Tcl_NewLongObj((long)value);	case 's':	    value = (((unsigned char)buffer[0])		    + ((unsigned char)buffer[1] << 8));	    goto shortValue;	case 'S':	    value = (((unsigned char)buffer[1])		    + ((unsigned char)buffer[0] << 8));	    shortValue:	    if (value & 0x8000) {		value |= -0x10000;	    }	    return Tcl_NewLongObj((long)value);	case 'i':	    value =  (((unsigned char)buffer[0])		    + ((unsigned char)buffer[1] << 8)		    + ((unsigned char)buffer[2] << 16)		    + ((unsigned char)buffer[3] << 24));	    goto intValue;	case 'I':	    value = (((unsigned char)buffer[3])		    + ((unsigned char)buffer[2] << 8)		    + ((unsigned char)buffer[1] << 16)		    + ((unsigned char)buffer[0] << 24));	    intValue:	    /*	     * Check to see if the value was sign extended properly on	     * systems where an int is more than 32-bits.	     */	    if ((value & (((unsigned int)1)<<31)) && (value > 0)) {		value -= (((unsigned int)1)<<31);		value -= (((unsigned int)1)<<31);	    }			    return Tcl_NewLongObj((long)value);	case 'f': {	    float fvalue;	    memcpy(&fvalue, buffer, sizeof(float));	    return Tcl_NewDoubleObj(fvalue);	}	case 'd': {	    double dvalue;	    memcpy(&dvalue, buffer, sizeof(double));	    return Tcl_NewDoubleObj(dvalue);	}    }    return NULL;}

⌨️ 快捷键说明

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