W
Wenming Hu
here is my code, as follows:
void TString::FormatV(const char *pszFormat, va_list argList)
{
va_list argListSave = argList;
// make a guess at the maximum length of the resulting string
size_t nMaxLen = 0;
for(const char *psz = pszFormat; *psz != '\0'; psz = _tcsinc(psz))
{
// handle '%' character, but watch out for '%%'
if (*psz != '%' || *(psz = _tcsinc(psz)) == '%')
{
nMaxLen += _tclen(psz);
continue;
}
size_t nItemLen = 0;
// handle '%' character with format
size_t nWidth = 0;
for(; *psz != '\0'; psz = _tcsinc(psz))
{
// check for valid flags
if(*psz == '#')
{
nMaxLen += 2; // for '0x'
}
else if(*psz == '*')
{
nWidth = va_arg(argList, int);
}
else if(*psz == '-' ||
*psz == '+' ||
*psz == '0' ||
*psz == ' ')
{
;
}
else // hit non-flag character
{
break;
}
}
// get width and skip it
if(nWidth == 0)
{
// width indicated by
nWidth = _ttoi(psz);
for (; *psz != '\0' && _istdigit(*psz); psz = _tcsinc(psz))
{
;
}
}
TASSERT(nWidth >= 0);
size_t nPrecision = 0;
if(*psz == '.')
{
// skip past '.' separator (width.precision)
psz = _tcsinc(psz);
// get precision and skip it
if (*psz == '*')
{
nPrecision = va_arg(argList, int);
psz = _tcsinc(psz);
}
else
{
nPrecision = _ttoi(psz);
for (; *psz != '\0' && _istdigit(*psz); psz = _tcsinc(psz))
{
;
}
}
TASSERT(nPrecision >= 0);
}
// should be on type modifier or specifier
switch (*psz)
{
// modifiers that affect size
case 'h':
case 'l':
case 'F':
case 'N':
case 'L':
psz = _tcsinc(psz);
break;
}
// now should be on specifier
switch(*psz)
{
// single characters
case 'c':
case 'C':
nItemLen = 2;
va_arg(argList, int);
break;
// strings
case 's':
case 'S':
const char *pstrNextArg = va_arg(argList, const char*);
if(pstrNextArg == NULL)
{
nItemLen = 6; // "(null)"
}
else
{
nItemLen = ::strlen(pstrNextArg);
nItemLen = max(1, nItemLen);
}
break;
}
// adjust nItemLen for strings
if(nItemLen != 0)
{
nItemLen = max(nItemLen, nWidth);
if (nPrecision != 0)
{
nItemLen = min(nItemLen, nPrecision);
}
}
else
{
switch(*psz)
{
// integers
case 'd':
case 'i':
case 'u':
case 'x':
case 'X':
case 'o':
va_arg(argList, int);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth + nPrecision);
break;
case 'e':
case 'f':
case 'g':
case 'G':
va_arg(argList, double);
nItemLen = 128;
nItemLen = max(nItemLen, nWidth + nPrecision);
break;
case 'p':
va_arg(argList, void*);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth + nPrecision);
break;
// no output
case 'n':
va_arg(argList, int*);
break;
default:
TASSERT(FALSE); // unknown formatting option
}
}
// adjust nMaxLen for output nItemLen
nMaxLen += nItemLen;
}
if(!AllocBeforeWrite(nMaxLen))
{
return;
}
::sprintf(m_pchData, pszFormat, argListSave);
}
it is difficult for me to write it, unfortunately, it does not work well.
is anyone willing to rewrite it?
my email: wenming_hu2002 at hotmail.com
void TString::FormatV(const char *pszFormat, va_list argList)
{
va_list argListSave = argList;
// make a guess at the maximum length of the resulting string
size_t nMaxLen = 0;
for(const char *psz = pszFormat; *psz != '\0'; psz = _tcsinc(psz))
{
// handle '%' character, but watch out for '%%'
if (*psz != '%' || *(psz = _tcsinc(psz)) == '%')
{
nMaxLen += _tclen(psz);
continue;
}
size_t nItemLen = 0;
// handle '%' character with format
size_t nWidth = 0;
for(; *psz != '\0'; psz = _tcsinc(psz))
{
// check for valid flags
if(*psz == '#')
{
nMaxLen += 2; // for '0x'
}
else if(*psz == '*')
{
nWidth = va_arg(argList, int);
}
else if(*psz == '-' ||
*psz == '+' ||
*psz == '0' ||
*psz == ' ')
{
;
}
else // hit non-flag character
{
break;
}
}
// get width and skip it
if(nWidth == 0)
{
// width indicated by
nWidth = _ttoi(psz);
for (; *psz != '\0' && _istdigit(*psz); psz = _tcsinc(psz))
{
;
}
}
TASSERT(nWidth >= 0);
size_t nPrecision = 0;
if(*psz == '.')
{
// skip past '.' separator (width.precision)
psz = _tcsinc(psz);
// get precision and skip it
if (*psz == '*')
{
nPrecision = va_arg(argList, int);
psz = _tcsinc(psz);
}
else
{
nPrecision = _ttoi(psz);
for (; *psz != '\0' && _istdigit(*psz); psz = _tcsinc(psz))
{
;
}
}
TASSERT(nPrecision >= 0);
}
// should be on type modifier or specifier
switch (*psz)
{
// modifiers that affect size
case 'h':
case 'l':
case 'F':
case 'N':
case 'L':
psz = _tcsinc(psz);
break;
}
// now should be on specifier
switch(*psz)
{
// single characters
case 'c':
case 'C':
nItemLen = 2;
va_arg(argList, int);
break;
// strings
case 's':
case 'S':
const char *pstrNextArg = va_arg(argList, const char*);
if(pstrNextArg == NULL)
{
nItemLen = 6; // "(null)"
}
else
{
nItemLen = ::strlen(pstrNextArg);
nItemLen = max(1, nItemLen);
}
break;
}
// adjust nItemLen for strings
if(nItemLen != 0)
{
nItemLen = max(nItemLen, nWidth);
if (nPrecision != 0)
{
nItemLen = min(nItemLen, nPrecision);
}
}
else
{
switch(*psz)
{
// integers
case 'd':
case 'i':
case 'u':
case 'x':
case 'X':
case 'o':
va_arg(argList, int);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth + nPrecision);
break;
case 'e':
case 'f':
case 'g':
case 'G':
va_arg(argList, double);
nItemLen = 128;
nItemLen = max(nItemLen, nWidth + nPrecision);
break;
case 'p':
va_arg(argList, void*);
nItemLen = 32;
nItemLen = max(nItemLen, nWidth + nPrecision);
break;
// no output
case 'n':
va_arg(argList, int*);
break;
default:
TASSERT(FALSE); // unknown formatting option
}
}
// adjust nMaxLen for output nItemLen
nMaxLen += nItemLen;
}
if(!AllocBeforeWrite(nMaxLen))
{
return;
}
::sprintf(m_pchData, pszFormat, argListSave);
}
it is difficult for me to write it, unfortunately, it does not work well.
is anyone willing to rewrite it?
my email: wenming_hu2002 at hotmail.com