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

📄 pack.c

📁 php-4.4.7学习linux时下载的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	efree(argv);	efree(formatcodes);	efree(formatargs);	output[outputpos] = '\0';	RETVAL_STRINGL(output, outputpos, 1);	efree(output);}/* }}} *//* {{{ php_unpack */static long php_unpack(char *data, int size, int issigned, int *map){	long result;	char *cresult = (char *) &result;	int i;	result = issigned ? -1 : 0;	for (i = 0; i < size; i++) {		cresult[map[i]] = *data++;	}	return result;}/* }}} *//* unpack() is based on Perl's unpack(), but is modified a bit from there. * Rather than depending on error-prone ordered lists or syntactically * unpleasant pass-by-reference, we return an object with named paramters  * (like *_fetch_object()). Syntax is "f[repeat]name/...", where "f" is the * formatter char (like pack()), "[repeat]" is the optional repeater argument, * and "name" is the name of the variable to use. * Example: "c2chars/nints" will return an object with fields * chars1, chars2, and ints. * Numeric pack types will return numbers, a and A will return strings, * f and d will return doubles. * Implemented formats are A, a, h, H, c, C, s, S, i, I, l, L, n, N, f, d, x, X, @. *//* {{{ proto array unpack(string format, string input)   Unpack binary string into named array elements according to format argument */PHP_FUNCTION(unpack){	zval **formatarg;	zval **inputarg;	char *format;	char *input;	int formatlen;	int inputpos, inputlen;	int i;	if (ZEND_NUM_ARGS() != 2 ||         zend_get_parameters_ex(2, &formatarg, &inputarg) == FAILURE) {		WRONG_PARAM_COUNT;	}	convert_to_string_ex(formatarg);	convert_to_string_ex(inputarg);	format = Z_STRVAL_PP(formatarg);	formatlen = Z_STRLEN_PP(formatarg);	input = Z_STRVAL_PP(inputarg);	inputlen = Z_STRLEN_PP(inputarg);	inputpos = 0;	array_init(return_value);	while (formatlen-- > 0) {		char type = *(format++);		char c;		int arg = 1, argb;		char *name;		int namelen;		int size=0;		/* Handle format arguments if any */		if (formatlen > 0) {			c = *format;			if (c >= '0' && c <= '9') {				arg = atoi(format);				while (formatlen > 0 && *format >= '0' && *format <= '9') {					format++;					formatlen--;				}			} else if (c == '*') {				arg = -1;				format++;				formatlen--;			}		}		/* Get of new value in array */		name = format;		argb = arg;		while (formatlen > 0 && *format != '/') {			formatlen--;			format++;		}		namelen = format - name;		if (namelen > 200)			namelen = 200;		switch ((int) type) {			/* Never use any input */			case 'X': 				size = -1;				break;			case '@':				size = 0;				break;			case 'a': 			case 'A':				size = arg;				arg = 1;				break;			case 'h': 			case 'H': 				size = (arg > 0) ? (arg + (arg % 2)) / 2 : arg;				arg = 1;				break;			/* Use 1 byte of input */			case 'c': 			case 'C':			case 'x':				size = 1;				break;			/* Use 2 bytes of input */			case 's': 			case 'S': 			case 'n': 			case 'v':				size = 2;				break;			/* Use sizeof(int) bytes of input */			case 'i': 			case 'I':				size = sizeof(int);				break;			/* Use 4 bytes of input */			case 'l': 			case 'L': 			case 'N': 			case 'V':				size = 4;				break;			/* Use sizeof(float) bytes of input */			case 'f':				size = sizeof(float);				break;			/* Use sizeof(double) bytes of input */			case 'd':				size = sizeof(double);				break;		}		/* Do actual unpacking */		for (i = 0; i != arg; i++ ) {			/* Space for name + number, safe as namelen is ensured <= 200 */			char n[256];			if (arg != 1 || namelen == 0) {				/* Need to add element number to name */				sprintf(n, "%.*s%d", namelen, name, i + 1);			} else {				/* Truncate name to next format code or end of string */				sprintf(n, "%.*s", namelen, name);			}			if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) {				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow", type);				inputpos = 0;			}			if ((inputpos + size) <= inputlen) {				switch ((int) type) {					case 'a': 					case 'A': {						char pad = (type == 'a') ? '\0' : ' ';						int len = inputlen - inputpos;	/* Remaining string */						/* If size was given take minimum of len and size */						if ((size >= 0) && (len > size)) {							len = size;						}						size = len;						/* Remove padding chars from unpacked data */						while (--len >= 0) {							if (input[inputpos + len] != pad)								break;						}						add_assoc_stringl(return_value, n, &input[inputpos], len + 1, 1);						break;					}										case 'h': 					case 'H': {						int len = (inputlen - inputpos) * 2;	/* Remaining */						int nibbleshift = (type == 'h') ? 0 : 4;						int first = 1;						char *buf;						int ipos, opos;						/* If size was given take minimum of len and size */						if (size >= 0 && len > (size * 2)) {							len = size * 2;						} 						if (argb > 0) {								len -= argb % 2;						}						buf = emalloc(len + 1);						for (ipos = opos = 0; opos < len; opos++) {							char c = (input[inputpos + ipos] >> nibbleshift) & 0xf;							if (c < 10) {								c += '0';							} else {								c += 'a' - 10;							}							buf[opos] = c;							nibbleshift = (nibbleshift + 4) & 7;							if (first-- == 0) {								ipos++;								first = 1;							}						}						buf[len] = '\0';						add_assoc_stringl(return_value, n, buf, len, 1);						efree(buf);						break;					}					case 'c': 					case 'C': {						int issigned = (type == 'c') ? (input[inputpos] & 0x80) : 0;						long v = php_unpack(&input[inputpos], 1, issigned, byte_map);						add_assoc_long(return_value, n, v);						break;					}					case 's': 					case 'S': 					case 'n': 					case 'v': {						long v;						int issigned = 0;						int *map = machine_endian_short_map;						if (type == 's') {							issigned = input[inputpos + (machine_little_endian ? 1 : 0)] & 0x80;						} else if (type == 'n') {							map = big_endian_short_map;						} else if (type == 'v') {							map = little_endian_short_map;						}						v = php_unpack(&input[inputpos], 2, issigned, map);						add_assoc_long(return_value, n, v);						break;					}					case 'i': 					case 'I': {						long v;						int issigned = 0;						if (type == 'i') {							issigned = input[inputpos + (machine_little_endian ? (sizeof(int) - 1) : 0)] & 0x80;						}						v = php_unpack(&input[inputpos], sizeof(int), issigned, int_map);						add_assoc_long(return_value, n, v);						break;					}					case 'l': 					case 'L': 					case 'N': 					case 'V': {						int issigned = 0;						int *map = machine_endian_long_map;						long v;						if (type == 'l') {							issigned = input[inputpos + (machine_little_endian ? 3 : 0)] & 0x80;						} else if (type == 'N') {							map = big_endian_long_map;						} else if (type == 'V') {							map = little_endian_long_map;						}						v = php_unpack(&input[inputpos], 4, issigned, map);						add_assoc_long(return_value, n, v);						break;					}					case 'f': {						float v;						memcpy(&v, &input[inputpos], sizeof(float));						add_assoc_double(return_value, n, (double)v);						break;					}					case 'd': {						double v;						memcpy(&v, &input[inputpos], sizeof(double));						add_assoc_double(return_value, n, v);						break;					}					case 'x':						/* Do nothing with input, just skip it */						break;					case 'X':						if (inputpos < size) {							inputpos = -size;							i = arg - 1;		/* Break out of for loop */							if (arg >= 0) {								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);							}						}						break;					case '@':						if (arg <= inputlen) {							inputpos = arg;						} else {							php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);						}						i = arg - 1;	/* Done, break out of for loop */						break;				}				inputpos += size;				if (inputpos < 0) {					if (size != -1) { /* only print warning if not working with * */						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);					}					inputpos = 0;				}			} else if (arg < 0) {				/* Reached end of input for '*' repeater */				break;			} else {				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough input, need %d, have %d", type, size, inputlen - inputpos);				zval_dtor(return_value);				RETURN_FALSE;			}		}		formatlen--;	/* Skip '/' separator, does no harm if inputlen == 0 */		format++;	}}/* }}} *//* {{{ PHP_MINIT_FUNCTION */PHP_MINIT_FUNCTION(pack){	int machine_endian_check = 1;	int i;	machine_little_endian = ((char *)&machine_endian_check)[0];	if (machine_little_endian) {		/* Where to get lo to hi bytes from */		byte_map[0] = 0;		for (i = 0; i < sizeof(int); i++) {			int_map[i] = i;		}		machine_endian_short_map[0] = 0;		machine_endian_short_map[1] = 1;		big_endian_short_map[0] = 1;		big_endian_short_map[1] = 0;		little_endian_short_map[0] = 0;		little_endian_short_map[1] = 1;		machine_endian_long_map[0] = 0;		machine_endian_long_map[1] = 1;		machine_endian_long_map[2] = 2;		machine_endian_long_map[3] = 3;		big_endian_long_map[0] = 3;		big_endian_long_map[1] = 2;		big_endian_long_map[2] = 1;		big_endian_long_map[3] = 0;		little_endian_long_map[0] = 0;		little_endian_long_map[1] = 1;		little_endian_long_map[2] = 2;		little_endian_long_map[3] = 3;	}	else {		zval val;		int size = sizeof(Z_LVAL(val));		Z_LVAL(val)=0; /*silence a warning*/		/* Where to get hi to lo bytes from */		byte_map[0] = size - 1;		for (i = 0; i < sizeof(int); i++) {			int_map[i] = size - (sizeof(int) - i);		}		machine_endian_short_map[0] = size - 2;		machine_endian_short_map[1] = size - 1;		big_endian_short_map[0] = size - 2;		big_endian_short_map[1] = size - 1;		little_endian_short_map[0] = size - 1;		little_endian_short_map[1] = size - 2;		machine_endian_long_map[0] = size - 4;		machine_endian_long_map[1] = size - 3;		machine_endian_long_map[2] = size - 2;		machine_endian_long_map[3] = size - 1;		big_endian_long_map[0] = size - 4;		big_endian_long_map[1] = size - 3;		big_endian_long_map[2] = size - 2;		big_endian_long_map[3] = size - 1;		little_endian_long_map[0] = size - 1;		little_endian_long_map[1] = size - 2;		little_endian_long_map[2] = size - 3;		little_endian_long_map[3] = size - 4;	}	return SUCCESS;}/* }}} *//* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */

⌨️ 快捷键说明

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