Let VarParseNumFromStr and VarNumFromParseNum cope with hex and oct
strings. Needed from VB conversions such as CLng, CInt, CByte...
This commit is contained in:
parent
ccd428e503
commit
5feedfdc73
|
@ -789,6 +789,45 @@ static void test_VarParseNumFromStr(void)
|
||||||
EXPECTRGB(2,0);
|
EXPECTRGB(2,0);
|
||||||
EXPECTRGB(3,FAILDIG);
|
EXPECTRGB(3,FAILDIG);
|
||||||
|
|
||||||
|
/* VB hex */
|
||||||
|
CONVERT("&HF800", NUMPRS_HEX_OCT);
|
||||||
|
EXPECT(4,NUMPRS_HEX_OCT,0x40,6,4,0);
|
||||||
|
EXPECTRGB(0,15);
|
||||||
|
EXPECTRGB(1,8);
|
||||||
|
EXPECTRGB(2,0);
|
||||||
|
EXPECTRGB(3,0);
|
||||||
|
EXPECTRGB(4,FAILDIG);
|
||||||
|
|
||||||
|
/* VB hex lower case and leading zero */
|
||||||
|
CONVERT("&h0abcd", NUMPRS_HEX_OCT);
|
||||||
|
EXPECT(4,NUMPRS_HEX_OCT,0x40,7,4,0);
|
||||||
|
EXPECTRGB(0,10);
|
||||||
|
EXPECTRGB(1,11);
|
||||||
|
EXPECTRGB(2,12);
|
||||||
|
EXPECTRGB(3,13);
|
||||||
|
EXPECTRGB(4,FAILDIG);
|
||||||
|
|
||||||
|
/* VB oct */
|
||||||
|
CONVERT("&O300", NUMPRS_HEX_OCT);
|
||||||
|
EXPECT(3,NUMPRS_HEX_OCT,0x40,5,3,0);
|
||||||
|
EXPECTRGB(0,3);
|
||||||
|
EXPECTRGB(1,0);
|
||||||
|
EXPECTRGB(2,0);
|
||||||
|
EXPECTRGB(3,FAILDIG);
|
||||||
|
|
||||||
|
/* VB oct lower case and leading zero */
|
||||||
|
CONVERT("&o0777", NUMPRS_HEX_OCT);
|
||||||
|
EXPECT(3,NUMPRS_HEX_OCT,0x40,6,3,0);
|
||||||
|
EXPECTRGB(0,7);
|
||||||
|
EXPECTRGB(1,7);
|
||||||
|
EXPECTRGB(2,7);
|
||||||
|
EXPECTRGB(3,FAILDIG);
|
||||||
|
|
||||||
|
/* VB oct char bigger than 7 */
|
||||||
|
CONVERT("&o128", NUMPRS_HEX_OCT);
|
||||||
|
EXPECTFAIL;
|
||||||
|
EXPECTRGB(0,FAILDIG);
|
||||||
|
|
||||||
/** NUMPRS_PARENS **/
|
/** NUMPRS_PARENS **/
|
||||||
|
|
||||||
/* Empty parens = error */
|
/* Empty parens = error */
|
||||||
|
|
|
@ -1464,6 +1464,8 @@ void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, D
|
||||||
#define B_EXPONENT_START 0x4
|
#define B_EXPONENT_START 0x4
|
||||||
#define B_INEXACT_ZEROS 0x8
|
#define B_INEXACT_ZEROS 0x8
|
||||||
#define B_LEADING_ZERO 0x10
|
#define B_LEADING_ZERO 0x10
|
||||||
|
#define B_PROCESSING_HEX 0x20
|
||||||
|
#define B_PROCESSING_OCT 0x40
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* VarParseNumFromStr [OLEAUT32.46]
|
* VarParseNumFromStr [OLEAUT32.46]
|
||||||
|
@ -1581,6 +1583,23 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
|
||||||
chars.cCurrencyDigitSeperator = chars.cDigitSeperator;
|
chars.cCurrencyDigitSeperator = chars.cDigitSeperator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
|
||||||
|
pNumprs->dwInFlags & NUMPRS_HEX_OCT)
|
||||||
|
{
|
||||||
|
dwState |= B_PROCESSING_HEX;
|
||||||
|
pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
|
||||||
|
cchUsed=cchUsed+2;
|
||||||
|
lpszStr=lpszStr+2;
|
||||||
|
}
|
||||||
|
else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
|
||||||
|
pNumprs->dwInFlags & NUMPRS_HEX_OCT)
|
||||||
|
{
|
||||||
|
dwState |= B_PROCESSING_OCT;
|
||||||
|
pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
|
||||||
|
cchUsed=cchUsed+2;
|
||||||
|
lpszStr=lpszStr+2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Strip Leading zeros */
|
/* Strip Leading zeros */
|
||||||
while (*lpszStr == '0')
|
while (*lpszStr == '0')
|
||||||
{
|
{
|
||||||
|
@ -1624,7 +1643,8 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pNumprs->cDig >= iMaxDigits)
|
if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
|
||||||
|
&& !(dwState & B_PROCESSING_OCT))
|
||||||
{
|
{
|
||||||
pNumprs->dwOutFlags |= NUMPRS_INEXACT;
|
pNumprs->dwOutFlags |= NUMPRS_INEXACT;
|
||||||
|
|
||||||
|
@ -1639,8 +1659,13 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
|
||||||
|
return DISP_E_TYPEMISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
|
if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
|
||||||
pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
|
pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
|
||||||
|
|
||||||
rgbTmp[pNumprs->cDig] = *lpszStr - '0';
|
rgbTmp[pNumprs->cDig] = *lpszStr - '0';
|
||||||
}
|
}
|
||||||
pNumprs->cDig++;
|
pNumprs->cDig++;
|
||||||
|
@ -1694,6 +1719,24 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
|
||||||
dwState |= B_NEGATIVE_EXPONENT;
|
dwState |= B_NEGATIVE_EXPONENT;
|
||||||
cchUsed++;
|
cchUsed++;
|
||||||
}
|
}
|
||||||
|
else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
|
||||||
|
(*lpszStr >= 'A' && *lpszStr <= 'F')) &&
|
||||||
|
dwState & B_PROCESSING_HEX)
|
||||||
|
{
|
||||||
|
if (pNumprs->cDig >= iMaxDigits)
|
||||||
|
{
|
||||||
|
return DISP_E_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*lpszStr >= 'a')
|
||||||
|
rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
|
||||||
|
else
|
||||||
|
rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
|
||||||
|
}
|
||||||
|
pNumprs->cDig++;
|
||||||
|
cchUsed++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break; /* Stop at an unrecognised character */
|
break; /* Stop at an unrecognised character */
|
||||||
|
|
||||||
|
@ -1724,6 +1767,16 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
|
||||||
/* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
|
/* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
|
||||||
memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
|
memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
|
||||||
|
|
||||||
|
if (dwState & B_PROCESSING_HEX) {
|
||||||
|
/* hex numbers have always the same format */
|
||||||
|
pNumprs->nPwr10=0;
|
||||||
|
pNumprs->nBaseShift=4;
|
||||||
|
} else {
|
||||||
|
if (dwState & B_PROCESSING_OCT) {
|
||||||
|
/* oct numbers have always the same format */
|
||||||
|
pNumprs->nPwr10=0;
|
||||||
|
pNumprs->nBaseShift=3;
|
||||||
|
} else {
|
||||||
while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
|
while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
|
||||||
{
|
{
|
||||||
if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
|
if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
|
||||||
|
@ -1733,6 +1786,8 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
|
||||||
|
|
||||||
pNumprs->cDig--;
|
pNumprs->cDig--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
/* Remove trailing zeros from the last (whole number or decimal) part */
|
/* Remove trailing zeros from the last (whole number or decimal) part */
|
||||||
|
@ -1866,7 +1921,110 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
|
||||||
if (pNumprs->nBaseShift)
|
if (pNumprs->nBaseShift)
|
||||||
{
|
{
|
||||||
/* nBaseShift indicates a hex or octal number */
|
/* nBaseShift indicates a hex or octal number */
|
||||||
FIXME("nBaseShift=%d not yet implemented, returning overflow\n", pNumprs->nBaseShift);
|
ULONG64 ul64 = 0;
|
||||||
|
LONG64 l64;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Convert the hex or octal number string into a UI64 */
|
||||||
|
for (i = 0; i < pNumprs->cDig; i++)
|
||||||
|
{
|
||||||
|
if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
|
||||||
|
{
|
||||||
|
TRACE("Overflow multiplying digits\n");
|
||||||
|
return DISP_E_OVERFLOW;
|
||||||
|
}
|
||||||
|
ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* also make a negative representation */
|
||||||
|
l64=-ul64;
|
||||||
|
|
||||||
|
/* Try signed and unsigned types in size order */
|
||||||
|
if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN)))
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_I1;
|
||||||
|
if (ul64 <= I1_MAX)
|
||||||
|
V_I1(pVarDst) = ul64;
|
||||||
|
else
|
||||||
|
V_I1(pVarDst) = l64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_UI1;
|
||||||
|
V_UI1(pVarDst) = ul64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN)))
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_I2;
|
||||||
|
if (ul64 <= I2_MAX)
|
||||||
|
V_I2(pVarDst) = ul64;
|
||||||
|
else
|
||||||
|
V_I2(pVarDst) = l64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_UI2;
|
||||||
|
V_UI2(pVarDst) = ul64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_I4;
|
||||||
|
if (ul64 <= I4_MAX)
|
||||||
|
V_I4(pVarDst) = ul64;
|
||||||
|
else
|
||||||
|
V_I4(pVarDst) = l64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_UI4;
|
||||||
|
V_UI4(pVarDst) = ul64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN)))
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_I8;
|
||||||
|
V_I8(pVarDst) = ul64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_UI8)
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_UI8;
|
||||||
|
V_UI8(pVarDst) = ul64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_DECIMAL;
|
||||||
|
DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
|
||||||
|
DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
|
||||||
|
DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_R4;
|
||||||
|
if (ul64 <= I4_MAX)
|
||||||
|
V_R4(pVarDst) = ul64;
|
||||||
|
else
|
||||||
|
V_R4(pVarDst) = l64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
|
||||||
|
{
|
||||||
|
V_VT(pVarDst) = VT_R8;
|
||||||
|
if (ul64 <= I4_MAX)
|
||||||
|
V_R8(pVarDst) = ul64;
|
||||||
|
else
|
||||||
|
V_R8(pVarDst) = l64;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
|
||||||
return DISP_E_OVERFLOW;
|
return DISP_E_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue