- more VarFormat fixes for number formats (exponent, mixed '#' and '0'

in formats, rounding, etc). Simplify the code.
- previous VarFormat todo_wine tests pass now + add more tests
This commit is contained in:
Michael Stefaniuc 2005-06-23 09:48:07 +00:00 committed by Alexandre Julliard
parent 138934129c
commit 0b1f8cdf4d
2 changed files with 138 additions and 138 deletions

View File

@ -1716,9 +1716,16 @@ static void test_VarFormat(void)
VARFMT(VT_I4,V_I4,1,"000###",S_OK,"000001"); VARFMT(VT_I4,V_I4,1,"000###",S_OK,"000001");
VARFMT(VT_I4,V_I4,1,"#00##00#0",S_OK,"00000001"); VARFMT(VT_I4,V_I4,1,"#00##00#0",S_OK,"00000001");
VARFMT(VT_I4,V_I4,1,"1#####0000",S_OK,"10001"); VARFMT(VT_I4,V_I4,1,"1#####0000",S_OK,"10001");
VARFMT(VT_R8,V_R8,1.23456789,"0#.0#0#0#0#0",S_OK,"01.234567890");
VARFMT(VT_R8,V_R8,1.2,"0#.0#0#0#0#0",S_OK,"01.200000000");
VARFMT(VT_R8,V_R8,9.87654321,"#0.#0#0#0#0#",S_OK,"9.87654321");
VARFMT(VT_R8,V_R8,9.8,"#0.#0#0#0#0#",S_OK,"9.80000000");
VARFMT(VT_R8,V_R8,0.00000008,"#0.#0#0#0#0#0",S_OK,"0.0000000800");
VARFMT(VT_R8,V_R8,0.00010705,"#0.##########",S_OK,"0.00010705");
VARFMT(VT_I4,V_I4,17,"#0",S_OK,"17"); VARFMT(VT_I4,V_I4,17,"#0",S_OK,"17");
VARFMT(VT_I4,V_I4,4711,"#0",S_OK,"4711"); VARFMT(VT_I4,V_I4,4711,"#0",S_OK,"4711");
VARFMT(VT_I4,V_I4,17,"#00",S_OK,"17"); VARFMT(VT_I4,V_I4,17,"#00",S_OK,"17");
VARFMT(VT_I4,V_I4,100,"0##",S_OK,"100");
VARFMT(VT_I4,V_I4,17,"#000",S_OK,"017"); VARFMT(VT_I4,V_I4,17,"#000",S_OK,"017");
VARFMT(VT_I4,V_I4,17,"#0.00",S_OK,"17.00"); VARFMT(VT_I4,V_I4,17,"#0.00",S_OK,"17.00");
VARFMT(VT_I4,V_I4,17,"#0000.00",S_OK,"0017.00"); VARFMT(VT_I4,V_I4,17,"#0000.00",S_OK,"0017.00");
@ -1734,20 +1741,22 @@ static void test_VarFormat(void)
VARFMT(VT_R8,V_R8,1.7,"0.0000E-000",S_OK,"1.7000E000"); VARFMT(VT_R8,V_R8,1.7,"0.0000E-000",S_OK,"1.7000E000");
VARFMT(VT_R8,V_R8,1.7,"0.0000e-1",S_OK,"1.7000e01"); VARFMT(VT_R8,V_R8,1.7,"0.0000e-1",S_OK,"1.7000e01");
VARFMT(VT_R8,V_R8,86.936849,"#0.000000000000e-000",S_OK,"86.936849000000e000"); VARFMT(VT_R8,V_R8,86.936849,"#0.000000000000e-000",S_OK,"86.936849000000e000");
todo_wine { VARFMT(VT_R8,V_R8,1.7,"#0",S_OK,"2");
/* rounding */ VARFMT(VT_R8,V_R8,1.7,"#.33",S_OK,"2.33");
VARFMT(VT_R8,V_R8,1.7,"#0",S_OK,"2"); VARFMT(VT_R8,V_R8,1.7,"#3",S_OK,"23");
VARFMT(VT_R8,V_R8,1.7,"#.33",S_OK,"2.33"); VARFMT(VT_R8,V_R8,1.73245,"0.0000E+000",S_OK,"1.7325E+000");
VARFMT(VT_R8,V_R8,1.7,"#3",S_OK,"23"); VARFMT(VT_R8,V_R8,9.9999999,"#0.000000",S_OK,"10.000000");
VARFMT(VT_R8,V_R8,1.73245,"0.0000E+000",S_OK,"1.7325E+000"); VARFMT(VT_R8,V_R8,1.7,"0.0000e+0#",S_OK,"1.7000e+0");
VARFMT(VT_R8,V_R8,9.9999999,"#0.000000",S_OK,"10.000000"); VARFMT(VT_R8,V_R8,100.0001e+0,"0.0000E+0",S_OK,"1.0000E+2");
/* handling of numbers > 0 with exponent format */ VARFMT(VT_R8,V_R8,1000001,"0.0000e+1",S_OK,"1.0000e+61");
VARFMT(VT_R8,V_R8,1.7,"0.0000e+0#",S_OK,"1.7000e+0"); VARFMT(VT_R8,V_R8,100.0001e+25,"0.0000e+0",S_OK,"1.0000e+27");
VARFMT(VT_R8,V_R8,100.0001e+0,"0.0000E+0",S_OK,"1.0000E+2"); VARFMT(VT_R8,V_R8,450.0001e+43,"#000.0000e+0",S_OK,"4500.0010e+42");
VARFMT(VT_R8,V_R8,1000001,"0.0000e+1",S_OK,"1.0000e+61"); VARFMT(VT_R8,V_R8,0.0001e-11,"##00.0000e-0",S_OK,"1000.0000e-18");
VARFMT(VT_R8,V_R8,100.0001e+25,"0.0000e+0",S_OK,"1.0000e+27"); VARFMT(VT_R8,V_R8,0.0317e-11,"0000.0000e-0",S_OK,"3170.0000e-16");
VARFMT(VT_R8,V_R8,450.0001e+43,"#000.0000e+0",S_OK,"4500.0010e+42"); VARFMT(VT_R8,V_R8,0.0021e-11,"00##.0000e-0",S_OK,"2100.0000e-17");
} VARFMT(VT_R8,V_R8,1.0001e-27,"##00.0000e-0",S_OK,"1000.1000e-30");
VARFMT(VT_R8,V_R8,47.11,".0000E+0",S_OK,".4711E+2");
VARFMT(VT_R8,V_R8,3.0401e-13,"#####.####e-0%",S_OK,"30401.e-15%");
/* 'out' is not cleared */ /* 'out' is not cleared */

