40#include <wx/wfstream.h> 
   41#include <wx/zipstrm.h> 
   42#include <wx/stdstream.h> 
   58static bool FindBoardInStream( 
const wxString& aName, wxInputStream& aStream, nlohmann::json& aOut,
 
   61    if( aName.Lower().EndsWith( wxS( 
".json" ) ) )
 
   63        wxStdInputStream sin( aStream );
 
   64        nlohmann::json   js = nlohmann::json::parse( sin, 
nullptr, 
false );
 
   66        if( js.is_discarded() )
 
   80    else if( aName.Lower().EndsWith( wxS( 
".zip" ) ) )
 
   82        std::shared_ptr<wxZipEntry> entry;
 
   83        wxZipInputStream            
zip( aStream );
 
   88        while( entry.reset( 
zip.GetNextEntry() ), entry.get() != NULL )
 
   90            wxString 
name = entry->GetName();
 
 
  108        wxFFileInputStream in( aFileName );
 
  114    catch( nlohmann::json::exception& )
 
  117    catch( std::exception& )
 
 
  138                                  const std::map<std::string, UTF8>* aProperties, 
PROJECT* aProject )
 
  149        m_board->SetFileName( aFileName );
 
  163        wxFFileInputStream in( aFileName );
 
  170                    wxString::Format( 
_( 
"Unable to find a valid board in '%s'" ), aFileName ) );
 
  175        const int innerStart = 21;
 
  176        const int innerEnd = 52;
 
  178        int                              maxLayer = innerStart;
 
  179        std::map<PCB_LAYER_ID, wxString> layerNames;
 
  181        for( 
const wxString& layerLine : pcbDoc.
layers )
 
  183            wxArrayString parts = wxSplit( layerLine, 
'~', 
'\0' );
 
  184            int           layerId = wxAtoi( parts[0] );
 
  185            wxString      layerName = parts[1];
 
  186            wxString      layerColor = parts[2];
 
  187            wxString      visible = parts[3];
 
  188            wxString      active = parts[4];
 
  189            bool          enabled = parts[5] != wxS( 
"false" );
 
  191            if( layerId >= innerStart && layerId <= innerEnd && enabled )
 
  192                maxLayer = layerId + 1;
 
  194            layerNames[parser.
LayerToKi( parts[0] )] = layerName;
 
  197        m_board->SetCopperLayerCount( 2 + maxLayer - innerStart );
 
  199        for( 
auto& [klayer, 
name] : layerNames )
 
  207            std::map<wxString, nlohmann::json>& rules = *pcbDoc.
DRCRULE;
 
  209            if( 
auto defRules = 
get_opt( rules, 
"Default" ) )
 
  213                key = wxS( 
"trackWidth" );
 
  214                if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
 
  216                    double val = parser.
ScaleSize( defRules->at( key ) );
 
  217                    defNetclass->SetTrackWidth( val );
 
  220                key = wxS( 
"clearance" );
 
  221                if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
 
  223                    double val = parser.
ScaleSize( defRules->at( key ) );
 
  224                    defNetclass->SetClearance( val );
 
  227                key = wxS( 
"viaHoleD" );
 
  228                if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
 
  230                    double val = parser.
ScaleSize( defRules->at( key ) );
 
  232                    defNetclass->SetViaDrill( val );
 
  235                key = wxS( 
"viaHoleDiameter" ); 
 
  236                if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
 
  238                    double val = parser.
ScaleSize( defRules->at( key ) );
 
  239                    defNetclass->SetViaDiameter( val );
 
  248        BOX2I     outlineBbox = 
m_board->ComputeBoundingBox( 
true );
 
  257        offset.
x = 
KiROUND( offset.
x / alignGrid ) * alignGrid;
 
  258        offset.
y = 
KiROUND( offset.
y / alignGrid ) * alignGrid;
 
  265    catch( nlohmann::json::exception& e )
 
  267        THROW_IO_ERROR( wxString::Format( 
_( 
"Error loading board '%s': %s" ), aFileName, e.what() ) );
 
  269    catch( std::exception& e )
 
  271        THROW_IO_ERROR( wxString::Format( 
_( 
"Error loading board '%s': %s" ), aFileName, e.what() ) );
 
 
  283                                         const wxString& aLibraryPath, 
bool aBestEfforts,
 
  284                                         const std::map<std::string, UTF8>* aProperties )
 
  288        wxFFileInputStream in( aLibraryPath );
 
  294            THROW_IO_ERROR( wxString::Format( 
_( 
"Unable to find valid footprints in '%s'" ),
 
  301            for( wxString shap : doc.
shape )
 
  303                shap.Replace( wxS( 
"#@$" ), 
"\n" );
 
  304                wxArrayString parts = wxSplit( shap, 
'\n', 
'\0' );
 
  306                if( parts.size() < 1 )
 
  309                wxArrayString paramsRoot = wxSplit( parts[0], 
'~', 
'\0' );
 
  311                if( paramsRoot.size() < 1 )
 
  314                wxString rootType = paramsRoot[0];
 
  316                if( rootType == wxS( 
"LIB" ) )
 
  318                    if( paramsRoot.size() < 4 )
 
  321                    wxString packageName = wxString::Format( wxS( 
"Unknown_%s_%s" ), paramsRoot[1],
 
  324                    wxArrayString paramParts = wxSplit( paramsRoot[3], 
'`', 
'\0' );
 
  326                    std::map<wxString, wxString> paramMap;
 
  328                    for( 
int i = 1; i < paramParts.size(); i += 2 )
 
  330                        wxString key = paramParts[i - 1];
 
  331                        wxString value = paramParts[i];
 
  333                        if( key == wxS( 
"package" ) )
 
  336                        paramMap[key] = value;
 
  339                    aFootprintNames.Add( packageName );
 
  347            wxString packageName = wxString::Format( wxS( 
"Unknown_%s" ),
 
  348                                                     pcbDoc.
uuid.value_or( wxS( 
"Unknown" ) ) );
 
  350            std::optional<std::map<wxString, wxString>> c_para;
 
  358                packageName = 
get_def( *c_para, wxS( 
"package" ), packageName );
 
  360            aFootprintNames.Add( packageName );
 
  363    catch( nlohmann::json::exception& e )
 
  365        THROW_IO_ERROR( wxString::Format( 
_( 
"Error enumerating footprints in library '%s': %s" ),
 
  366                                          aLibraryPath, e.what() ) );
 
  368    catch( std::exception& e )
 
  370        THROW_IO_ERROR( wxString::Format( 
_( 
"Error enumerating footprints in library '%s': %s" ),
 
  371                                          aLibraryPath, e.what() ) );
 
 
  377                                          const wxString& aFootprintName, 
bool aKeepUUID,
 
  378                                          const std::map<std::string, UTF8>* aProperties )
 
  388        wxFFileInputStream in( aLibraryPath );
 
  394            THROW_IO_ERROR( wxString::Format( 
_( 
"Unable to find valid footprints in '%s'" ),
 
  401            for( wxString shap : doc.
shape )
 
  403                if( !shap.Contains( wxS( 
"LIB" ) ) )
 
  406                shap.Replace( wxS( 
"#@$" ), 
"\n" );
 
  407                wxArrayString parts = wxSplit( shap, 
'\n', 
'\0' );
 
  409                if( parts.size() < 1 )
 
  412                wxArrayString paramsRoot = wxSplit( parts[0], 
'~', 
'\0' );
 
  414                if( paramsRoot.size() < 1 )
 
  417                wxString rootType = paramsRoot[0];
 
  419                if( rootType == wxS( 
"LIB" ) )
 
  421                    if( paramsRoot.size() < 4 )
 
  425                                     parser.
Convert( paramsRoot[2] ) );
 
  427                    wxString packageName = wxString::Format( wxS( 
"Unknown_%s_%s" ), paramsRoot[1],
 
  430                    wxArrayString paramParts = wxSplit( paramsRoot[3], 
'`', 
'\0' );
 
  432                    std::map<wxString, wxString> paramMap;
 
  434                    for( 
int i = 1; i < paramParts.size(); i += 2 )
 
  436                        wxString key = paramParts[i - 1];
 
  437                        wxString value = paramParts[i];
 
  439                        if( key == wxS( 
"package" ) )
 
  442                        paramMap[key] = value;
 
  446                    if( !paramsRoot[4].IsEmpty() )
 
  451                    if( !paramsRoot[7].IsEmpty() )
 
  452                        layer = parser.
Convert( paramsRoot[7] );
 
  454                    if( packageName == aFootprintName )
 
  483            wxString packageName = wxString::Format( wxS( 
"Unknown_%s" ),
 
  484                                                     pcbDoc.
uuid.value_or( wxS( 
"Unknown" ) ) );
 
  486            std::optional<std::map<wxString, wxString>> c_para;
 
  495                packageName = 
get_def( *c_para, wxS( 
"package" ), packageName );
 
  497                if( packageName != aFootprintName )
 
  522    catch( nlohmann::json::exception& e )
 
  524        THROW_IO_ERROR( wxString::Format( 
_( 
"Error reading footprint '%s' from library '%s': %s" ),
 
  525                                          aFootprintName, aLibraryPath, e.what() ) );
 
  527    catch( std::exception& e )
 
  529        THROW_IO_ERROR( wxString::Format( 
_( 
"Error reading footprint '%s' from library '%s': %s" ),
 
  530                                          aFootprintName, aLibraryPath, e.what() ) );
 
 
  539    std::vector<FOOTPRINT*> 
result;
 
 
constexpr EDA_IU_SCALE pcbIUScale
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
Container for design settings for a BOARD object.
 
std::shared_ptr< NET_SETTINGS > m_NetSettings
 
void SetAuxOrigin(const VECTOR2I &aOrigin)
 
Information pertinent to a Pcbnew printed circuit board.
 
constexpr const Vec GetCenter() const
 
static double Convert(const wxString &aValue)
 
virtual void SetVisible(bool aVisible)
 
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
 
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
 
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
 
Describe the page size and margins of a paper page on which to eventually print or plot.
 
double GetHeightMils() const
 
double GetWidthMils() const
 
FOOTPRINT * ParseFootprint(const VECTOR2D &aOrigin, const EDA_ANGLE &aOrientation, int aLayer, BOARD *aParent, std::map< wxString, wxString > aParams, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString aShapes)
 
double ScaleSize(double aValue) override
 
void ParseBoard(BOARD *aBoard, const VECTOR2D &aOrigin, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString aShapes)
 
PCB_LAYER_ID LayerToKi(const wxString &aLayer)
 
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
 
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
 
FOOTPRINT * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
 
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
 
std::map< wxString, std::unique_ptr< FOOTPRINT > > m_loadedFootprints
 
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
 
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
 
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
 
bool CanReadFootprint(const wxString &aFileName) const override
Checks if this PCB_IO can read a footprint from specified file or directory.
 
BOARD * m_board
The board BOARD being worked on, no ownership here.
 
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
 
PCB_IO(const wxString &aName)
 
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
 
virtual void SetPosition(const VECTOR2I &aPos) override
 
Container for project specific data.
 
static REPORTER & GetInstance()
 
static void SetReporter(REPORTER *aReporter)
Set the reporter to use for reporting font substitution warnings.
 
static constexpr EDA_ANGLE ANGLE_0
 
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
 
This file contains miscellaneous commonly used macros and functions.
 
wxString get_def(const std::map< wxString, wxString > &aMap, const char *aKey, const char *aDefval="")
 
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
 
static bool FindBoardInStream(const wxString &aName, wxInputStream &aStream, nlohmann::json &aOut, EASYEDA::DOCUMENT &aDoc)
 
std::optional< std::map< wxString, nlohmann::json > > DRCRULE
 
std::optional< std::map< wxString, wxString > > c_para
 
std::vector< wxString > layers
 
std::optional< wxString > uuid
 
std::optional< std::map< wxString, wxString > > c_para
 
wxString result
Test unit parsing edge cases and error handling.
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D