Centralize the parseDouble functions in the parsers and gcc specialcase

This commit is contained in:
Marek Roszko 2022-08-14 18:40:54 -04:00
parent 84138d5039
commit c418b25756
9 changed files with 73 additions and 116 deletions

View File

@ -849,20 +849,8 @@ double DRAWING_SHEET_PARSER::parseDouble()
if( token != T_NUMBER ) if( token != T_NUMBER )
Expecting( T_NUMBER ); Expecting( T_NUMBER );
double dval{};
const std::string& str = CurStr();
std::from_chars_result res = std::from_chars( str.data(), str.data() + str.size(), dval );
if( res.ec != std::errc() ) return DSNLEXER::parseDouble();
{
wxString error;
error.Printf( _( "Invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
CurSource(), CurLineNumber(), CurOffset() );
THROW_IO_ERROR( error );
}
return dval;
} }
// defaultDrawingSheet is the default drawing sheet using the S expr. // defaultDrawingSheet is the default drawing sheet using the S expr.

View File

@ -23,7 +23,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <charconv>
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include <cstdlib> // bsearch() #include <cstdlib> // bsearch()
@ -820,3 +820,51 @@ wxArrayString* DSNLEXER::ReadCommentLines()
return ret; return ret;
} }
double DSNLEXER::parseDouble()
{
#if ( defined( __GNUC__ ) && __GNUC__ < 11 ) || ( defined( __clang__ ) && __clang_major__ < 13 )
// GCC older than 11 "supports" C++17 without supporting the C++17 std::from_chars for doubles
// clang is similar
char* tmp;
errno = 0;
double fval = strtod( CurText(), &tmp );
if( errno )
{
wxString error;
error.Printf( _( "Invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
CurSource(), CurLineNumber(), CurOffset() );
THROW_IO_ERROR( error );
}
if( CurText() == tmp )
{
wxString error;
error.Printf( _( "Missing floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
CurSource(), CurLineNumber(), CurOffset() );
THROW_IO_ERROR( error );
}
return fval;
#else
// Use std::from_chars which is designed to be locale independent and performance oriented for data interchange
double dval{};
const std::string& str = CurStr();
std::from_chars_result res = std::from_chars( str.data(), str.data() + str.size(), dval );
if( res.ec != std::errc() )
{
THROW_PARSE_ERROR( _( "Invalid floating point number" ), CurSource(), CurLine(),
CurLineNumber(), CurOffset() );
}
return dval;
#endif
}

View File

@ -316,20 +316,7 @@ double STROKE_PARAMS_PARSER::parseDouble( const char* aText )
if( token != T_NUMBER ) if( token != T_NUMBER )
Expecting( aText ); Expecting( aText );
double dval{}; return DSNLEXER::parseDouble();
const std::string& str = CurStr();
std::from_chars_result res = std::from_chars( str.data(), str.data() + str.size(), dval );
if( res.ec != std::errc() )
{
wxString error;
error.Printf( _( "Invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
CurSource(), CurLineNumber(), CurOffset() );
THROW_IO_ERROR( error );
}
return dval;
} }

View File

@ -422,29 +422,6 @@ LIB_ITEM* SCH_SEXPR_PARSER::ParseDrawItem()
} }
double SCH_SEXPR_PARSER::parseDouble()
{
// In case the file got saved with the wrong locale.
if( strchr( CurText(), ',' ) != nullptr )
{
THROW_PARSE_ERROR( _( "Floating point number with incorrect locale" ), CurSource(),
CurLine(), CurLineNumber(), CurOffset() );
}
double dval{};
const std::string& str = CurStr();
std::from_chars_result res = std::from_chars( str.data(), str.data() + str.size(), dval );
if( res.ec != std::errc() )
{
THROW_PARSE_ERROR( _( "Invalid floating point number" ), CurSource(), CurLine(),
CurLineNumber(), CurOffset() );
}
return dval;
}
int SCH_SEXPR_PARSER::parseInternalUnits() int SCH_SEXPR_PARSER::parseInternalUnits()
{ {
auto retval = parseDouble() * IU_PER_MM; auto retval = parseDouble() * IU_PER_MM;

View File

@ -117,26 +117,6 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
return parseInt(); return parseInt();
} }
/**
* Parse the current token as an ASCII numeric string with possible leading
* whitespace into a double precision floating point number.
*
* @throw IO_ERROR if an error occurs attempting to convert the current token.
* @return The result of the parsed token.
*/
double parseDouble();
inline double parseDouble( const char* aExpected )
{
NeedNUMBER( aExpected );
return parseDouble();
}
inline double parseDouble( TSCHEMATIC_T::T aToken )
{
return parseDouble( GetTokenText( aToken ) );
}
int parseInternalUnits(); int parseInternalUnits();
int parseInternalUnits( const char* aExpected ); int parseInternalUnits( const char* aExpected );

View File

@ -498,6 +498,27 @@ protected:
return false; return false;
} }
/**
* Parse the current token as an ASCII numeric string with possible leading
* whitespace into a double precision floating point number.
*
* @throw IO_ERROR if an error occurs attempting to convert the current token.
* @return The result of the parsed token.
*/
double parseDouble();
double parseDouble( const char* aExpected )
{
NeedNUMBER( aExpected );
return parseDouble();
}
template <typename T>
inline double parseDouble( T aToken )
{
return parseDouble( GetTokenText( aToken ) );
}
bool iOwnReaders; ///< on readerStack, should I delete them? bool iOwnReaders; ///< on readerStack, should I delete them?
const char* start; const char* start;
const char* next; const char* next;

View File

@ -660,20 +660,7 @@ double PCB_PLOT_PARAMS_PARSER::parseDouble()
if( token != T_NUMBER ) if( token != T_NUMBER )
Expecting( T_NUMBER ); Expecting( T_NUMBER );
double dval{}; return DSNLEXER::parseDouble();
const std::string& str = CurStr();
std::from_chars_result res = std::from_chars( str.data(), str.data() + str.size(), dval );
if( res.ec != std::errc() )
{
wxString error;
error.Printf( _( "Invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
CurSource(), CurLineNumber(), CurOffset() );
THROW_IO_ERROR( error );
}
return dval;
} }

View File

@ -175,25 +175,6 @@ void PCB_PARSER::pushValueIntoMap( int aIndex, int aValue )
} }
double PCB_PARSER::parseDouble()
{
double dval{};
const std::string& str = CurStr();
std::from_chars_result res = std::from_chars( str.data(), str.data() + str.size(), dval );
if( res.ec != std::errc() )
{
wxString error;
error.Printf( _( "Invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
CurSource(), CurLineNumber(), CurOffset() );
THROW_IO_ERROR( error );
}
return dval;
}
int PCB_PARSER::parseBoardUnits() int PCB_PARSER::parseBoardUnits()
{ {
// There should be no major rounding issues here, since the values in // There should be no major rounding issues here, since the values in

View File

@ -282,18 +282,6 @@ private:
* @return The result of the parsed token. * @return The result of the parsed token.
* @throw IO_ERROR if an error occurs attempting to convert the current token. * @throw IO_ERROR if an error occurs attempting to convert the current token.
*/ */
double parseDouble();
inline double parseDouble( const char* aExpected )
{
NeedNUMBER( aExpected );
return parseDouble();
}
inline double parseDouble( PCB_KEYS_T::T aToken )
{
return parseDouble( GetTokenText( aToken ) );
}
int parseBoardUnits(); int parseBoardUnits();