- 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:
parent
138934129c
commit
0b1f8cdf4d
|
@ -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,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");
|
||||
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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
need_int = numHeader->whole;
|
||||
need_frac = numHeader->fractional;
|
||||
|
||||
if (numHeader->flags & FMT_FLAG_PERCENT &&
|
||||
!(wholeNumberDigits == 1 && !fractionalDigits && !multiplier10 &&
|
||||
!divisor10 && rgbDig[0] == 0))
|
||||
!(have_int == 1 && !exponent && rgbDig[0] == 0))
|
||||
exponent += 2;
|
||||
|
||||
if (numHeader->flags & FMT_FLAG_EXPONENT)
|
||||
{
|
||||
/* *100 for %'s. Try to 'steal' fractional digits if we can */
|
||||
TRACE("Fraction - multiply by 100\n");
|
||||
if (!fractionalDigits)
|
||||
multiplier10 += 2;
|
||||
/* 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
|
||||
{
|
||||
fractionalDigits--;
|
||||
wholeNumberDigits++;
|
||||
if (!fractionalDigits)
|
||||
multiplier10++;
|
||||
else
|
||||
{
|
||||
fractionalDigits--;
|
||||
wholeNumberDigits++;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
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--)
|
||||
*pBuff++ = '0'; /* Write leading zeros for missing digits */
|
||||
while (count-- > 0)
|
||||
*pBuff++ = '0';
|
||||
}
|
||||
TRACE("write %d whole number digits\n", wholeNumberDigits);
|
||||
for (count = 0; count < count_max - multiplier10; count++, prgbDig++) {
|
||||
*pBuff++ = '0' + *prgbDig;
|
||||
wholeNumberDigits--;
|
||||
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' + *prgbDig++;
|
||||
}
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue