37#include <wx/zipstrm.h> 
   38#include <wx/wfstream.h> 
   39#include <wx/mstream.h> 
   40#include <wx/txtstrm.h> 
   45    wxString shortenedName = aProjectName;
 
   46    shortenedName.Replace( wxS( 
"ProProject_" ), wxS( 
"" ) );
 
   47    shortenedName.Replace( wxS( 
"ProDocument_" ), wxS( 
"" ) );
 
   48    shortenedName = shortenedName.substr( 0, 10 );
 
 
   59    wxString key = !aLibName.empty() ? ( aLibName + 
':' + libReference ) : libReference;
 
   62    libId.
Parse( key, 
true );
 
 
   68std::vector<IMPORT_PROJECT_DESC>
 
   71    std::vector<IMPORT_PROJECT_DESC> 
result;
 
   73    std::map<wxString, EASYEDAPRO::PRJ_SCHEMATIC> prjSchematics = aProject.at( 
"schematics" );
 
   74    std::map<wxString, EASYEDAPRO::PRJ_BOARD>     prjBoards = aProject.at( 
"boards" );
 
   75    std::map<wxString, wxString>                  prjPcbNames = aProject.at( 
"pcbs" );
 
   77    for( 
const auto& [prjName, board] : prjBoards )
 
   81        desc.
PCBId = board.pcb;
 
   84        auto pcbNameIt = prjPcbNames.find( desc.
PCBId );
 
   85        if( pcbNameIt != prjPcbNames.end() )
 
   87            desc.
PCBName = pcbNameIt->second;
 
   90                desc.
PCBName = pcbNameIt->first;
 
   92            prjPcbNames.erase( pcbNameIt );
 
   95        auto schIt = prjSchematics.find( desc.
SchematicId );
 
   96        if( schIt != prjSchematics.end() )
 
  103            prjSchematics.erase( schIt );
 
  106        result.emplace_back( desc );
 
  111        for( 
const auto& [pcbId, pcbName] : prjPcbNames )
 
  120            result.emplace_back( desc );
 
  126        for( 
const auto& [schId, schData] : prjSchematics )
 
  135            result.emplace_back( desc );
 
 
  144                                         const std::set<wxString>& aFileNames )
 
  146    std::shared_ptr<wxZipEntry> entry;
 
  147    wxFFileInputStream          in( aZipFileName );
 
  148    wxZipInputStream            
zip( in );
 
  150    while( entry.reset( 
zip.GetNextEntry() ), entry.get() != NULL )
 
  152        wxString 
name = entry->GetName();
 
  156            if( aFileNames.find( 
name ) != aFileNames.end() )
 
  158                wxMemoryOutputStream memos;
 
  160                wxStreamBuffer* buf = memos.GetOutputStreamBuffer();
 
  163                        wxString::FromUTF8( (
char*) buf->GetBufferStart(), buf->GetBufferSize() );
 
  165                return nlohmann::json::parse( str );
 
  168        catch( nlohmann::json::exception& e )
 
  171                    wxString::Format( 
_( 
"JSON error reading '%s': %s" ), 
name, e.what() ) );
 
  173        catch( std::exception& e )
 
  179    return nlohmann::json{};
 
 
  185    static const std::set<wxString> c_files = { wxS( 
"project.json" ), wxS( 
"device.json" ),
 
  186                                                wxS( 
"footprint.json" ), wxS( 
"symbol.json" ) };
 
  188    nlohmann::json j = 
FindJsonFile( aZipFileName, c_files );
 
  194            _( 
"'%s' does not appear to be a valid EasyEDA (JLCEDA) Pro " 
  195               "project or library file. Cannot find project.json or device.json." ),
 
 
  201        const wxString&                                                         aFileName,
 
  202        std::function<
bool( 
const wxString&, 
const wxString&, wxInputStream& )> aCallback )
 
  204    std::shared_ptr<wxZipEntry> entry;
 
  205    wxFFileInputStream          in( aFileName );
 
  206    wxZipInputStream            
