Kaydet (Commit) 66a96c82 authored tarafından Eike Rathke's avatar Eike Rathke

clean up SbiScanner::NextSym() a little, fdo#70319 follow-up

Number recognition was suboptimal and didn't properly resync scan
positions after having detected an error.

Change-Id: I278fdaaf17ed40560785deaaad0e3412a249d90a
üst f85c494b
...@@ -576,10 +576,12 @@ namespace ...@@ -576,10 +576,12 @@ namespace
CPPUNIT_ASSERT(errors == 0); CPPUNIT_ASSERT(errors == 0);
symbols = getSymbols(source2, errors); symbols = getSymbols(source2, errors);
CPPUNIT_ASSERT(symbols.size() == 2); CPPUNIT_ASSERT(symbols.size() == 3);
CPPUNIT_ASSERT(symbols[0].number == 1.23); CPPUNIT_ASSERT(symbols[0].number == 1.2);
CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE); CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE);
CPPUNIT_ASSERT(symbols[1].text == cr); CPPUNIT_ASSERT(rtl::math::round( symbols[1].number, 12) == rtl::math::round( .3, 12));
CPPUNIT_ASSERT(symbols[1].type == SbxDOUBLE);
CPPUNIT_ASSERT(symbols[2].text == cr);
CPPUNIT_ASSERT(errors == 1); CPPUNIT_ASSERT(errors == 1);
symbols = getSymbols(source3, errors); symbols = getSymbols(source3, errors);
...@@ -627,10 +629,11 @@ namespace ...@@ -627,10 +629,11 @@ namespace
CPPUNIT_ASSERT(errors == 0); CPPUNIT_ASSERT(errors == 0);
symbols = getSymbols(source9, errors); symbols = getSymbols(source9, errors);
CPPUNIT_ASSERT(symbols.size() == 2); CPPUNIT_ASSERT(symbols.size() == 3);
CPPUNIT_ASSERT(symbols[0].number == 12000); CPPUNIT_ASSERT(symbols[0].number == 12);
CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE); CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE);
CPPUNIT_ASSERT(symbols[1].text == cr); CPPUNIT_ASSERT(symbols[1].text == OUString("dE3"));
CPPUNIT_ASSERT(symbols[2].text == cr);
CPPUNIT_ASSERT(errors == 1); CPPUNIT_ASSERT(errors == 1);
symbols = getSymbols(source10, errors); symbols = getSymbols(source10, errors);
...@@ -647,16 +650,16 @@ namespace ...@@ -647,16 +650,16 @@ namespace
CPPUNIT_ASSERT(symbols[1].text == cr); CPPUNIT_ASSERT(symbols[1].text == cr);
CPPUNIT_ASSERT(errors == 0); CPPUNIT_ASSERT(errors == 0);
/* FIXME: SbiScanner::NextSym() is total crap, the result of scanning
* "12e++3" should be something different than this.. */
symbols = getSymbols(source12, errors); symbols = getSymbols(source12, errors);
CPPUNIT_ASSERT(symbols.size() == 4); CPPUNIT_ASSERT(symbols.size() == 6);
CPPUNIT_ASSERT(symbols[0].number == 12); CPPUNIT_ASSERT(symbols[0].number == 12);
CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE); CPPUNIT_ASSERT(symbols[0].type == SbxDOUBLE);
CPPUNIT_ASSERT(symbols[1].text == OUString("+")); CPPUNIT_ASSERT(symbols[1].text == OUString("e"));
CPPUNIT_ASSERT(symbols[2].number == 3); CPPUNIT_ASSERT(symbols[2].text == OUString("+"));
CPPUNIT_ASSERT(symbols[2].type == SbxINTEGER); CPPUNIT_ASSERT(symbols[3].text == OUString("+"));
CPPUNIT_ASSERT(symbols[3].text == cr); CPPUNIT_ASSERT(symbols[4].number == 3);
CPPUNIT_ASSERT(symbols[4].type == SbxINTEGER);
CPPUNIT_ASSERT(symbols[5].text == cr);
CPPUNIT_ASSERT(errors == 1); CPPUNIT_ASSERT(errors == 1);
symbols = getSymbols(source13, errors); symbols = getSymbols(source13, errors);
......
...@@ -302,12 +302,12 @@ bool SbiScanner::NextSym() ...@@ -302,12 +302,12 @@ bool SbiScanner::NextSym()
(nCol + 1 < aLine.getLength() && aLine[nCol] == '.' && theBasicCharClass::get().isDigit(aLine[nCol + 1] & 0xFF))) (nCol + 1 < aLine.getLength() && aLine[nCol] == '.' && theBasicCharClass::get().isDigit(aLine[nCol + 1] & 0xFF)))
{ {
short exp = 0; short exp = 0;
short comma = 0; short dec = 0;
short ndig = 0;
short ncdig = 0;
eScanType = SbxDOUBLE; eScanType = SbxDOUBLE;
bool bScanError = false;
bool bBufOverflow = false; bool bBufOverflow = false;
while(nCol < aLine.getLength() && strchr("0123456789.DEde", aLine[nCol])) // All this because of 'D' or 'd' floating point type, sigh..
while(!bScanError && nCol < aLine.getLength() && strchr("0123456789.DEde", aLine[nCol]))
{ {
// from 4.1.1996: buffer full? -> go on scanning empty // from 4.1.1996: buffer full? -> go on scanning empty
if( (p-buf) == (BUF_SIZE-1) ) if( (p-buf) == (BUF_SIZE-1) )
...@@ -319,64 +319,84 @@ bool SbiScanner::NextSym() ...@@ -319,64 +319,84 @@ bool SbiScanner::NextSym()
// point or exponent? // point or exponent?
if(aLine[nCol] == '.') if(aLine[nCol] == '.')
{ {
if( ++comma > 1 ) if( ++dec > 1 )
{ bScanError = true;
++pLine; ++nCol; continue;
}
else else
{ *p++ = '.';
*p = '.';
++p, ++pLine, ++nCol;
}
} }
else if(strchr("DdEe", aLine[nCol])) else if(strchr("DdEe", aLine[nCol]))
{ {
if (++exp > 1) if (++exp > 1)
bScanError = true;
else
{ {
++pLine; ++nCol; continue; *p++ = 'E';
} if (nCol + 1 < aLine.getLength() && (aLine[nCol+1] == '+' || aLine[nCol+1] == '-'))
{
*p = 'E'; ++pLine, ++nCol;
++p, ++pLine, ++nCol; if( (p-buf) == (BUF_SIZE-1) )
{
if(aLine[nCol] == '+') bBufOverflow = true;
++pLine, ++nCol; continue;
else if(aLine[nCol] == '-') }
{ *p++ = aLine[nCol];
*p = '-'; }
++p, ++pLine, ++nCol;
} }
} }
else else
{ {
*p = aLine[nCol]; *p++ = aLine[nCol];
++p, ++pLine, ++nCol;
if( comma && !exp ) ++ncdig;
} }
if (!exp) ++ndig; ++pLine, ++nCol;
} }
*p = 0; *p = 0;
aSym = p; bNumber = true; aSym = p; bNumber = true;
if( comma > 1 || exp > 1 ) // For bad characters, scan and parse errors generate only one error.
{ aError = OUString('.'); SbError nError = 0;
GenError( SbERR_BAD_CHAR_IN_NUMBER ); } if (bScanError)
{
--pLine, --nCol;
aError = OUString( aLine[nCol]);
nError = SbERR_BAD_CHAR_IN_NUMBER;
}
rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
const sal_Unicode* pParseEnd = buf; const sal_Unicode* pParseEnd = buf;
nVal = rtl_math_uStringToDouble( buf, buf+(p-buf), '.', ',', &eStatus, &pParseEnd ); nVal = rtl_math_uStringToDouble( buf, buf+(p-buf), '.', ',', &eStatus, &pParseEnd );
if (eStatus != rtl_math_ConversionStatus_Ok || pParseEnd != buf+(p-buf)) if (pParseEnd != buf+(p-buf))
GenError( SbERR_MATH_OVERFLOW ); {
// e.g. "12e" or "12e+", or with bScanError "12d"+"E".
sal_Int32 nChars = buf+(p-buf) - pParseEnd;
pLine -= nChars;
nCol -= nChars;
// For bScanError, pLine and nCol were already decremented, just
// add that character to the parse end.
if (bScanError)
++nChars;
// Copy error position from original string, not the buffer
// replacement where "12dE" => "12EE".
aError = aLine.copy( nCol, nChars);
nError = SbERR_BAD_CHAR_IN_NUMBER;
}
else if (eStatus != rtl_math_ConversionStatus_Ok)
{
// Keep the scan error and character at position, if any.
if (!nError)
nError = SbERR_MATH_OVERFLOW;
}
if (nError)
GenError( nError );
ndig = ndig - comma; if( !dec && !exp )
if( !comma && !exp )
{ {
if( nVal >= SbxMININT && nVal <= SbxMAXINT ) if( nVal >= SbxMININT && nVal <= SbxMAXINT )
eScanType = SbxINTEGER; eScanType = SbxINTEGER;
else else if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG ) eScanType = SbxLONG;
eScanType = SbxLONG;
} }
if( bBufOverflow ) if( bBufOverflow )
GenError( SbERR_MATH_OVERFLOW ); GenError( SbERR_MATH_OVERFLOW );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment