📄 wsprintf.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "_common.h"
#pragma hdrstop
#ifdef UNDER_CE
/****************************** Module Header ******************************\
* Module Name: wsprintf.c
*
* sprintf.c
*
* Implements Windows friendly versions of sprintf and vsprintf
*
* History:
* 2-15-89 craigc Initial
* 11-12-90 MikeHar Ported from windows 3
\***************************************************************************/
#define WSPRINTF_LIMIT 1024
#define out(c) if (--cchLimit) *lpOut++=(c); else goto errorout
int xwvsprintf(LPSTR lpOut, LPCSTR lpFmt, va_list arglist);
/***************************************************************************\
* SP_PutNumber
*
* Takes an unsigned long integer and places it into a buffer, respecting
* a buffer limit, a radix, and a case select (upper or lower, for hex).
*
*
* History:
* 11-12-90 MikeHar Ported from windows 3 asm --> C
* 12-11-90 GregoryW need to increment lpstr after assignment of mod
\***************************************************************************/
int SP_PutNumber(
LPSTR lpstr,
DWORD n,
int limit,
DWORD radix,
int uppercase)
{
DWORD mod;
int count = 0;
if(uppercase)
uppercase = 'A'-'0'-10;
else
uppercase = 'a'-'0'-10;
if (count <= limit) {
do {
mod = n % radix;
n /= radix;
mod += '0';
if (mod > '9')
mod += uppercase;
*lpstr++ = (char)mod;
count++;
} while((count <= limit) && n);
}
return count;
}
/***************************************************************************\
* SP_Reverse
*
* reverses a string in place
*
* History:
* 11-12-90 MikeHar Ported from windows 3 asm --> C
* 12-11-90 GregoryW fixed boundary conditions; removed count
\***************************************************************************/
void SP_Reverse(
LPSTR lpFirst,
LPSTR lpLast)
{
char ch;
while(lpLast > lpFirst){
ch = *lpFirst;
*lpFirst++ = *lpLast;
*lpLast-- = ch;
}
}
/***************************************************************************\
* SP_GetFmtValue
*
* reads a width or precision value from the format string
*
* History:
* 11-12-90 MikeHar Ported from windows 3
\***************************************************************************/
LPCSTR SP_GetFmtValue(
LPCSTR lpch,
int *lpw)
{
int ii = 0;
while (*lpch >= '0' && *lpch <= '9') {
ii *= 10;
ii += (int)(*lpch - '0');
lpch++;
}
*lpw = ii;
/*
* return the address of the first non-digit character
*/
return lpch;
}
/***************************************************************************\
* SP_GetFmtValueW
*
* reads a width or precision value from the format string
*
* History:
* 11-12-90 MikeHar Ported from windows 3
* 07-27-92 GregoryW Created Unicode version (copied from SP_GetFmtValue)
\***************************************************************************/
LPCWSTR SP_GetFmtValueW(
LPCWSTR lpch,
int *lpw)
{
int ii = 0;
while (*lpch >= L'0' && *lpch <= L'9') {
ii *= 10;
ii += (int)(*lpch - L'0');
lpch++;
}
*lpw = ii;
/*
* return the address of the first non-digit character
*/
return lpch;
}
/***************************************************************************\
* wvsprintf (API)
*
* Windows version of vsprintf(). Does not support floating point or
* pointer types, and all strings are assumed to be FAR. Supports only
* the left alignment flag.
*
* Takes pointers to an output buffer, where the string is built, a
* pointer to an input buffer, and a pointer to a list of parameters.
*
* The cdecl function wsprintf() calls this function.
*
* History:
* 11-12-90 MikeHar Ported from windows 3
* 12-11-90 GregoryW after %d format is parsed lpParms needs to be aligned
* to a dword boundary.
* 09-Aug-1991 mikeke no it doesn't
* 11-19-91 DarrinM Now wvsprintf and wsprintf treat parameters the same
* (as if they originated from a DWORD-aligned stack).
\***************************************************************************/
int wvsprintfA(
LPSTR lpOut,
LPCSTR lpFmt,
va_list arglist)
{
return xwvsprintf(lpOut, lpFmt, arglist);
}
/***************************************************************************\
* xwvsprintf (API)
*
* wsprintf() calls this function.
*
* History:
* 09-Aug-1991 mikeke copied wsvprintf
\***************************************************************************/
int xwvsprintf(
LPSTR lpOut,
LPCSTR lpFmt,
va_list arglist)
{
char prefix, fillch;
int left, width, prec, size, sign, radix, upper, hprefix;
int cchLimit = WSPRINTF_LIMIT, cch;
LPSTR lpT;
LPWSTR pwsz;
va_list varglist = arglist;
union {
long l;
unsigned long ul;
char sz[sizeof(long)];
WCHAR wsz[sizeof(long)/sizeof(WCHAR)];
} val;
while (*lpFmt != 0) {
if (*lpFmt == '%') {
/*
* read the flags. These can be in any order
*/
left = 0;
prefix = 0;
while (*++lpFmt) {
if (*lpFmt == '-')
left++;
else if (*lpFmt == '#')
prefix++;
else
break;
}
/*
* find fill character
*/
if (*lpFmt == '0') {
fillch = '0';
lpFmt++;
} else
fillch = ' ';
/*
* read the width specification
*/
lpFmt = SP_GetFmtValue((LPCSTR)lpFmt, &cch);
width = cch;
/*
* read the precision
*/
if (*lpFmt == '.') {
lpFmt = SP_GetFmtValue((LPCSTR)++lpFmt, &cch);
prec = cch;
} else
prec = -1;
/*
* get the operand size
* default size: size == 0
* long number: size == 1
* wide chars: size == 2
* It may be a good idea to check the value of size when it
* is tested for non-zero below (IanJa)
*/
hprefix = 0;
if (*lpFmt == 'w') {
size = 2;
lpFmt++;
} else if (*lpFmt == 'l') {
size = 1;
lpFmt++;
} else if (*lpFmt == 't') {
size = 0;
lpFmt++;
} else {
size = 0;
if (*lpFmt == 'h') {
lpFmt++;
hprefix = 1;
}
}
upper = 0;
sign = 0;
radix = 10;
switch (*lpFmt) {
case 0:
goto errorout;
case 'i':
case 'd':
size=1;
sign++;
/*** FALL THROUGH to case 'u' ***/
case 'u':
/* turn off prefix if decimal */
prefix = 0;
donumeric:
/* special cases to act like MSC v5.10 */
if (left || prec >= 0)
fillch = ' ';
/*
* if size == 1, "%lu" was specified (good);
* if size == 2, "%wu" was specified (bad)
*/
if (size) {
val.l = va_arg(varglist, long);
} else if (sign) {
val.l = (long)va_arg(varglist, short);
} else {
val.ul = va_arg(varglist, unsigned);
}
if (sign && val.l < 0L)
val.l = -val.l;
else
sign = 0;
lpT = lpOut;
/*
* blast the number backwards into the user buffer
*/
cch = SP_PutNumber(lpOut, val.l, cchLimit, radix, upper);
if (!(cchLimit -= cch))
goto errorout;
lpOut += cch;
width -= cch;
prec -= cch;
if (prec > 0)
width -= prec;
/*
* fill to the field precision
*/
while (prec-- > 0)
out('0');
if (width > 0 && !left) {
/*
* if we're filling with spaces, put sign first
*/
if (fillch != '0') {
if (sign) {
sign = 0;
out('-');
width--;
}
if (prefix) {
out(prefix);
out('0');
prefix = 0;
}
}
if (sign)
width--;
/*
* fill to the field width
*/
while (width-- > 0)
out(fillch);
/*
* still have a sign?
*/
if (sign)
out('-');
if (prefix) {
out(prefix);
out('0');
}
/*
* now reverse the string in place
*/
SP_Reverse(lpT, lpOut - 1);
} else {
/*
* add the sign character
*/
if (sign) {
out('-');
width--;
}
if (prefix) {
out(prefix);
out('0');
}
/*
* reverse the string in place
*/
SP_Reverse(lpT, lpOut - 1);
/*
* pad to the right of the string in case left aligned
*/
while (width-- > 0)
out(fillch);
}
break;
case 'X':
upper++;
/*** FALL THROUGH to case 'x' ***/
case 'x':
radix = 16;
if (prefix)
if (upper)
prefix = 'X';
else
prefix = 'x';
goto donumeric;
case 'C':
/*
* explicit size specifier overrides case
*/
if (!size && !hprefix) {
size = 1; // force WCHAR
}
/*** FALL THROUGH to case 'c' ***/
case 'c':
/*
* if size == 0, "%c" or "%hc" or "%tc" was specified (CHAR)
* if size == 1, "%C" or "%lc" was specified (WCHAR);
* if size == 2, "%wc" was specified (WCHAR)
*/
if (size) {
val.wsz[0] = va_arg(varglist, WCHAR);
val.wsz[1] = 0x0000;
pwsz = val.wsz;
goto putwstring;
} else {
val.sz[0] = va_arg(varglist, CHAR);
val.sz[1] = 0;
lpT = val.sz;
cch = 1; // Length is one character.
goto putstring;
}
case 'S':
/*
* explicit size specifier overrides case
*/
if (!size && !hprefix) {
size = 1; // force LPWSTR
}
/*** FALL THROUGH to case 's' ***/
case 's':
/*
* if size == 0, "%s" or "%hs" or "%ts" was specified (LPSTR);
* if size == 1, "%S" or "%ls" was specified (LPWSTR);
* if size == 2, "%ws" was specified (LPWSTR)
*/
if (size) {
pwsz = va_arg(varglist, LPWSTR);
putwstring:
cch = wcslen(pwsz);
if (prec >= 0 && cch > prec)
cch = prec;
width -= cch;
if (left) {
while (cch--)
out((CHAR)*pwsz++);
while (width-- > 0)
out(fillch);
} else {
while (width-- > 0)
out(fillch);
while (cch--)
out((CHAR)*pwsz++);
}
} else {
lpT = va_arg(varglist, LPSTR);
cch = strlen(lpT);
putstring:
if (prec >= 0 && cch > prec)
cch = prec;
width -= cch;
if (left) {
while (cch--)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -