More robust file reading for simulator files.
This commit is contained in:
parent
afc6b325b2
commit
c381b6d024
|
@ -106,6 +106,47 @@ std::string StrPrintf( const char* format, ... )
|
|||
}
|
||||
|
||||
|
||||
wxString SafeReadFile( const wxString& aFilePath, const wxString& aReadType )
|
||||
{
|
||||
auto FROM_UTF8_WINE =
|
||||
[]( const char* cstring )
|
||||
{
|
||||
wxString line = wxString::FromUTF8( cstring );
|
||||
|
||||
if( line.IsEmpty() ) // happens when cstring is not a valid UTF8 sequence
|
||||
line = wxConvCurrent->cMB2WC( cstring ); // try to use locale conversion
|
||||
|
||||
// We have trouble here *probably* because Wine-hosted LTSpice writes out MSW
|
||||
// encoded text on a macOS, where it isn't expected. In any case, wxWidgets'
|
||||
// wxSafeConvert() appears to get around it.
|
||||
|
||||
if( line.IsEmpty() )
|
||||
line = wxSafeConvertMB2WX( cstring );
|
||||
|
||||
// I'm not sure what the source of this style of line-endings is, but it can be
|
||||
// found in some Fairchild Semiconductor SPICE files.
|
||||
line.Replace( wxS( "\r\r\n" ), wxS( "\n" ) );
|
||||
|
||||
return line;
|
||||
};
|
||||
|
||||
// Open file
|
||||
FILE* fp = wxFopen( aFilePath, aReadType );
|
||||
|
||||
if( !fp )
|
||||
THROW_IO_ERROR( wxString::Format( _( "Cannot open file '%s'." ), aFilePath ) );
|
||||
|
||||
FILE_LINE_READER fileReader( fp, aFilePath );
|
||||
|
||||
wxString contents;
|
||||
|
||||
while( fileReader.ReadLine() )
|
||||
contents += FROM_UTF8_WINE( fileReader.Line() );
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
|
||||
//-----<LINE_READER>------------------------------------------------------
|
||||
|
||||
LINE_READER::LINE_READER( unsigned aMaxLineLength ) :
|
||||
|
|
|
@ -88,8 +88,8 @@ wxString SIM_LIB_MGR::ResolveLibraryPath( const wxString& aLibraryPath, const PR
|
|||
}
|
||||
|
||||
|
||||
std::string SIM_LIB_MGR::ResolveEmbeddedLibraryPath( const std::string& aLibPath,
|
||||
const std::string& aRelativeLib )
|
||||
wxString SIM_LIB_MGR::ResolveEmbeddedLibraryPath( const wxString& aLibPath,
|
||||
const wxString& aRelativeLib )
|
||||
{
|
||||
wxFileName testPath( aLibPath );
|
||||
wxString fullPath( aLibPath );
|
||||
|
@ -123,7 +123,7 @@ std::string SIM_LIB_MGR::ResolveEmbeddedLibraryPath( const std::string& aLibPath
|
|||
catch( ... )
|
||||
{}
|
||||
|
||||
return fullPath.ToStdString();
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,7 +133,7 @@ void SIM_LIB_MGR::SetLibrary( const wxString& aLibraryPath )
|
|||
{
|
||||
wxString path = ResolveLibraryPath( aLibraryPath, m_project );
|
||||
|
||||
std::function<std::string(const std::string&, const std::string&)> f2 =
|
||||
std::function<wxString(const wxString&, const wxString&)> f2 =
|
||||
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 );
|
||||
|
||||
std::unique_ptr<SIM_LIBRARY> library = SIM_LIBRARY::Create( path, m_reporter, &f2 );
|
||||
|
@ -287,7 +287,7 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const wxString& aLibraryPath,
|
|||
{
|
||||
path = ResolveLibraryPath( aLibraryPath, m_project );
|
||||
|
||||
std::function<std::string( const std::string&, const std::string& )> f2 =
|
||||
std::function<wxString( const wxString&, const wxString& )> f2 =
|
||||
std::bind( &SIM_LIB_MGR::ResolveEmbeddedLibraryPath, this, _1, _2 );
|
||||
|
||||
auto it = m_libraries.try_emplace( path, SIM_LIBRARY::Create( path, m_reporter, &f2 ) ).first;
|
||||
|
|
|
@ -76,9 +76,7 @@ public:
|
|||
std::vector<std::reference_wrapper<SIM_MODEL>> GetModels() const;
|
||||
|
||||
static wxString ResolveLibraryPath( const wxString& aLibraryPath, const PROJECT* aProject );
|
||||
|
||||
std::string ResolveEmbeddedLibraryPath( const std::string& aLibPath,
|
||||
const std::string& aRelativeLib );
|
||||
wxString ResolveEmbeddedLibraryPath( const wxString& aLibPath, const wxString& aRelativeLib );
|
||||
|
||||
private:
|
||||
const PROJECT* m_project;
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
#include <macros.h>
|
||||
|
||||
|
||||
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString& aFilePath, REPORTER* aReporter,
|
||||
std::function<std::string( const std::string&, const std::string& )> *aResolver )
|
||||
std::unique_ptr<SIM_LIBRARY>
|
||||
SIM_LIBRARY::Create( const wxString& aFilePath, REPORTER* aReporter,
|
||||
std::function<wxString( const wxString&, const wxString& )>* aResolver )
|
||||
{
|
||||
std::unique_ptr<SIM_LIBRARY> library;
|
||||
|
||||
|
@ -41,13 +42,13 @@ std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( const wxString& aFilePath, REP
|
|||
|
||||
library->m_reporter = aReporter;
|
||||
library->m_pathResolver = aResolver;
|
||||
library->ReadFile( std::string( TO_UTF8( aFilePath ) ), aReporter );
|
||||
library->ReadFile( aFilePath, aReporter );
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
|
||||
void SIM_LIBRARY::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
|
||||
void SIM_LIBRARY::ReadFile( const wxString& aFilePath, REPORTER* aReporter )
|
||||
{
|
||||
m_filePath = aFilePath;
|
||||
}
|
||||
|
|
|
@ -52,9 +52,9 @@ public:
|
|||
* @param aReporter The reporter the library reports to
|
||||
* @return The library loaded in a newly constructed object.
|
||||
*/
|
||||
static std::unique_ptr<SIM_LIBRARY> Create( const wxString& aFilePath,
|
||||
REPORTER* aReporter = nullptr,
|
||||
std::function<std::string( const std::string&, const std::string& )>* aResolver = nullptr);
|
||||
static std::unique_ptr<SIM_LIBRARY>
|
||||
Create( const wxString& aFilePath, REPORTER* aReporter,
|
||||
std::function<wxString( const wxString&, const wxString& )>* aResolver );
|
||||
|
||||
/**
|
||||
* Read library from a source file. Must be in the format appropriate to the subclass, e.g.
|
||||
|
@ -63,15 +63,7 @@ public:
|
|||
* @param aFilePath Path to the file.
|
||||
* @throw IO_ERROR on read or parsing error.
|
||||
*/
|
||||
virtual void ReadFile( const std::string& aFilePath, REPORTER* aReporter ) = 0;
|
||||
|
||||
/**
|
||||
* Write library to a source file (e.g. in Spice format).
|
||||
*
|
||||
* @param aFilePath Path to the file.
|
||||
* @throw IO_ERROR on write error.
|
||||
*/
|
||||
virtual void WriteFile( const std::string& aFilePath ) = 0;
|
||||
virtual void ReadFile( const wxString& aFilePath, REPORTER* aReporter ) = 0;
|
||||
|
||||
SIM_MODEL* FindModel( const std::string& aModelName ) const;
|
||||
|
||||
|
@ -83,7 +75,7 @@ protected:
|
|||
std::vector<std::string> m_modelNames;
|
||||
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
|
||||
|
||||
std::function<std::string( const std::string&, const std::string& )>* m_pathResolver;
|
||||
std::function<wxString( const wxString&, const wxString& )>* m_pathResolver;
|
||||
|
||||
std::string m_filePath;
|
||||
|
||||
|
|
|
@ -29,10 +29,10 @@
|
|||
#include <lib_pin.h>
|
||||
|
||||
|
||||
void SIM_LIBRARY_KIBIS::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
|
||||
void SIM_LIBRARY_KIBIS::ReadFile( const wxString& aFilePath, REPORTER* aReporter )
|
||||
{
|
||||
SIM_LIBRARY::ReadFile( aFilePath, aReporter );
|
||||
m_kibis = KIBIS( aFilePath, m_reporter );
|
||||
m_kibis = KIBIS( aFilePath.ToStdString(), m_reporter );
|
||||
|
||||
if( !m_kibis.m_valid )
|
||||
{
|
||||
|
|
|
@ -38,10 +38,7 @@ public:
|
|||
static constexpr auto DIFF_FIELD = "Sim.Ibis.Diff";
|
||||
|
||||
// @copydoc SIM_LIBRARY::ReadFile()
|
||||
void ReadFile( const std::string& aFilePath, REPORTER* aReporter ) override;
|
||||
|
||||
// @copydoc SIM_LIBRARY::WriteFile()
|
||||
void WriteFile( const std::string& aFilePath ) override{};
|
||||
void ReadFile( const wxString& aFilePath, REPORTER* aReporter ) override;
|
||||
|
||||
bool InitModel( SIM_MODEL_KIBIS& aModel, wxString aCompName );
|
||||
bool isPinDiff( const std::string& aComp, const std::string& aPinNumber ) const;
|
||||
|
|
|
@ -33,14 +33,9 @@ SIM_LIBRARY_SPICE::SIM_LIBRARY_SPICE() :
|
|||
}
|
||||
|
||||
|
||||
void SIM_LIBRARY_SPICE::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
|
||||
void SIM_LIBRARY_SPICE::ReadFile( const wxString& aFilePath, REPORTER* aReporter )
|
||||
{
|
||||
SIM_LIBRARY::ReadFile( aFilePath, aReporter );
|
||||
m_spiceLibraryParser->ReadFile( aFilePath, aReporter );
|
||||
}
|
||||
|
||||
|
||||
void SIM_LIBRARY_SPICE::WriteFile( const std::string& aFilePath )
|
||||
{
|
||||
// Not implemented yet.
|
||||
}
|
||||
|
|
|
@ -37,10 +37,7 @@ public:
|
|||
SIM_LIBRARY_SPICE();
|
||||
|
||||
// @copydoc SIM_LIBRARY::ReadFile()
|
||||
void ReadFile( const std::string& aFilePath, REPORTER* aReporter ) override;
|
||||
|
||||
// @copydoc SIM_LIBRARY::WriteFile()
|
||||
void WriteFile( const std::string& aFilePath ) override;
|
||||
void ReadFile( const wxString& aFilePath, REPORTER* aReporter ) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<SPICE_LIBRARY_PARSER> m_spiceLibraryParser;
|
||||
|
|
|
@ -57,17 +57,16 @@ namespace SIM_LIBRARY_SPICE_PARSER
|
|||
};
|
||||
|
||||
|
||||
void SPICE_LIBRARY_PARSER::readElement( const std::string &aFilePath, REPORTER& aReporter )
|
||||
void SPICE_LIBRARY_PARSER::parseFile( const wxString &aFilePath, REPORTER& aReporter )
|
||||
{
|
||||
try
|
||||
{
|
||||
tao::pegtl::file_input in( aFilePath );
|
||||
std::unique_ptr<tao::pegtl::parse_tree::node> root =
|
||||
tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
|
||||
tao::pegtl::string_input<> in( SafeReadFile( aFilePath, wxS( "r" ) ).ToStdString(),
|
||||
aFilePath.ToStdString() );
|
||||
auto root = tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
|
||||
SIM_LIBRARY_SPICE_PARSER::librarySelector,
|
||||
tao::pegtl::nothing,
|
||||
SIM_LIBRARY_SPICE_PARSER::control>
|
||||
( in );
|
||||
SIM_LIBRARY_SPICE_PARSER::control> ( in );
|
||||
|
||||
for( const auto& node : root->children )
|
||||
{
|
||||
|
@ -88,14 +87,14 @@ void SPICE_LIBRARY_PARSER::readElement( const std::string &aFilePath, REPORTER&
|
|||
}
|
||||
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::dotInclude>() )
|
||||
{
|
||||
std::string lib = node->children.at( 0 )->string();
|
||||
wxString lib = node->children.at( 0 )->string();
|
||||
|
||||
try
|
||||
{
|
||||
if( m_library.m_pathResolver )
|
||||
lib = ( *m_library.m_pathResolver )( lib, aFilePath );
|
||||
|
||||
readElement( lib, aReporter );
|
||||
parseFile( lib, aReporter );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
|
@ -112,9 +111,9 @@ void SPICE_LIBRARY_PARSER::readElement( const std::string &aFilePath, REPORTER&
|
|||
}
|
||||
}
|
||||
}
|
||||
catch( const std::filesystem::filesystem_error& e )
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
aReporter.Report( e.what(), RPT_SEVERITY_ERROR );
|
||||
aReporter.Report( e.What(), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
catch( const tao::pegtl::parse_error& e )
|
||||
{
|
||||
|
@ -123,21 +122,21 @@ void SPICE_LIBRARY_PARSER::readElement( const std::string &aFilePath, REPORTER&
|
|||
}
|
||||
|
||||
|
||||
void SPICE_LIBRARY_PARSER::ReadFile( const std::string& aFilePath, REPORTER* aReporter )
|
||||
void SPICE_LIBRARY_PARSER::ReadFile( const wxString& aFilePath, REPORTER* aReporter )
|
||||
{
|
||||
m_library.m_models.clear();
|
||||
m_library.m_modelNames.clear();
|
||||
|
||||
if( aReporter )
|
||||
{
|
||||
readElement( aFilePath, *aReporter );
|
||||
parseFile( aFilePath, *aReporter );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString msg;
|
||||
WX_STRING_REPORTER reporter( &msg );
|
||||
|
||||
readElement( aFilePath, reporter );
|
||||
parseFile( aFilePath, reporter );
|
||||
|
||||
if( reporter.HasMessage() )
|
||||
THROW_IO_ERROR( msg );
|
||||
|
|
|
@ -40,10 +40,10 @@ public:
|
|||
virtual ~SPICE_LIBRARY_PARSER()
|
||||
{};
|
||||
|
||||
virtual void ReadFile( const std::string& aFilePath, REPORTER* aReporter );
|
||||
virtual void ReadFile( const wxString& aFilePath, REPORTER* aReporter );
|
||||
|
||||
protected:
|
||||
void readElement( const std::string& aFilePath, REPORTER& aReporter );
|
||||
void parseFile( const wxString& aFilePath, REPORTER& aReporter );
|
||||
|
||||
private:
|
||||
SIM_LIBRARY_SPICE& m_library;
|
||||
|
|
|
@ -70,6 +70,18 @@ std::string
|
|||
StrPrintf( const char* format, ... );
|
||||
|
||||
|
||||
/**
|
||||
* Nominally opens a file and reads it into a string. But unlike other facilities, this handles
|
||||
* mis-encded Wine-written files on macOS.
|
||||
*
|
||||
* @param aFilePath
|
||||
* @param aReadType
|
||||
* @throw IO_ERROR if the file can't be opened
|
||||
* @return the file contents
|
||||
*/
|
||||
wxString SafeReadFile( const wxString& aFilePath, const wxString& aReadType );
|
||||
|
||||
|
||||
#define LINE_READER_LINE_DEFAULT_MAX 1000000
|
||||
#define LINE_READER_LINE_INITIAL_SIZE 5000
|
||||
|
||||
|
|
Loading…
Reference in New Issue