View File

@ -1192,7 +1192,7 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
{ {
BYTE rgbDig[256], *prgbDig; BYTE rgbDig[256], *prgbDig;
NUMPARSE np; NUMPARSE np;
int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0; int have_int, need_int = 0, have_frac, need_frac, exponent = 0, pad = 0;
WCHAR buff[256], *pBuff = buff; WCHAR buff[256], *pBuff = buff;
VARIANT vString, vBool; VARIANT vString, vBool;
DWORD dwState = 0; DWORD dwState = 0;
@ -1210,7 +1210,7 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
if (V_TYPE(pVarIn) == VT_EMPTY || V_TYPE(pVarIn) == VT_NULL) if (V_TYPE(pVarIn) == VT_EMPTY || V_TYPE(pVarIn) == VT_NULL)
{ {
wholeNumberDigits = fractionalDigits = 0; have_int = have_frac = 0;
numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNull(header)); numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNull(header));
V_BOOL(&vBool) = VARIANT_FALSE; V_BOOL(&vBool) = VARIANT_FALSE;
} }
@ -1227,36 +1227,9 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
if (FAILED(hRes)) if (FAILED(hRes))
return hRes; return hRes;
if (np.nPwr10 < 0) have_int = np.cDig;
{ have_frac = 0;
if (-np.nPwr10 >= np.cDig) exponent = np.nPwr10;
{
/* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
wholeNumberDigits = 0;
fractionalDigits = np.cDig;
divisor10 = -np.nPwr10;
}
else
{
/* An exactly represented real number e.g. 1.024 */
wholeNumberDigits = np.cDig + np.nPwr10;
fractionalDigits = np.cDig - wholeNumberDigits;
divisor10 = 0;
}
}
else if (np.nPwr10 == 0)
{
/* An exactly represented whole number e.g. 1024 */
wholeNumberDigits = np.cDig;
fractionalDigits = 0;
}
else /* np.nPwr10 > 0 */
{
/* A whole number followed by nPwr10 0's e.g. 102400 */
wholeNumberDigits = np.cDig;
fractionalDigits = 0;
multiplier10 = np.nPwr10;
}
/* Figure out which format to use */ /* Figure out which format to use */
if (np.dwOutFlags & NUMPRS_NEG) if (np.dwOutFlags & NUMPRS_NEG)
@ -1264,8 +1237,7 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNegative(header)); numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNegative(header));
V_BOOL(&vBool) = VARIANT_TRUE; V_BOOL(&vBool) = VARIANT_TRUE;
} }
else if (wholeNumberDigits == 1 && !fractionalDigits && !multiplier10 && else if (have_int == 1 && !exponent && rgbDig[0] == 0)
!divisor10 && rgbDig[0] == 0)
{ {
numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetZero(header)); numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetZero(header));
V_BOOL(&vBool) = VARIANT_FALSE; V_BOOL(&vBool) = VARIANT_FALSE;
@ -1280,32 +1252,70 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
numHeader->flags, numHeader->multiplier, numHeader->divisor, numHeader->flags, numHeader->multiplier, numHeader->divisor,
numHeader->whole, numHeader->fractional); numHeader->whole, numHeader->fractional);
need_int = numHeader->whole;
need_frac = numHeader->fractional;
if (numHeader->flags & FMT_FLAG_PERCENT && if (numHeader->flags & FMT_FLAG_PERCENT &&
!(wholeNumberDigits == 1 && !fractionalDigits && !multiplier10 && !(have_int == 1 && !exponent && rgbDig[0] == 0))
!divisor10 && rgbDig[0] == 0)) exponent += 2;
if (numHeader->flags & FMT_FLAG_EXPONENT)
{ {
/* *100 for %'s. Try to 'steal' fractional digits if we can */ /* Exponent format: length of the integral number part is fixed and
TRACE("Fraction - multiply by 100\n"); specified by the format. */
if (!fractionalDigits) pad = need_int - have_int;
multiplier10 += 2; if (pad >= 0)
exponent -= pad;
else else
{ {
fractionalDigits--; have_int = need_int;
wholeNumberDigits++; have_frac -= pad;
if (!fractionalDigits) exponent -= pad;
multiplier10++; pad = 0;
else }
{ }
fractionalDigits--; else
wholeNumberDigits++; {
} /* Convert the exponent */
pad = max(exponent, -have_int);
exponent -= pad;
if (pad < 0)
{
have_int += pad;
have_frac = -pad;
pad = 0;
} }
} }
TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", np.cDig,
np.nPwr10, wholeNumberDigits, fractionalDigits);
TRACE("mult %d; div %d\n", multiplier10, divisor10);
/* Rounding the number */
if (have_frac > need_frac)
{
prgbDig = &rgbDig[have_int + need_frac];
have_frac = need_frac;
if (*prgbDig >= 5)
{
while (prgbDig-- > rgbDig && *prgbDig == 9)
*prgbDig = 0;
if (prgbDig < rgbDig)
{
/* We reached the first digit and that was also a 9 */
rgbDig[0] = 1;
if (numHeader->flags & FMT_FLAG_EXPONENT)
exponent++;
else
{
rgbDig[have_int + need_frac] = 0;
have_int++;
}
}
else
(*prgbDig)++;
}
}
TRACE("have_int=%d,need_int=%d,have_frac=%d,need_frac=%d,pad=%d,exp=%d\n",
have_int, need_int, have_frac, need_frac, pad, exponent);
} }
pToken = (const BYTE*)numHeader + sizeof(FMT_NUMBER_HEADER); pToken = (const BYTE*)numHeader + sizeof(FMT_NUMBER_HEADER);
prgbDig = rgbDig; prgbDig = rgbDig;
@ -1390,107 +1400,88 @@ VARIANT_FormatNumber_Bool:
*pBuff++ = 'e'; *pBuff++ = 'e';
else else
*pBuff++ = 'E'; *pBuff++ = 'E';
if (divisor10) if (exponent < 0)
{ {
*pBuff++ = '-'; *pBuff++ = '-';
sprintfW(pBuff, szPercentZeroStar_d, pToken[1], divisor10); sprintfW(pBuff, szPercentZeroStar_d, pToken[1], -exponent);
} }
else else
{ {
if (*pToken == FMT_NUM_EXP_POS_L || *pToken == FMT_NUM_EXP_POS_U) if (*pToken == FMT_NUM_EXP_POS_L || *pToken == FMT_NUM_EXP_POS_U)
*pBuff++ = '+'; *pBuff++ = '+';
sprintfW(pBuff, szPercentZeroStar_d, pToken[1], multiplier10); sprintfW(pBuff, szPercentZeroStar_d, pToken[1], exponent);
} }
while (*pBuff) while (*pBuff)
pBuff++; pBuff++;
pToken++; pToken++;
break; break;
case FMT_NUM_COPY_ZERO:
dwState |= NUM_WRITE_ON;
/* Fall through */
case FMT_NUM_COPY_SKIP: case FMT_NUM_COPY_SKIP:
TRACE("write %d %sdigits or %s\n", pToken[1],
dwState & NUM_WROTE_DEC ? "fractional " : "",
*pToken == FMT_NUM_COPY_ZERO ? "0" : "skip");
if (dwState & NUM_WROTE_DEC) if (dwState & NUM_WROTE_DEC)
{ {
int count; int count, i;
TRACE("write %d fractional digits or skip\n", pToken[1]); if (!(numHeader->flags & FMT_FLAG_EXPONENT) && exponent < 0)
{
/* Pad with 0 before writing the fractional digits */
pad = max(exponent, -pToken[1]);
exponent -= pad;
count = min(have_frac, pToken[1] + pad);
for (i = 0; i > pad; i--)
*pBuff++ = '0';
}
else
count = min(have_frac, pToken[1]);
for (count = 0; count < fractionalDigits; count++, prgbDig++) pad += pToken[1] - count;
pBuff[count] = '0' + *prgbDig; have_frac -= count;
pBuff += fractionalDigits; while (count--)
*pBuff++ = '0' + *prgbDig++;
if (*pToken == FMT_NUM_COPY_ZERO)
{
for (; pad > 0; pad--)
*pBuff++ = '0'; /* Write zeros for missing trailing digits */
}
} }
else else
{ {
int count, count_max; int count, count_max;
TRACE("write %d digits or skip\n", pToken[1]); need_int -= pToken[1];
count_max = have_int + pad - need_int;
numHeader->whole -= pToken[1];
count_max = wholeNumberDigits - numHeader->whole;
if (count_max < 0) if (count_max < 0)
count_max = 0; count_max = 0;
if (dwState & NUM_WRITE_ON) { if (dwState & NUM_WRITE_ON)
for (count = 0; count < pToken[1] - count_max; count++)
*pBuff++ = '0'; /* Write zeros, don't skip */
}
if (wholeNumberDigits > 1 || *prgbDig > 0)
{ {
TRACE("write %d whole number digits\n", count_max); count = pToken[1] - count_max;
for (count = 0; count < count_max; count++, prgbDig++) {
*pBuff++ = '0' + *prgbDig;
wholeNumberDigits--;
dwState |= NUM_WRITE_ON;
}
TRACE("write %d whole trailing 0's\n", multiplier10);
for (count = 0; count < multiplier10; count++)
*pBuff++ = '0'; /* Write trailing zeros for multiplied values */
}
}
pToken++;
break;
case FMT_NUM_COPY_ZERO:
if (dwState & NUM_WROTE_DEC)
{
int count;
TRACE("write %d fractional digits or 0's\n", pToken[1]);
for (count = 0; count < fractionalDigits; count++, prgbDig++)
pBuff[count] = '0' + *prgbDig;
pBuff += fractionalDigits;
if (pToken[1] > fractionalDigits)
{
count = pToken[1] - fractionalDigits;
while (count--)
*pBuff++ = '0'; /* Write trailing zeros for missing digits */
}
}
else
{
int count, count_max;
TRACE("write %d digits or 0's\n", pToken[1]);
dwState |= NUM_WRITE_ON;
numHeader->whole -= pToken[1];
count_max = wholeNumberDigits + multiplier10 - numHeader->whole;
if (pToken[1] > (wholeNumberDigits + multiplier10))
{
if (count_max > 0)
count = pToken[1] - (wholeNumberDigits + multiplier10);
else
count = pToken[1];
TRACE("write %d leading zeros\n", count); TRACE("write %d leading zeros\n", count);
while(count--) while (count-- > 0)
*pBuff++ = '0'; /* Write leading zeros for missing digits */ *pBuff++ = '0';
} }
TRACE("write %d whole number digits\n", wholeNumberDigits); if (*pToken == FMT_NUM_COPY_ZERO || have_int > 1 || *prgbDig > 0)
for (count = 0; count < count_max - multiplier10; count++, prgbDig++) { {
*pBuff++ = '0' + *prgbDig; dwState |= NUM_WRITE_ON;
wholeNumberDigits--; count = min(count_max, have_int);
count_max -= count;
have_int -= count;
TRACE("write %d whole number digits\n", count);
while (count--)
*pBuff++ = '0' + *prgbDig++;
} }
TRACE("write %d whole trailing 0's\n", multiplier10); count = min(count_max, pad);
for (count = 0; count < multiplier10; count++) count_max -= count;
*pBuff++ = '0'; /* Write trailing zeros for multiplied values */ pad -= count;
TRACE("write %d whole trailing 0's\n", count);
while (count--)
*pBuff++ = '0';
} }
pToken++; pToken++;
break; break;