[resend] VarParseNumFromStr: Convert hex and oct strings
Fabian Cenedese
Cenedese at indel.ch
Tue Mar 16 02:10:51 CST 2004
Hi
Anything I need to improve on this one?
Thanks
Changelog:
Fabian Cenedese <Cenedese at indel.ch>
Let VarParseNumFromStr and VarNumFromParseNum cope with hex and oct
strings. Needed from VB conversions such as CLng, CInt, CByte...
Index: wine/dlls/oleaut32/variant.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/variant.c,v
retrieving revision 1.90
diff -u -r1.90 variant.c
--- wine/dlls/oleaut32/variant.c 27 Feb 2004 21:32:55 -0000 1.90
+++ wine/dlls/oleaut32/variant.c 16 Mar 2004 08:02:17 -0000
@@ -1464,6 +1464,8 @@
#define B_EXPONENT_START 0x4
#define B_INEXACT_ZEROS 0x8
#define B_LEADING_ZERO 0x10
+#define B_PROCESSING_HEX 0x20
+#define B_PROCESSING_OCT 0x40
/**********************************************************************
* VarParseNumFromStr [OLEAUT32.46]
@@ -1581,6 +1583,23 @@
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 */
while (*lpszStr == '0')
{
@@ -1624,7 +1643,8 @@
}
else
{
- if (pNumprs->cDig >= iMaxDigits)
+ if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
+ && !(dwState & B_PROCESSING_OCT))
{
pNumprs->dwOutFlags |= NUMPRS_INEXACT;
@@ -1639,8 +1659,13 @@
}
else
{
+ if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
+ return DISP_E_TYPEMISMATCH;
+ }
+
if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
+
rgbTmp[pNumprs->cDig] = *lpszStr - '0';
}
pNumprs->cDig++;
@@ -1694,6 +1719,24 @@
dwState |= B_NEGATIVE_EXPONENT;
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
break; /* Stop at an unrecognised character */
@@ -1724,14 +1767,26 @@
/* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
- while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
- {
- if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
- pNumprs->nPwr10--;
- else
- pNumprs->nPwr10++;
+ 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])
+ {
+ if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
+ pNumprs->nPwr10--;
+ else
+ pNumprs->nPwr10++;
- pNumprs->cDig--;
+ pNumprs->cDig--;
+ }
+ }
}
} else
{
@@ -1866,7 +1921,110 @@
if (pNumprs->nBaseShift)
{
/* 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;
}
Index: wine/dlls/oleaut32/tests/vartest.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/tests/vartest.c,v
retrieving revision 1.24
diff -u -r1.24 vartest.c
--- wine/dlls/oleaut32/tests/vartest.c 26 Feb 2004 05:27:11 -0000 1.24
+++ wine/dlls/oleaut32/tests/vartest.c 16 Mar 2004 08:02:18 -0000
@@ -789,6 +789,45 @@
EXPECTRGB(2,0);
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 **/
/* Empty parens = error */
More information about the wine-patches
mailing list