- 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,"#00##00#0",S_OK,"00000001");
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,4711,"#0",S_OK,"4711");
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,"#0.00",S_OK,"17.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-1",S_OK,"1.7000e01");
VARFMT(VT_R8,V_R8,86.936849,"#0.000000000000e-000",S_OK,"86.936849000000e000");
todo_wine {
/* rounding */
VARFMT(VT_R8,V_R8,1.7,"#0",S_OK,"2");
VARFMT(VT_R8,V_R8,1.7,"#.33",S_OK,"2.33");
VARFMT(VT_R8,V_R8,1.7,"#3",S_OK,"23");
VARFMT(VT_R8,V_R8,1.73245,"0.0000E+000",S_OK,"1.7325E+000");
VARFMT(VT_R8,V_R8,9.9999999,"#0.000000",S_OK,"10.000000");
/* handling of numbers > 0 with exponent format */
VARFMT(VT_R8,V_R8,1.7,"0.0000e+0#",S_OK,"1.7000e+0");
VARFMT(VT_R8,V_R8,100.0001e+0,"0.0000E+0",S_OK,"1.0000E+2");
VARFMT(VT_R8,V_R8,1000001,"0.0000e+1",S_OK,"1.0000e+61");
VARFMT(VT_R8,V_R8,100.0001e+25,"0.0000e+0",S_OK,"1.0000e+27");
VARFMT(VT_R8,V_R8,450.0001e+43,"#000.0000e+0",S_OK,"4500.0010e+42");
}
VARFMT(VT_R8,V_R8,0.0001e-11,"##00.0000e-0",S_OK,"1000.0000e-18");
VARFMT(VT_R8,V_R8,0.0317e-11,"0000.0000e-0",S_OK,"3170.0000e-16");
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 */

View File

@ -1192,7 +1192,7 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
{
BYTE rgbDig[256], *prgbDig;
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;
VARIANT vString, vBool;
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)
{
wholeNumberDigits = fractionalDigits = 0;
have_int = have_frac = 0;
numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNull(header));
V_BOOL(&vBool) = VARIANT_FALSE;
}
@ -1227,36 +1227,9 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
if (FAILED(hRes))
return hRes;
if (np.nPwr10 < 0)
{
if (-np.nPwr10 >= np.cDig)
{
/* 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;
}
have_int = np.cDig;
have_frac = 0;
exponent = np.nPwr10;
/* Figure out which format to use */
if (np.dwOutFlags & NUMPRS_NEG)
@ -1264,8 +1237,7 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNegative(header));
V_BOOL(&vBool) = VARIANT_TRUE;
}
else if (wholeNumberDigits == 1 && !fractionalDigits && !multiplier10 &&
!divisor10 && rgbDig[0] == 0)
else if (have_int == 1 && !exponent && rgbDig[0] == 0)
{
numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetZero(header));
V_BOOL(&vBool) = VARIANT_FALSE;
@ -1280,32 +1252,70 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
numHeader->flags, numHeader->multiplier, numHeader->divisor,
numHeader->whole, numHeader->fractional);
if (numHeader->flags & FMT_FLAG_PERCENT &&
!(wholeNumberDigits == 1 && !fractionalDigits && !multiplier10 &&
!divisor10 && rgbDig[0] == 0))
{
/* *100 for %'s. Try to 'steal' fractional digits if we can */
TRACE("Fraction - multiply by 100\n");
if (!fractionalDigits)
multiplier10 += 2;
else
{
fractionalDigits--;
wholeNumberDigits++;
if (!fractionalDigits)
multiplier10++;
else
{
fractionalDigits--;
wholeNumberDigits++;
}
}
}
TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", np.cDig,
np.nPwr10, wholeNumberDigits, fractionalDigits);
TRACE("mult %d; div %d\n", multiplier10, divisor10);
need_int = numHeader->whole;
need_frac = numHeader->fractional;
if (numHeader->flags & FMT_FLAG_PERCENT &&
!(have_int == 1 && !exponent && rgbDig[0] == 0))
exponent += 2;
if (numHeader->flags & FMT_FLAG_EXPONENT)
{
/* Exponent format: length of the integral number part is fixed and
specified by the format. */
pad = need_int - have_int;
if (pad >= 0)
exponent -= pad;
else
{
have_int = need_int;
have_frac -= pad;
exponent -= pad;
pad = 0;
}
}
else
{
/* Convert the exponent */
pad = max(exponent, -have_int);
exponent -= pad;
if (pad < 0)
{
have_int += pad;
have_frac = -pad;
pad = 0;
}
}
/* 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);
prgbDig = rgbDig;
@ -1390,107 +1400,88 @@ VARIANT_FormatNumber_Bool:
*pBuff++ = 'e';
else
*pBuff++ = 'E';
if (divisor10)
if (exponent < 0)
{
*pBuff++ = '-';
sprintfW(pBuff, szPercentZeroStar_d, pToken[1], divisor10);
sprintfW(pBuff, szPercentZeroStar_d, pToken[1], -exponent);
}
else
{
if (*pToken == FMT_NUM_EXP_POS_L || *pToken == FMT_NUM_EXP_POS_U)
*pBuff++ = '+';
sprintfW(pBuff, szPercentZeroStar_d, pToken[1], multiplier10);
sprintfW(pBuff, szPercentZeroStar_d, pToken[1], exponent);
}
while (*pBuff)
pBuff++;
pToken++;
break;
case FMT_NUM_COPY_ZERO:
dwState |= NUM_WRITE_ON;
/* Fall through */
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)
{
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++)
pBuff[count] = '0' + *prgbDig;
pBuff += fractionalDigits;
pad += pToken[1] - count;
have_frac -= count;
while (count--)
*pBuff++ = '0' + *prgbDig++;
if (*pToken == FMT_NUM_COPY_ZERO)
{
for (; pad > 0; pad--)
*pBuff++ = '0'; /* Write zeros for missing trailing digits */
}
}
else
{
int count, count_max;
TRACE("write %d digits or skip\n", pToken[1]);
numHeader->whole -= pToken[1];
count_max = wholeNumberDigits - numHeader->whole;
need_int -= pToken[1];
count_max = have_int + pad - need_int;
if (count_max < 0)
count_max = 0;
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)
if (dwState & NUM_WRITE_ON)
{
TRACE("write %d whole number digits\n", 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];
count = pToken[1] - count_max;
TRACE("write %d leading zeros\n", count);
while (count-- > 0)
*pBuff++ = '0';
}
if (*pToken == FMT_NUM_COPY_ZERO || have_int > 1 || *prgbDig > 0)
{
dwState |= NUM_WRITE_ON;
count = min(count_max, have_int);
count_max -= count;
have_int -= count;
TRACE("write %d whole number digits\n", count);
while (count--)
*pBuff++ = '0'; /* Write leading zeros for missing digits */
*pBuff++ = '0' + *prgbDig++;
}
TRACE("write %d whole number digits\n", wholeNumberDigits);
for (count = 0; count < count_max - multiplier10; count++, prgbDig++) {
*pBuff++ = '0' + *prgbDig;
wholeNumberDigits--;
}
TRACE("write %d whole trailing 0's\n", multiplier10);
for (count = 0; count < multiplier10; count++)
*pBuff++ = '0'; /* Write trailing zeros for multiplied values */
count = min(count_max, pad);
count_max -= count;
pad -= count;
TRACE("write %d whole trailing 0's\n", count);
while (count--)
*pBuff++ = '0';
}
pToken++;
break;