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

📄 mprprintf.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/** *	@file 	mprPrintf.c *	@brief	Printf routines safe for embedded programming *	@overview This module provides safe replacements for the standard  *		printf formatting routines. *	@remarks Most routines in this file are not thread-safe. It is the callers  *		responsibility to perform all thread synchronization. *//* *	@copy	default *	 *	Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. *	 *	This software is distributed under commercial and open source licenses. *	You may use the GPL open source license described below or you may acquire  *	a commercial license from Mbedthis Software. You agree to be fully bound  *	by the terms of either license. Consult the LICENSE.TXT distributed with  *	this software for full details. *	 *	This software is open source; you can redistribute it and/or modify it  *	under the terms of the GNU General Public License as published by the  *	Free Software Foundation; either version 2 of the License, or (at your  *	option) any later version. See the GNU General Public License for more  *	details at: http://www.mbedthis.com/downloads/gplLicense.html *	 *	This program is distributed WITHOUT ANY WARRANTY; without even the  *	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  *	 *	This GPL license does NOT permit incorporating this software into  *	proprietary programs. If you are unable to comply with the GPL, you must *	acquire a commercial license to use this software. Commercial licenses  *	for this software and support services are available from Mbedthis  *	Software at http://www.mbedthis.com  *	 *	@end *//********************************** Includes **********************************//* *	We need to use the underlying str(cpy) routines to implement our safe *	alternatives */#if !DOXYGEN#define 	UNSAFE_FUNCTIONS_OK 1#endif#include	"mpr.h"/*********************************** Defines **********************************//* *	Class definitions */#define CLASS_NORMAL	0		/* [All other]		Normal characters */#define CLASS_PERCENT	1		/* [%]				Begin format */#define CLASS_MODIFIER	2		/* [-+ #,]			Modifiers */#define CLASS_ZERO		3		/* [0]				Special modifier */#define CLASS_STAR		4		/* [*]				Width supplied by arg */#define CLASS_DIGIT		5		/* [1-9]			Field widths */#define CLASS_DOT		6		/* [.]				Introduce precision */#define CLASS_BITS		7		/* [hlL]			Length bits */#define CLASS_TYPE		8		/* [cdfinopsSuxX]	Type specifiers */#define STATE_NORMAL	0				/* Normal chars in format string */#define STATE_PERCENT	1				/* "%" */#define STATE_MODIFIER	2				/* Read flag */#define STATE_WIDTH		3				/* Width spec */#define STATE_DOT		4				/* "." */#define STATE_PRECISION	5				/* Precision spec */#define STATE_BITS		6				/* Size spec */#define STATE_TYPE		7				/* Data type */#define STATE_COUNT		8/* *	Format:			%[modifier][width][precision][bits][type] * *	#define CLASS_MODIFIER	2		[-+ #,]			Modifiers *	#define CLASS_BITS		7		[hlL]			Length bits *//* *	Flags */#define SPRINTF_LEFT		0x1			/* Left align */#define SPRINTF_SIGN		0x2			/* Always sign the result */#define SPRINTF_LEAD_SPACE	0x4			/* put leading space for +ve numbers */#define SPRINTF_ALTERNATE	0x8			/* Alternate format */#define SPRINTF_LEAD_ZERO	0x10		/* Zero pad */#define SPRINTF_SHORT		0x20		/* 16-bit */#define SPRINTF_LONG		0x40		/* 32-bit */#if BLD_FEATURE_INT64#define SPRINTF_LONGLONG	0x80		/* 64-bit */#endif#define SPRINTF_COMMA		0x100		/* Thousand comma separators */#define SPRINTF_UPPER_CASE	0x200		/* As the name says for numbers */typedef struct Format {	uchar	*buf;	uchar	*endbuf;	uchar	*start;	uchar	*end;	int		growBy;	int		maxsize;	int		precision;	int		radix;	int		width;	int		flags;	int		len;} Format;static int growBuf(MPR_LOC_DEC(ctx, loc), Format *fmt);#define BPUT(ctx, loc, fmt, c) \	if (1) { \		/* Less one to allow room for the null */ \		if ((fmt)->end >= ((fmt)->endbuf - sizeof(char))) { \			if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \				*(fmt)->end++ = (c); \			} \		} else { \			*(fmt)->end++ = (c); \		} \	} else#define BPUTNULL(ctx, loc, fmt) \	if (1) { \		if ((fmt)->end > (fmt)->endbuf) { \			if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \				*(fmt)->end = '\0'; \			} \		} else { \			*(fmt)->end = '\0'; \		} \	} else /******************************************************************************/#if BLD_FEATURE_INT64#define unum 	uint64#define num 	int64#else#define unum 	uint#define num		int#endif/***************************** Forward Declarations ***************************/#ifdef __cplusplusextern "C" {#endifstatic int	getState(char c, int state);static int	mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **s, 	int maxsize, const char *fmt, va_list arg);static void	outNum(MPR_LOC_DEC(ctx, loc), Format *fmt, const char *prefix, 	unum val);#if BLD_FEATURE_FLOATING_POINTstatic void outFloat(MPR_LOC_DEC(ctx, loc), Format *fmt, char specChar, 	double value);#endif/******************************************************************************/int mprPrintf(MprCtx ctx, const char *fmt, ...){	va_list		ap;	char		*buf;	int			len;	MprApp		*app;	/* No asserts here as this is used as part of assert reporting */	app = mprGetApp(ctx);	va_start(ap, fmt);	len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap);	va_end(ap);	if (len >= 0 && app->console) {		len = mprWrite(app->console, buf, len);	}	mprFree(buf);	return len;}/******************************************************************************/int mprErrorPrintf(MprCtx ctx, const char *fmt, ...){	va_list		ap;	char		*buf;	int			len;	MprApp		*app;	/* No asserts here as this is used as part of assert reporting */	app = mprGetApp(ctx);	va_start(ap, fmt);	len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap);	va_end(ap);	if (len >= 0 && app->error) {		len = mprWrite(app->error, buf, len);	}	mprFree(buf);	return len;}/******************************************************************************/int mprFprintf(MprFile *file, const char *fmt, ...){	va_list		ap;	char		*buf;	int			len;	if (file == 0) {		return MPR_ERR_BAD_HANDLE;	}	va_start(ap, fmt);	len = mprAllocVsprintf(MPR_LOC_ARGS(file), &buf, 0, fmt, ap);	va_end(ap);	if (len >= 0) {		len = mprWrite(file, buf, len);	}	mprFree(buf);	return len;}/******************************************************************************//* *	Printf with a static buffer. Used internally only. WILL NOT MALLOC. */int mprStaticPrintf(MprCtx ctx, const char *fmt, ...){	va_list		ap;	char		buf[MPR_MAX_STRING];	char		*bufp;	int			len;	MprApp		*app;	app = mprGetApp(ctx);	va_start(ap, fmt);	bufp = buf;	len = mprSprintfCore(MPR_LOC_ARGS(0), &bufp, MPR_MAX_STRING, fmt, ap);	va_end(ap);	if (len >= 0) {		len = mprWrite(app->console, buf, len);	}	return len;}/******************************************************************************/int mprSprintf(char *buf, int n, const char *fmt, ...){	va_list		ap;	int			result;	mprAssert(buf);	mprAssert(fmt);	mprAssert(n > 0);	va_start(ap, fmt);	result = mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, ap);	va_end(ap);	return result;}/******************************************************************************/int mprVsprintf(char *buf, int n, const char *fmt, va_list arg){	mprAssert(buf);	mprAssert(fmt);	mprAssert(n > 0);	return mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, arg);}/******************************************************************************/int mprAllocSprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, 	const char *fmt, ...){	va_list	ap;	int		result;	mprAssert(buf);	mprAssert(fmt);	*buf = 0;	va_start(ap, fmt);	result = mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, ap);	va_end(ap);	return result;}/******************************************************************************/int mprAllocVsprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, 	const char *fmt, va_list arg){	mprAssert(buf);	mprAssert(fmt);	*buf = 0;	return mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, arg);}/******************************************************************************/static int getState(char c, int state){	/*	 *	Declared here to remove all static / globals	 *	FUTURE OPT -- need to measure this. Could be slow on BREW.	 */	char stateMap[] = {	/*     STATES:  Normal Percent Modifier Width  Dot  Prec Bits Type */	/* CLASS           0      1       2       3     4     5    6    7  */	/* Normal   0 */   0,     0,      0,      0,    0,    0,   0,   0,	/* Percent  1 */   1,     0,      1,      1,    1,    1,   1,   1,	/* Modifier 2 */   0,     2,      2,      0,    0,    0,   0,   0,	/* Zero     3 */   0,     2,      2,      3,    0,    5,   0,   0,	/* Star     4 */   0,     3,      3,      0,    5,    0,   0,   0,	/* Digit    5 */   0,     3,      3,      3,    5,    5,   0,   0,	/* Dot      6 */   0,     4,      4,      4,    0,    0,   0,   0,	/* Bits     7 */   0,     6,      6,      6,    6,    6,   6,   0,	/* Types    8 */   0,     7,      7,      7,    7,    7,   7,   0,	};	/*	 *	Format:			%[modifier][width][precision][bits][type]	 */	char classMap[] = {		/*   0  ' '    !     "     #     $     %     &     ' */				 2,    0,    0,    2,    0,    1,    0,    0,		/*  07   (     )     *     +     ,     -     .     / */				 0,    0,    4,    2,    2,    2,    6,    0,		/*  10   0     1     2     3     4     5     6     7 */				 3,    5,    5,    5,    5,    5,    5,    5,		/*  17   8     9     :     ;     <     =     >     ? */				 5,    5,    0,    0,    0,    0,    0,    0,		/*  20   @     A     B     C     D     E     F     G */				 0,    0,    0,    0,    0,    0,    0,    0,		/*  27   H     I     J     K     L     M     N     O */				 0,    0,    0,    0,    7,    0,    0,    0,		/*  30   P     Q     R     S     T     U     V     W */				 0,    0,    0,    8,    0,    0,    0,    0,		/*  37   X     Y     Z     [     \     ]     ^     _ */				 8,    0,    0,    0,    0,    0,    0,    0,		/*  40   '     a     b     c     d     e     f     g */				 0,    0,    0,    8,    8,    0,    8,    0,		/*  47   h     i     j     k     l     m     n     o */				 7,    8,    0,    0,    7,    0,    8,    8,		/*  50   p     q     r     s     t     u     v     w */				 8,    0,    0,    8,    0,    8,    0,    0,		/*  57   x     y     z  */				 8,    0,    0,	};	int		chrClass;	if (c < ' ' || c > 'z') {		chrClass = CLASS_NORMAL;	} else {		mprAssert((c - ' ') < (int) sizeof(classMap));		chrClass = classMap[(c - ' ')];	}	mprAssert((chrClass * STATE_COUNT + state) < (int) sizeof(stateMap));	state = stateMap[chrClass * STATE_COUNT + state];	return state;}/******************************************************************************/static int mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **bufPtr, 	int maxsize, const char *spec, va_list arg){	Format		fmt;	char		*cp;	char		c;	char		*sValue;	num			iValue;	unum		uValue;	int			count, i, len, state;	mprAssert(bufPtr);	mprAssert(spec);	if (*bufPtr != 0) {		mprAssert(maxsize > 0);		fmt.buf = (uchar*) *bufPtr;		fmt.endbuf = &fmt.buf[maxsize];		fmt.growBy = 0;	} else {		if (maxsize <= 0) {			maxsize = MAXINT;		}		len = min(MPR_DEFAULT_ALLOC, maxsize);		fmt.buf = (uchar*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);		fmt.endbuf = &fmt.buf[len];		fmt.growBy = MPR_DEFAULT_ALLOC * 2;	}	fmt.maxsize = maxsize;	fmt.start = fmt.buf;	fmt.end = fmt.buf;	fmt.len = 0;	*fmt.start = '\0';	state = STATE_NORMAL;	while ((c = *spec++) != '\0') {		state = getState(c, state);		switch (state) {		case STATE_NORMAL:			BPUT(ctx, loc, &fmt, c);			break;		case STATE_PERCENT:			fmt.precision = -1;			fmt.width = 0;			fmt.flags = 0;			break;		case STATE_MODIFIER:			switch (c) {			case '+':				fmt.flags |= SPRINTF_SIGN;				break;			case '-':				fmt.flags |= SPRINTF_LEFT;				break;			case '#':				fmt.flags |= SPRINTF_ALTERNATE;				break;			case '0':				fmt.flags |= SPRINTF_LEAD_ZERO;				break;			case ' ':				fmt.flags |= SPRINTF_LEAD_SPACE;				break;			case ',':				fmt.flags |= SPRINTF_COMMA;				break;			}			break;		case STATE_WIDTH:			if (c == '*') {				fmt.width = va_arg(arg, int);

⌨️ 快捷键说明

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