zip( in );
 
  210        THROW_IO_ERROR( wxString::Format( 
_( 
"Cannot read ZIP archive '%s'" ), aFileName ) );
 
  213    while( entry.reset( 
zip.GetNextEntry() ), entry.get() != NULL )
 
  215        wxString 
name = entry->GetName();
 
  216        wxString baseName = 
name.AfterLast( 
'\\' ).AfterLast( 
'/' ).BeforeFirst( 
'.' );
 
  220            if( aCallback( 
name, baseName, 
zip ) )
 
  223        catch( nlohmann::json::exception& e )
 
  226                    wxString::Format( 
_( 
"JSON error reading '%s': %s" ), 
name, e.what() ) );
 
  228        catch( std::exception& e )
 
 
  237                                                        const wxString& aSource )
 
  239    wxTextInputStream txt( aInput, wxS( 
" " ), wxConvUTF8 );
 
  243    std::vector<nlohmann::json> lines;
 
  244    while( aInput.CanRead() )
 
  248            wxString line = txt.ReadLine();
 
  250            if( !line.IsEmpty() )
 
  252                nlohmann::json js = nlohmann::json::parse( line );
 
  253                lines.emplace_back( js );
 
  257                lines.emplace_back( nlohmann::json() );
 
  260        catch( nlohmann::json::exception& e )
 
  262            wxLogWarning( wxString::Format( 
_( 
"Cannot parse JSON line %d in '%s': %s" ),
 
  263                                            currentLine, aSource, e.what() ) );
 
 
  273std::vector<std::vector<nlohmann::json>>
 
  276    wxTextInputStream txt( aInput, wxS( 
" " ), wxConvUTF8 );
 
  280    std::vector<std::vector<nlohmann::json>> lineBlocks;
 
  281    lineBlocks.emplace_back();
 
  283    while( aInput.CanRead() )
 
  287            wxString line = txt.ReadLine();
 
  289            if( !line.IsEmpty() )
 
  291                nlohmann::json js = nlohmann::json::parse( line );
 
  292                lineBlocks.back().emplace_back( js );
 
  296                lineBlocks.emplace_back();
 
  299        catch( nlohmann::json::exception& e )
 
  301            wxLogWarning( wxString::Format( 
_( 
"Cannot parse JSON line %d in '%s': %s" ),
 
  302                                            currentLine, aSource, e.what() ) );
 
 
  312std::map<wxString, wxString>
 
  315    std::map<wxString, wxString> stringMap;
 
  317    for( 
auto& [key, value] : aInput )
 
  319        if( value.is_string() )
 
  320            stringMap[key] = value.get<wxString>();
 
  321        else if( value.is_number() )
 
  322            stringMap[key] = wxString::FromCDouble( value.get<
double>() );
 
 
A logical library item identifier and consists of various portions much like a URI.
 
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
 
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
 
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
 
LIB_ID ToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
 
void IterateZipFiles(const wxString &aFileName, std::function< bool(const wxString &, const wxString &, wxInputStream &)> aCallback)
 
std::vector< nlohmann::json > ParseJsonLines(wxInputStream &aInput, const wxString &aSource)
 
std::vector< std::vector< nlohmann::json > > ParseJsonLinesWithSeparation(wxInputStream &aInput, const wxString &aSource)
Multiple document types (e.g.
 
nlohmann::json FindJsonFile(const wxString &aZipFileName, const std::set< wxString > &aFileNames)
 
std::vector< IMPORT_PROJECT_DESC > ProjectToSelectorDialog(const nlohmann::json &aProject, bool aPcbOnly=false, bool aSchOnly=false)
 
nlohmann::json ReadProjectOrDeviceFile(const wxString &aZipFileName)
 
wxString ShortenLibName(wxString aProjectName)
 
std::map< wxString, wxString > AnyMapToStringMap(const std::map< wxString, nlohmann::json > &aInput)
 
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
 
Describes how non-KiCad boards and schematics should be imported as KiCad projects.
 
wxString result
Test unit parsing edge cases and error handling.