From 0b1f8cdf4dc0b52abd379792a267f881dad5b77f Mon Sep 17 00:00:00 2001 From: Michael Stefaniuc Date: Thu, 23 Jun 2005 09:48:07 +0000 Subject: [PATCH] - 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 --- dlls/oleaut32/tests/vartest.c | 37 ++++--- dlls/oleaut32/varformat.c | 233 ++++++++++++++++++++---------------------- 2 files changed, 135 insertions(+), 135 deletions(-) diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c index 22a27833652..9dbdcf4a883 100644 --- a/dlls/oleaut32/tests/vartest.c +++ b/dlls/oleaut32/tests/vartest.c @@ -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 */ diff --git a/dlls/oleaut32/varformat.c b/dlls/oleaut32/varformat.c index f5f8247b751..9e4db05f4e7 100644 --- a/dlls/oleaut32/varformat.c +++ b/dlls/oleaut32/varformat.c @@ -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 + 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) { - fractionalDigits--; - wholeNumberDigits++; + /* 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("cDig %d; nPwr10 %d, whole %d, frac %d ", np.cDig, - np.nPwr10, wholeNumberDigits, fractionalDigits); - TRACE("mult %d; div %d\n", multiplier10, divisor10); - + 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_SKIP: - if (dwState & NUM_WROTE_DEC) - { - int count; + case FMT_NUM_COPY_ZERO: + dwState |= NUM_WRITE_ON; + /* Fall through */ - TRACE("write %d fractional digits or skip\n", pToken[1]); + 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"); - for (count = 0; count < fractionalDigits; count++, prgbDig++) - pBuff[count] = '0' + *prgbDig; - pBuff += fractionalDigits; - } - else + if (dwState & NUM_WROTE_DEC) { - int count, count_max; + int count, i; - TRACE("write %d digits or skip\n", pToken[1]); - - numHeader->whole -= pToken[1]; - count_max = wholeNumberDigits - numHeader->whole; - 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 (!(numHeader->flags & FMT_FLAG_EXPONENT) && exponent < 0) { - 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 */ + /* 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'; } - } - 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]); + else + count = min(have_frac, pToken[1]); - for (count = 0; count < fractionalDigits; count++, prgbDig++) - pBuff[count] = '0' + *prgbDig; - pBuff += fractionalDigits; - if (pToken[1] > fractionalDigits) + pad += pToken[1] - count; + have_frac -= count; + while (count--) + *pBuff++ = '0' + *prgbDig++; + if (*pToken == FMT_NUM_COPY_ZERO) { - count = pToken[1] - fractionalDigits; - while (count--) - *pBuff++ = '0'; /* Write trailing zeros for missing digits */ + for (; pad > 0; pad--) + *pBuff++ = '0'; /* Write zeros for missing trailing 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)) + need_int -= pToken[1]; + count_max = have_int + pad - need_int; + if (count_max < 0) + count_max = 0; + if (dwState & NUM_WRITE_ON) { - 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; -- 2.11.4.GIT