From 4fcba4d61912a13db57c4d1fd4b240c8be55e17c Mon Sep 17 00:00:00 2001 From: Roberto Fernandez Bautista Date: Sat, 18 Jul 2020 10:04:22 +0100 Subject: [PATCH] CADSTAR PCB Archive Importer: Parse HEADER and ASSIGNMENTS->CODEDEFS sections --- .../cadstar_common.cpp | 95 +- .../cadstar2kicadpcb_plugin/cadstar_common.h | 47 +- .../cadstar2kicadpcb_plugin/cadstar_pcb.cpp | 32 +- pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.h | 3 +- .../cadstar_pcb_archive_parser.cpp | 869 ++++++++++++++++-- .../cadstar_pcb_archive_parser.h | 456 ++++++++- 6 files changed, 1367 insertions(+), 135 deletions(-) diff --git a/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.cpp b/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.cpp index 2dfe9453ad..347997688e 100644 --- a/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.cpp +++ b/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.cpp @@ -25,6 +25,40 @@ #include + +void CADSTAR_COMMON::EVALUE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "E" ) ); + + if( ( !CADSTAR_COMMON::GetAttributeID( aNode, 0 ).ToLong( &Base ) ) + || ( !CADSTAR_COMMON::GetAttributeID( aNode, 1 ).ToLong( &Exponent ) ) ) + THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ), + wxString::Format( + "%s->%s", aNode->GetParent()->GetName(), aNode->GetParent()->GetName() ) ); +} + + +double CADSTAR_COMMON::EVALUE::GetDouble() +{ + return Base * std::pow( 10.0, Exponent ); +} + + +void CADSTAR_COMMON::InsertAttributeAtEnd( XNODE* aNode, wxString aValue ) +{ + wxString result, paramName = "attr0"; + int i = 0; + + while( aNode->GetAttribute( paramName, &result ) ) + { + paramName = wxT( "attr" ); + paramName << i++; + } + + aNode->AddAttribute( paramName, aValue ); +} + + XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aType ) { KEYWORD emptyKeywords[1] = {}; @@ -80,6 +114,8 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy if( iNode ) { + //we will add it as attribute as well as child node + InsertAttributeAtEnd( iNode, str ); iNode->AddChild( cNode ); } else if( !cadstarFileCheckDone ) @@ -99,16 +135,7 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy if( !str.IsEmpty() ) { - wxString result, paramName = "attr0"; - int i = 0; - - while( iNode->GetAttribute( paramName, &result ) ) - { - paramName = wxT( "attr" ); - paramName << i++; - } - - iNode->AddAttribute( paramName, str ); + InsertAttributeAtEnd( iNode, str ); } } else @@ -130,6 +157,7 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy } else { + //no data? THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) ); } @@ -138,15 +166,54 @@ XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aTy wxString CADSTAR_COMMON::GetAttributeID( XNODE* aNode, unsigned int aID ) { - wxString attrName = "attr"; + wxString attrName, retVal; + attrName = "attr"; attrName << aID; - return aNode->GetAttribute( attrName, wxEmptyString ); + + if( !aNode->GetAttribute( attrName, &retVal ) ) + THROW_MISSING_PARAMETER_IO_ERROR( std::to_string( aID ), aNode->GetName() ); + + return retVal; } -void CADSTAR_COMMON::CheckNoChildNodes( XNODE* aNode, wxString aLocation ) + +long CADSTAR_COMMON::GetAttributeIDLong( XNODE* aNode, unsigned int aID ) +{ + long retVal; + + if( !CADSTAR_COMMON::GetAttributeID( aNode, aID ).ToLong( &retVal ) ) + THROW_PARSING_IO_ERROR( std::to_string( aID ), aNode->GetName() ); + + return retVal; +} + + +void CADSTAR_COMMON::CheckNoChildNodes( XNODE* aNode ) { if( aNode->GetChildren() ) { - THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aLocation ); + THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() ); + } +} + + +void CADSTAR_COMMON::CheckNoNextNodes( XNODE* aNode ) +{ + if( aNode->GetNext() ) + { + THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() ); + } +} + + +void CADSTAR_COMMON::ParseChildEValue( XNODE* aNode, CADSTAR_COMMON::EVALUE& aValueToParse ) +{ + if( aNode->GetChildren()->GetName() == wxT( "E" ) ) + { + aValueToParse.Parse( aNode->GetChildren() ); + } + else + { + THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() ); } } diff --git a/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.h b/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.h index 3f4f3e66c3..3ef98565f8 100644 --- a/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.h +++ b/pcbnew/cadstar2kicadpcb_plugin/cadstar_common.h @@ -60,6 +60,20 @@ enum class FILE_TYPE }; +/** + * @brief Represents a floating value in E notation + */ +struct EVALUE +{ + long Base = 0; + long Exponent = 0; + + void Parse( XNODE* aNode ); + double GetDouble(); +}; + +extern void InsertAttributeAtEnd( XNODE* aNode, wxString aValue ); + /** * @brief Reads a CADSTAR Archive file (S-parameter format) * @param aFileName @@ -72,20 +86,51 @@ enum class FILE_TYPE extern XNODE* LoadArchiveFile( const wxString& aFileName, FILE_TYPE aType = FILE_TYPE::PCB_ARCHIVE ); + /** * @brief * @param aNode * @param aID * @return returns the value of attribute "attrX" in aNode where 'X' is aID + * @throws IO_ERROR if attribute does not exist */ extern wxString GetAttributeID( XNODE* aNode, unsigned int aID ); + +/** + * @brief + * @param aNode + * @param aID + * @return returns the value of attribute "attrX" in aNode where 'X' is aID + * @throws IO_ERROR if attribute does not exist + */ +extern long GetAttributeIDLong( XNODE* aNode, unsigned int aID ); + + /** * @brief * @param aNode * @throw IO_ERROR if a child node was found */ -extern void CheckNoChildNodes( XNODE* aNode, wxString aLocation ); +extern void CheckNoChildNodes( XNODE* aNode ); + + +/** + * @brief + * @param aNode + * @throw IO_ERROR if a node adjacent to aNode was found + */ +extern void CheckNoNextNodes( XNODE* aNode ); + + +/** + * @brief + * @param aNode with a child node containing an EVALUE + * @param aValueToParse + * @throw IO_ERROR if unable to parse or node is not an EVALUE +*/ +extern void ParseChildEValue( XNODE* aNode, EVALUE& aValueToParse ); + } // namespace CADSTAR_COMMON diff --git a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.cpp b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.cpp index 148709b138..051e900453 100644 --- a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.cpp +++ b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.cpp @@ -37,20 +37,19 @@ void CADSTAR_PCB::Load( CPA_FILE* aCPAfile ) void CADSTAR_PCB::loadBoardStackup( CPA_FILE* aCPAfile ) { - std::map& cpaLayers = aCPAfile->Assignments.Layerdefs.Layers; - std::map& cpaMaterials = - aCPAfile->Assignments.Layerdefs.Materials; - std::vector& cpaLayerStack = aCPAfile->Assignments.Layerdefs.LayerStack; - unsigned numElectricalAndPowerLayers = 0; - BOARD_DESIGN_SETTINGS& designSettings = mBoard->GetDesignSettings(); - BOARD_STACKUP& stackup = designSettings.GetStackupDescriptor(); - int noOfKiCadStackupLayers = 0; - int lastElectricalLayerIndex = 0; - int dielectricSublayer = 0; - int numDielectricLayers = 0; - bool prevWasDielectric = false; - BOARD_STACKUP_ITEM* tempKiCadLayer; - std::vector layerIDs; + std::map& cpaLayers = aCPAfile->Assignments.Layerdefs.Layers; + std::map& cpaMaterials = aCPAfile->Assignments.Layerdefs.Materials; + std::vector& cpaLayerStack = aCPAfile->Assignments.Layerdefs.LayerStack; + unsigned numElectricalAndPowerLayers = 0; + BOARD_DESIGN_SETTINGS& designSettings = mBoard->GetDesignSettings(); + BOARD_STACKUP& stackup = designSettings.GetStackupDescriptor(); + int noOfKiCadStackupLayers = 0; + int lastElectricalLayerIndex = 0; + int dielectricSublayer = 0; + int numDielectricLayers = 0; + bool prevWasDielectric = false; + BOARD_STACKUP_ITEM* tempKiCadLayer; + std::vector layerIDs; //Remove all layers except required ones stackup.RemoveAll(); @@ -207,9 +206,7 @@ void CADSTAR_PCB::loadBoardStackup( CPA_FILE* aCPAfile ) //TODO add Resistivity when KiCad supports it } - int unitMultiplier = 10; //assume CPA_FILE uses HUNDREDTH MICRON as its unit - //TODO: read units from CPA_FILE header and change unitMultiplier - // Also, add unitMultiplier somewhere in CPA_FILE + int unitMultiplier = aCPAfile->KiCadUnitMultiplier; tempKiCadLayer->SetThickness( curLayer.Thickness * unitMultiplier, dielectricSublayer ); wxASSERT( layerTypeName != wxEmptyString ); @@ -234,6 +231,7 @@ void CADSTAR_PCB::loadBoardStackup( CPA_FILE* aCPAfile ) tempKiCadLayer->GetBrdLayerId(), tempKiCadLayer->GetLayerName() ) ); //TODO set layer names for other CADSTAR layers when KiCad supports custom //layer names on non-copper layers + mCopperLayers.insert( std::make_pair( curLayer.PhysicalLayer, curLayer.ID ) ); } //TODO map kicad layer to CADSTAR layer in mLayermap } diff --git a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.h b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.h index a8ace12202..c854fe46e6 100644 --- a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.h +++ b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.h @@ -45,7 +45,8 @@ public: private: BOARD* mBoard; - std::map mLayermap; + std::map mLayermap; // mCopperLayers; void loadBoardStackup( CPA_FILE* aCPAfile ); PCB_LAYER_ID getKiCadCopperLayerID( unsigned int aLayerNum ); }; diff --git a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.cpp b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.cpp index 0341d7eb64..28dd23c714 100644 --- a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.cpp +++ b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.cpp @@ -34,6 +34,26 @@ void CPA_FILE::Parse() XNODE* tempNode = fileRootNode->GetChildren(); + for( ; tempNode && ( tempNode->GetName() != wxT( "HEADER" ) ); tempNode = tempNode->GetNext() ) + ; + + if( !tempNode ) + THROW_MISSING_NODE_IO_ERROR( wxT( "HEADER" ), wxT( "CADSTARPCB" ) ); + + //TODO try.. catch + throw again with more detailed error information + Header.Parse( tempNode ); + + switch( Header.Resolution ) + { + case CPA_RESOLUTION::HUNDREDTH_MICRON: + KiCadUnitMultiplier = 10; + break; + + default: + wxASSERT_MSG( true, wxT( "Unknown File Resolution" ) ); + break; + } + for( ; tempNode && ( tempNode->GetName() != wxT( "ASSIGNMENTS" ) ); tempNode = tempNode->GetNext() ) ; @@ -43,14 +63,19 @@ void CPA_FILE::Parse() tempNode = tempNode->GetChildren(); - for( ; tempNode && ( tempNode->GetName() != wxT( "LAYERDEFS" ) ); - tempNode = tempNode->GetNext() ) - ; - if( !tempNode ) THROW_MISSING_NODE_IO_ERROR( wxT( "LAYERDEFS" ), wxT( "ASSIGNMENTS" ) ); - Assignments.Layerdefs.Parse( tempNode ); + for( ; tempNode; tempNode = tempNode->GetNext() ) + { + if( tempNode->GetName() == wxT( "LAYERDEFS" ) ) + //TODO try.. catch + throw again with more detailed error information + Assignments.Layerdefs.Parse( tempNode ); + else if( tempNode->GetName() == wxT( "CODEDEFS" ) ) + Assignments.Codedefs.Parse( tempNode ); + //TODO parse technology, grids,etc + } + //Todo - This is just for testing. Remove this block & delete fileRootNode. { @@ -64,57 +89,51 @@ void CPA_FILE::Parse() //TODO need to parse everything else! } + void CPA_LAYERDEFS::Parse( XNODE* aNode ) { wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) ); - XNODE * iNode, *cNode; + wxXmlAttribute* xmlAttribute = NULL; - iNode = aNode->GetChildren(); + XNODE* cNode = aNode->GetChildren(); - if( !iNode ) + if( !cNode ) THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) ); - for( ; iNode; iNode = iNode->GetNext() ) + for( ; cNode; cNode = cNode->GetNext() ) { - wxString nodeName = iNode->GetName(); + wxString nodeName = cNode->GetName(); if( nodeName == wxT( "LAYERSTACK" ) ) { - xmlAttribute = iNode->GetAttributes(); + xmlAttribute = cNode->GetAttributes(); for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() ) { LayerStack.push_back( xmlAttribute->GetValue() ); } - if( cNode = iNode->GetChildren() ) //Shouldn't have any children - { - THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), nodeName ); - } + CADSTAR_COMMON::CheckNoChildNodes( cNode ); } else if( nodeName == wxT( "MATERIAL" ) ) { CPA_MATERIAL material; - material.Parse( iNode ); + //TODO try.. catch + throw again with more detailed error information + material.Parse( cNode ); Materials.insert( std::make_pair( material.ID, material ) ); } else if( nodeName == wxT( "LAYER" ) ) { CPA_LAYER layer; - layer.Parse( iNode ); + //TODO try.. catch + throw again with more detailed error information + layer.Parse( cNode ); Layers.insert( std::make_pair( layer.ID, layer ) ); } else if( nodeName == wxT( "SWAPPAIR" ) ) { - wxString layerId = CADSTAR_COMMON::GetAttributeID( iNode, 0 ); - wxString swapLayerId = CADSTAR_COMMON::GetAttributeID( iNode, 1 ); - - if( layerId.IsEmpty() || swapLayerId.IsEmpty() ) - { - THROW_MISSING_PARAMETER_IO_ERROR( - wxT( "ID" ), wxString::Format( "SWAPPAIR %s,%s", layerId, swapLayerId ) ); - } + wxString layerId = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); + wxString swapLayerId = CADSTAR_COMMON::GetAttributeID( cNode, 1 ); Layers[layerId].SwapLayerID = swapLayerId; } @@ -126,39 +145,122 @@ void CPA_LAYERDEFS::Parse( XNODE* aNode ) } -void CPAParseEValue( XNODE* aNode, CPA_EVALUE& aValue, wxString location ) +void CPA_CODEDEFS::Parse( XNODE* aNode ) { - if( aNode->GetChildren()->GetName() == wxT( "E" ) ) + wxASSERT( aNode->GetName() != wxT( "CODEDEFS" ) ); + + XNODE* cNode = aNode->GetChildren(); + + for( ; cNode; cNode = cNode->GetNext() ) { - aValue.Parse( aNode->GetChildren() ); - } - else - { - THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location ); + wxString nodeName = cNode->GetName(); + + if( nodeName == wxT( "LINECODE" ) ) + { + CPA_LINECODE linecode; + //TODO try.. catch + throw again with more detailed error information + linecode.Parse( cNode ); + LineCodes.insert( std::make_pair( linecode.ID, linecode ) ); + } + else if( nodeName == wxT( "HATCHCODE" ) ) + { + CPA_HATCHCODE hatchcode; + //TODO try.. catch + throw again with more detailed error information + hatchcode.Parse( cNode ); + HatchCodes.insert( std::make_pair( hatchcode.ID, hatchcode ) ); + } + else if( nodeName == wxT( "TEXTCODE" ) ) + { + CPA_TEXTCODE textcode; + //TODO try.. catch + throw again with more detailed error information + textcode.Parse( cNode ); + TextCodes.insert( std::make_pair( textcode.ID, textcode ) ); + } + else if( nodeName == wxT( "ROUTECODE" ) ) + { + CPA_ROUTECODE routecode; + //TODO try.. catch + throw again with more detailed error information + routecode.Parse( cNode ); + RouteCodes.insert( std::make_pair( routecode.ID, routecode ) ); + } + else if( nodeName == wxT( "COPPERCODE" ) ) + { + CPA_COPPERCODE coppercode; + //TODO try.. catch + throw again with more detailed error information + coppercode.Parse( cNode ); + CopperCodes.insert( std::make_pair( coppercode.ID, coppercode ) ); + } + else if( nodeName == wxT( "SPACINGCODE" ) ) + { + CPA_SPACINGCODE spacingcode; + //TODO try.. catch + throw again with more detailed error information + spacingcode.Parse( cNode ); + SpacingCodes.push_back( spacingcode ); + } + else if( nodeName == wxT( "PADCODE" ) ) + { + CPA_PADCODE padcode; + //TODO try.. catch + throw again with more detailed error information + padcode.Parse( cNode ); + PadCodes.insert( std::make_pair( padcode.ID, padcode ) ); + } + else if( nodeName == wxT( "VIACODE" ) ) + { + CPA_VIACODE viacode; + //TODO try.. catch + throw again with more detailed error information + viacode.Parse( cNode ); + ViaCodes.insert( std::make_pair( viacode.ID, viacode ) ); + } + else if( nodeName == wxT( "LAYERPAIR" ) ) + { + CPA_LAYERPAIR layerpair; + //TODO try.. catch + throw again with more detailed error information + layerpair.Parse( cNode ); + LayerPairs.insert( std::make_pair( layerpair.ID, layerpair ) ); + } + else if( nodeName == wxT( "ATTRNAME" ) ) + { + CPA_ATTRNAME attrname; + //TODO try.. catch + throw again with more detailed error information + attrname.Parse( cNode ); + AttributeNames.insert( std::make_pair( attrname.ID, attrname ) ); + } + else if( nodeName == wxT( "NETCLASS" ) ) + { + CPA_NETCLASS netclass; + //TODO try.. catch + throw again with more detailed error information + netclass.Parse( cNode ); + NetClasses.insert( std::make_pair( netclass.ID, netclass ) ); + } + else if( nodeName == wxT( "SPCCLASSNAME" ) ) + { + CPA_SPCCLASSNAME spcclassname; + //TODO try.. catch + throw again with more detailed error information + spcclassname.Parse( cNode ); + SpacingClassNames.insert( std::make_pair( spcclassname.ID, spcclassname ) ); + } + else if( nodeName == wxT( "SPCCLASSSPACE" ) ) + { + CPA_SPCCLASSSPACE spcclassspace; + //TODO try.. catch + throw again with more detailed error information + spcclassspace.Parse( cNode ); + SpacingClasses.push_back( spcclassspace ); + } + else + { + THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() ); + } } } -void CPAParseNameAndID( XNODE* aNode, wxString& aName, wxString& aID ) -{ - aID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); - aName = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); - - if( aID.IsEmpty() ) - THROW_MISSING_PARAMETER_IO_ERROR( - wxT( "ID" ), wxString::Format( "%s %s", aNode->GetName(), aName ) ); - - if( aName.IsEmpty() ) - THROW_MISSING_PARAMETER_IO_ERROR( - wxT( "Name" ), wxString::Format( "%s %s", aNode->GetName(), aID ) ); -} - void CPA_MATERIAL::Parse( XNODE* aNode ) { wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) ); //Process Name & ID - CPAParseNameAndID( aNode, Name, ID ); + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); //Process Type wxString sType = CADSTAR_COMMON::GetAttributeID( aNode, 2 ); @@ -190,19 +292,21 @@ void CPA_MATERIAL::Parse( XNODE* aNode ) for( ; iNode; iNode = iNode->GetNext() ) { wxString nodeName = iNode->GetName(); - wxString location = wxString::Format( "MATERIAL %s->%s", Name, nodeName ); if( nodeName == wxT( "RELPERMIT" ) ) { - CPAParseEValue( iNode, Permittivity, location ); + //TODO try.. catch + throw again with more detailed error information + CADSTAR_COMMON::ParseChildEValue( iNode, Permittivity ); } else if( nodeName == wxT( "LOSSTANGENT" ) ) { - CPAParseEValue( iNode, LossTangent, location ); + //TODO try.. catch + throw again with more detailed error information + CADSTAR_COMMON::ParseChildEValue( iNode, LossTangent ); } else if( nodeName == wxT( "RESISTIVITY" ) ) { - CPAParseEValue( iNode, Resistivity, location ); + //TODO try.. catch + throw again with more detailed error information + CADSTAR_COMMON::ParseChildEValue( iNode, Resistivity ); } else { @@ -211,12 +315,14 @@ void CPA_MATERIAL::Parse( XNODE* aNode ) } } + void CPA_LAYER::Parse( XNODE* aNode ) { wxASSERT( aNode->GetName() == wxT( "LAYER" ) ); //Process Name & ID - CPAParseNameAndID( aNode, Name, ID ); + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); XNODE* cNode = aNode->GetChildren(); auto processLayerMaterialDetails = [&]() { @@ -230,13 +336,7 @@ void CPA_LAYER::Parse( XNODE* aNode ) //Process material ID and layer width MaterialId = CADSTAR_COMMON::GetAttributeID( tempNode, 0 ); - if( MaterialId.IsEmpty() ) - THROW_PARSING_IO_ERROR( - wxT( "Material ID" ), wxString::Format( "LAYER %s->MAKE", Name ) ); - - if( !CADSTAR_COMMON::GetAttributeID( tempNode, 1 ).ToLong( &Thickness ) ) - THROW_PARSING_IO_ERROR( - wxT( "Thickness" ), wxString::Format( "LAYER %s->MAKE", Name ) ); + Thickness = CADSTAR_COMMON::GetAttributeIDLong( tempNode, 1 ); XNODE* childOfTempNode = tempNode->GetChildren(); @@ -412,18 +512,649 @@ void CPA_LAYER::Parse( XNODE* aNode ) } } -void CPA_EVALUE::Parse( XNODE* aNode ) -{ - wxASSERT( aNode->GetName() == wxT( "E" ) ); - if( ( !CADSTAR_COMMON::GetAttributeID( aNode, 0 ).ToLong( &Base ) ) - || ( !CADSTAR_COMMON::GetAttributeID( aNode, 1 ).ToLong( &Exponent ) ) ) - THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ), - wxString::Format( - "%s->%s", aNode->GetParent()->GetName(), aNode->GetParent()->GetName() ) ); +void CPA_FORMAT::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "FORMAT" ) ); + + Type = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + SomeInt = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 ); + Version = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); } -double CPA_EVALUE::GetDouble() + +void CPA_TIMESTAMP::Parse( XNODE* aNode ) { - return Base * std::pow( 10.0, Exponent ); + wxASSERT( aNode->GetName() == wxT( "TIMESTAMP" ) ); + + if( !CADSTAR_COMMON::GetAttributeID( aNode, 0 ).ToLong( &Year ) + || !CADSTAR_COMMON::GetAttributeID( aNode, 1 ).ToLong( &Month ) + || !CADSTAR_COMMON::GetAttributeID( aNode, 2 ).ToLong( &Day ) + || !CADSTAR_COMMON::GetAttributeID( aNode, 3 ).ToLong( &Hour ) + || !CADSTAR_COMMON::GetAttributeID( aNode, 4 ).ToLong( &Minute ) + || !CADSTAR_COMMON::GetAttributeID( aNode, 5 ).ToLong( &Second ) ) + THROW_PARSING_IO_ERROR( wxT( "TIMESTAMP" ), wxString::Format( "HEADER" ) ); +} + + +void CPA_HEADER::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "HEADER" ) ); + + XNODE* cNode = aNode->GetChildren(); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString nodeName = cNode->GetName(); + + if( nodeName == wxT( "FORMAT" ) ) + //TODO try.. catch + throw again with more detailed error information + Format.Parse( cNode ); + else if( nodeName == wxT( "JOBFILE" ) ) + JobFile = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); + else if( nodeName == wxT( "JOBTITLE" ) ) + JobTitle = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); + else if( nodeName == wxT( "GENERATOR" ) ) + Generator = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); + else if( nodeName == wxT( "RESOLUTION" ) ) + { + XNODE* subNode = cNode->GetChildren(); + if( ( subNode->GetName() == wxT( "METRIC" ) ) + && ( CADSTAR_COMMON::GetAttributeID( subNode, 0 ) == wxT( "HUNDREDTH" ) ) + && ( CADSTAR_COMMON::GetAttributeID( subNode, 1 ) == wxT( "MICRON" ) ) ) + { + Resolution = CPA_RESOLUTION::HUNDREDTH_MICRON; + } + else //TODO Need to find out if there are other possible resolutions. Logically + // there must be other base units that could be used, such as "IMPERIAL INCH" + // or "METRIC MM" but so far none of settings in CADSTAR generated a different + // output resolution to "HUNDREDTH MICRON" + THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), wxT( "HEADER->RESOLUTION" ) ); + } + else if( nodeName == wxT( "TIMESTAMP" ) ) + //TODO try.. catch + throw again with more detailed error information + Timestamp.Parse( cNode ); + else + THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "HEADER" ) ); + } +} + + +void CPA_LINECODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "LINECODE" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + if( !CADSTAR_COMMON::GetAttributeID( aNode, 2 ).ToLong( &Width ) ) + THROW_PARSING_IO_ERROR( wxT( "Line Width" ), wxString::Format( "LINECODE -> %s", Name ) ); + + XNODE* cNode = aNode->GetChildren(); + + if( cNode->GetName() != wxT( "STYLE" ) ) + THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxString::Format( "LINECODE -> %s", Name ) ); + + wxString styleStr = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); + + if( styleStr == wxT( "SOLID" ) ) + Style = CPA_LINESTYLE::SOLID; + else if( styleStr == wxT( "DASH" ) ) + Style = CPA_LINESTYLE::DASH; + else if( styleStr == wxT( "DASHDOT" ) ) + Style = CPA_LINESTYLE::DASHDOT; + else if( styleStr == wxT( "DASHDOTDOT" ) ) + Style = CPA_LINESTYLE::DASHDOTDOT; + else if( styleStr == wxT( "DOT" ) ) + Style = CPA_LINESTYLE::DOT; + else + THROW_UNKNOWN_PARAMETER_IO_ERROR( wxString::Format( "STYLE %s", styleStr ), + wxString::Format( "LINECODE -> %s", Name ) ); +} + + +void CPA_HATCH::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "HATCH" ) ); + + Step = CADSTAR_COMMON::GetAttributeIDLong( aNode, 0 ); + LineWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); + + XNODE* cNode = aNode->GetChildren(); + + if( !cNode || cNode->GetName() != wxT( "ORIENT" ) ) + THROW_MISSING_NODE_IO_ERROR( wxT( "ORIENT" ), wxT( "HATCH" ) ); + + OrientAngle = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); +} + + +void CPA_HATCHCODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "HATCHCODE" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + XNODE* cNode = aNode->GetChildren(); + wxString location = wxString::Format( "HATCHCODE -> %s", Name ); + + for( ; cNode; cNode = cNode->GetNext() ) + { + if( cNode->GetName() != wxT( "HATCH" ) ) + THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), location ); + + CPA_HATCH hatch; + //TODO try.. catch + throw again with more detailed error information + hatch.Parse( cNode ); + Hatches.push_back( hatch ); + } +} + + +void CPA_FONT::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "FONT" ) ); + + Name = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Modifier1 = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 ); + Modifier2 = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); + + XNODE* cNode = aNode->GetChildren(); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString cNodeName = cNode->GetName(); + + if( cNodeName == wxT( "ITALIC" ) ) + Italic = true; + else if( cNodeName == wxT( "KERNING" ) ) + KerningPairs = true; + else + THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() ); + } +} + +void CPA_TEXTCODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "TEXTCODE" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + LineWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); + Height = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 ); + Width = CADSTAR_COMMON::GetAttributeIDLong( aNode, 4 ); + + XNODE* cNode = aNode->GetChildren(); + + if( cNode ) + { + if( cNode->GetName() == wxT( "FONT" ) ) + //TODO try.. catch + throw again with more detailed error information + Font.Parse( cNode ); + else + THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() ); + } +} + + +void CPA_ROUTECODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "ROUTECODE" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + OptimalWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); + + XNODE* cNode = aNode->GetChildren(); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString cNodeName = cNode->GetName(); + + if( cNodeName == wxT( "NECKWIDTH" ) ) + NeckedWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "MINWIDTH" ) ) + MinWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "MAXWIDTH" ) ) + MaxWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else + THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() ); + } +} + + +void CPA_COPREASSIGN::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "COPREASSIGN" ) ); + + LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + + CopperWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 ); +} + + +void CPA_COPPERCODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "COPPERCODE" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + CopperWidth = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); + + XNODE* cNode = aNode->GetChildren(); + + for( ; cNode; cNode = cNode->GetNext() ) + { + if( cNode->GetName() == wxT( "COPREASSIGN" ) ) + { + //TODO try.. catch + throw again with more detailed error information + CPA_COPREASSIGN reassign; + reassign.Parse( cNode ); + Reassigns.push_back( reassign ); + } + else + THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() ); + } +} + + +void CPA_SPACINGCODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) ); + + Code = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + + Spacing = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 ); +} + + +bool CPA_PAD_SHAPE::IsShape( XNODE* aNode ) +{ + wxString aNodeName = aNode->GetName(); + + if( aNodeName == wxT( "ANNULUS" ) || aNodeName == wxT( "BULLET" ) || aNodeName == wxT( "ROUND" ) + || aNodeName == wxT( "DIAMOND" ) || aNodeName == wxT( "FINGER" ) + || aNodeName == wxT( "OCTAGON" ) || aNodeName == wxT( "RECTANGLE" ) + || aNodeName == wxT( "ROUNDED" ) || aNodeName == wxT( "SQUARE" ) ) + return true; + else + return false; +} + + +void CPA_PAD_SHAPE::Parse( XNODE* aNode ) +{ + wxASSERT( IsShape( aNode ) ); + + wxString aNodeName = aNode->GetName(); + + if( aNodeName == wxT( "ANNULUS" ) ) + ShapeType = CPA_SHAPE_TYPE::ANNULUS; + else if( aNodeName == wxT( "BULLET" ) ) + ShapeType = CPA_SHAPE_TYPE::BULLET; + else if( aNodeName == wxT( "ROUND" ) ) + ShapeType = CPA_SHAPE_TYPE::CIRCLE; + else if( aNodeName == wxT( "DIAMOND" ) ) + ShapeType = CPA_SHAPE_TYPE::DIAMOND; + else if( aNodeName == wxT( "FINGER" ) ) + ShapeType = CPA_SHAPE_TYPE::FINGER; + else if( aNodeName == wxT( "OCTAGON" ) ) + ShapeType = CPA_SHAPE_TYPE::OCTAGON; + else if( aNodeName == wxT( "RECTANGLE" ) ) + ShapeType = CPA_SHAPE_TYPE::RECTANGLE; + else if( aNodeName == wxT( "ROUNDED" ) ) + ShapeType = CPA_SHAPE_TYPE::ROUNDED_RECT; + else if( aNodeName == wxT( "SQUARE" ) ) + ShapeType = CPA_SHAPE_TYPE::SQUARE; + else + wxASSERT( true ); + + switch( ShapeType ) + { + case CPA_SHAPE_TYPE::ANNULUS: + Size = CADSTAR_COMMON::GetAttributeIDLong( aNode, 0 ); + InternalFeature = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 ); + break; + + case CPA_SHAPE_TYPE::ROUNDED_RECT: + InternalFeature = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 ); + //Fall through + case CPA_SHAPE_TYPE::BULLET: + case CPA_SHAPE_TYPE::FINGER: + case CPA_SHAPE_TYPE::RECTANGLE: + RightLength = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); + LeftLength = CADSTAR_COMMON::GetAttributeIDLong( aNode, 1 ); + //Fall through + case CPA_SHAPE_TYPE::SQUARE: + + if( aNode->GetChildren() ) + { + if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) ) + { + OrientAngle = CADSTAR_COMMON::GetAttributeIDLong( aNode->GetChildren(), 0 ); + } + else + THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() ); + + CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() ); + } + //Fall through + case CPA_SHAPE_TYPE::CIRCLE: + Size = CADSTAR_COMMON::GetAttributeIDLong( aNode, 0 ); + break; + } +} + +void CPA_PADREASSIGN::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) ); + + LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + + if( CPA_PAD_SHAPE::IsShape( aNode->GetChildren() ) ) + //TODO try.. catch + throw again with more detailed error information + Shape.Parse( aNode->GetChildren() ); + else + THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() ); + + CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() ); +} + + +void CPA_PADCODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "PADCODE" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + XNODE* cNode = aNode->GetChildren(); + wxString location = wxString::Format( "PADCODE -> %s", Name ); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString cNodeName = cNode->GetName(); + + if( CPA_PAD_SHAPE::IsShape( cNode ) ) + //TODO try.. catch + throw again with more detailed error information + Shape.Parse( cNode ); + else if( cNodeName == wxT( "CLEARANCE" ) ) + ReliefClearance = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "RELIEFWIDTH" ) ) + ReliefWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "DRILL" ) ) + { + DrillDiameter = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + XNODE* subNode = cNode->GetChildren(); + + for( ; subNode; subNode = subNode->GetNext() ) + { + wxString subNodeName = subNode->GetName(); + + if( subNodeName == wxT( "NONPLATED" ) ) + Plated = false; + else if( subNodeName == wxT( "OVERSIZE" ) ) + DrillOversize = CADSTAR_COMMON::GetAttributeIDLong( subNode, 0 ); + else + THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location ); + } + } + else if( cNodeName == wxT( "DRILLLENGTH" ) ) + SlotLength = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "DRILLORIENTATION" ) ) + SlotOrientation = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "DRILLXOFFSET" ) ) + DrillXoffset = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "DRILLYOFFSET" ) ) + DrillYoffset = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "PADREASSIGN" ) ) + { + //TODO try.. catch + throw again with more detailed error information + CPA_PADREASSIGN reassign; + reassign.Parse( cNode ); + Reassigns.push_back( reassign ); + } + else + THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location ); + } +} + + +void CPA_VIAREASSIGN::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) ); + + LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + + if( CPA_PAD_SHAPE::IsShape( aNode->GetChildren() ) ) + //TODO try.. catch + throw again with more detailed error information + Shape.Parse( aNode->GetChildren() ); + else + THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() ); + + CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() ); +} + + +void CPA_VIACODE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "VIACODE" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + XNODE* cNode = aNode->GetChildren(); + wxString location = wxString::Format( "VIACODE -> %s", Name ); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString cNodeName = cNode->GetName(); + + if( CPA_PAD_SHAPE::IsShape( cNode ) ) + //TODO try.. catch + throw again with more detailed error information + Shape.Parse( cNode ); + else if( cNodeName == wxT( "CLEARANCE" ) ) + ReliefClearance = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "RELIEFWIDTH" ) ) + ReliefWidth = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + else if( cNodeName == wxT( "DRILL" ) ) + { + DrillDiameter = CADSTAR_COMMON::GetAttributeIDLong( cNode, 0 ); + XNODE* subNode = cNode->GetChildren(); + + for( ; subNode; subNode = subNode->GetNext() ) + { + wxString subNodeName = subNode->GetName(); + + if( subNodeName == wxT( "OVERSIZE" ) ) + DrillOversize = CADSTAR_COMMON::GetAttributeIDLong( subNode, 0 ); + else + THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location ); + } + } + else if( cNodeName == wxT( "VIAREASSIGN" ) ) + { + //TODO try.. catch + throw again with more detailed error information + CPA_VIAREASSIGN reassign; + reassign.Parse( cNode ); + Reassigns.push_back( reassign ); + } + else + THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location ); + } +} + + +void CPA_LAYERPAIR::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + PhysicalLayerStart = CADSTAR_COMMON::GetAttributeIDLong( aNode, 2 ); + PhysicalLayerEnd = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 ); + + wxString location = wxString::Format( "LAYERPAIR -> %s", Name ); + + if( aNode->GetChildren() ) + { + if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) ) + { + ViacodeID = CADSTAR_COMMON::GetAttributeID( aNode->GetChildren(), 0 ); + } + else + THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location ); + + CADSTAR_COMMON::CheckNoNextNodes( aNode->GetChildren() ); + } +} + + +void CPA_ATTRNAME::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "ATTRNAME" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + XNODE* cNode = aNode->GetChildren(); + wxString location = wxString::Format( "ATTRNAME -> %s", Name ); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString cNodeName = cNode->GetName(); + + if( cNodeName == wxT( "ATTROWNER" ) ) + { + wxString attOwnerVal = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); + + if( attOwnerVal == wxT( "ALL_ITEMS" ) ) + AttributeOwner = CPA_ATTROWNER::ALL_ITEMS; + else if( attOwnerVal == wxT( "AREA" ) ) + AttributeOwner = CPA_ATTROWNER::AREA; + else if( attOwnerVal == wxT( "BOARD" ) ) + AttributeOwner = CPA_ATTROWNER::BOARD; + else if( attOwnerVal == wxT( "COMPONENT" ) ) + AttributeOwner = CPA_ATTROWNER::COMPONENT; + else if( attOwnerVal == wxT( "CONNECTION" ) ) + AttributeOwner = CPA_ATTROWNER::CONNECTION; + else if( attOwnerVal == wxT( "COPPER" ) ) + AttributeOwner = CPA_ATTROWNER::COPPER; + else if( attOwnerVal == wxT( "DOCSYMBOL" ) ) + AttributeOwner = CPA_ATTROWNER::DOCSYMBOL; + else if( attOwnerVal == wxT( "FIGURE" ) ) + AttributeOwner = CPA_ATTROWNER::FIGURE; + else if( attOwnerVal == wxT( "NET" ) ) + AttributeOwner = CPA_ATTROWNER::NET; + else if( attOwnerVal == wxT( "NETCLASS" ) ) + AttributeOwner = CPA_ATTROWNER::NETCLASS; + else if( attOwnerVal == wxT( "PART" ) ) + AttributeOwner = CPA_ATTROWNER::PART; + else if( attOwnerVal == wxT( "PART_DEFINITION" ) ) + AttributeOwner = CPA_ATTROWNER::PART_DEFINITION; + else if( attOwnerVal == wxT( "PIN" ) ) + AttributeOwner = CPA_ATTROWNER::PIN; + else if( attOwnerVal == wxT( "SYMDEF" ) ) + AttributeOwner = CPA_ATTROWNER::SYMDEF; + else if( attOwnerVal == wxT( "TEMPLATE" ) ) + AttributeOwner = CPA_ATTROWNER::TEMPLATE; + else if( attOwnerVal == wxT( "TESTPOINT" ) ) + AttributeOwner = CPA_ATTROWNER::TESTPOINT; + else + THROW_UNKNOWN_PARAMETER_IO_ERROR( attOwnerVal, location ); + } + else if( cNodeName == wxT( "ATTRUSAGE" ) ) + { + wxString attUsageVal = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); + + if( attUsageVal == wxT( "BOTH" ) ) + AttributeUsage = CPA_ATTRUSAGE::BOTH; + else if( attUsageVal == wxT( "COMPONENT" ) ) + AttributeUsage = CPA_ATTRUSAGE::COMPONENT; + else if( attUsageVal == wxT( "PART_DEFINITION" ) ) + AttributeUsage = CPA_ATTRUSAGE::PART_DEFINITION; + else if( attUsageVal == wxT( "PART_LIBRARY" ) ) + AttributeUsage = CPA_ATTRUSAGE::PART_LIBRARY; + else if( attUsageVal == wxT( "SYMBOL" ) ) + AttributeUsage = CPA_ATTRUSAGE::SYMBOL; + else + THROW_UNKNOWN_PARAMETER_IO_ERROR( attUsageVal, location ); + } + else if( cNodeName == wxT( "NOTRANSFER" ) ) + NoTransfer = true; + else + THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location ); + } +} + + +void CPA_ATTRIBUTE_VALUE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "ATTR" ) ); + + AttributeID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Value = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); +} + + +void CPA_NETCLASS::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "NETCLASS" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + + XNODE* cNode = aNode->GetChildren(); + wxString location = wxString::Format( "NETCLASS -> %s", Name ); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString cNodeName = cNode->GetName(); + + if( cNodeName == wxT( "ATTR" ) ) + { + //TODO try.. catch + throw again with more detailed error information + CPA_ATTRIBUTE_VALUE attribute_val; + attribute_val.Parse( cNode ); + Attributes.push_back( attribute_val ); + } + else + THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location ); + } +} + + +void CPA_SPCCLASSNAME::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "SPCCLASSNAME" ) ); + + //Process Name & ID + ID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + Name = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); +} + + +void CPA_SPCCLASSSPACE::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) ); + + SpacingClassID1 = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); + SpacingClassID2 = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); + LayerID = CADSTAR_COMMON::GetAttributeID( aNode, 2 ); + Spacing = CADSTAR_COMMON::GetAttributeIDLong( aNode, 3 ); } diff --git a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.h b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.h index 2521129805..7ac42a597c 100644 --- a/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.h +++ b/pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.h @@ -28,23 +28,68 @@ #include #include +#include -/** - * @brief Represents a floating value in E notation - */ -struct CPA_EVALUE +const long CPA_UNDEFINED = -1; // CADSTAR 2018.0 and 2019.0 arhive, + // 20=> CADSTAR 18.0 archive, 19=> CADSTAR 17.0 archive, etc.) + void Parse( XNODE* aNode ); }; -typedef wxString CPA_MATERIAL_ID; +struct CPA_TIMESTAMP +{ + long Year; + long Month; + long Day; + long Hour; + long Minute; + long Second; + + void Parse( XNODE* aNode ); +}; + +//Note: there are possibly several other resolutions, but HUNDREDTH MICRON is only one known +enum class CPA_RESOLUTION +{ + HUNDREDTH_MICRON +}; + + +struct CPA_HEADER +{ + CPA_FORMAT Format; + wxString JobFile; + wxString JobTitle; + wxString Generator; + CPA_RESOLUTION Resolution; + CPA_TIMESTAMP Timestamp; + + void Parse( XNODE* aNode ); +}; + + +//================================= +// ASSIGNMENTS +//================================= + +//................................. +// ASSIGNMENTS -> LAYERDEFS +//................................. -typedef wxString CPA_LAYER_ID; /** * @brief subset of CPA_LAYER_TYPE - for materials only @@ -56,18 +101,20 @@ enum class CPA_MATERIAL_LAYER_TYPE NON_ELECTRICAL }; + struct CPA_MATERIAL { - CPA_MATERIAL_ID ID; + CPA_ID ID; wxString Name; CPA_MATERIAL_LAYER_TYPE Type; // Materials; - std::map Layers; - std::vector LayerStack; + std::map Materials; + std::map Layers; + std::vector LayerStack; void Parse( XNODE* aNode ); }; + +//................................. +// ASSIGNMENTS -> CODEDEFS +//................................. + +enum class CPA_LINESTYLE +{ + SOLID, + DASH, + DASHDOT, + DASHDOTDOT, + DOT +}; + +struct CPA_LINECODE +{ + CPA_ID ID; + wxString Name; + long Width; + CPA_LINESTYLE Style; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_HATCH +{ + long Step; + long LineWidth; + long OrientAngle; //< 1/1000 of a Degree + + void Parse( XNODE* aNode ); +}; + + +struct CPA_HATCHCODE +{ + CPA_ID ID; + wxString Name; + std::vector Hatches; + + void Parse( XNODE* aNode ); +}; + + +const long CPA_FONT_NORMAL = 400; +const long CPA_FONT_BOLD = 700; + + +struct CPA_FONT +{ + wxString Name = wxT( "CADSTAR" ); + long Modifier1 = CPA_FONT_NORMAL; //< It seems this is related to weight. 400=Normal, 700=Bold. + long Modifier2 = 0; //< It seems this is always 0 regardless of settings + bool KerningPairs = false; //< From CADSTAR Help: "Kerning Pairs is for causing the system to + //automatically reduce the spacing between certain pairs of + //characters in order to improve the appearance of the text" + bool Italic = false; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_TEXTCODE +{ + CPA_ID ID; + wxString Name; + long LineWidth; + long Height; + long Width; //< Defaults to 0 if using system fonts or, if using CADSTAR font, default to + //equal height (1:1 aspect ratio). Allows for system fonts to be rendered in + //a different aspect ratio. + CPA_FONT Font; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_ROUTECODE +{ + CPA_ID ID; + wxString Name; + long OptimalWidth; + long MinWidth; + long MaxWidth; + long NeckedWidth; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_COPREASSIGN +{ + CPA_ID LayerID; + long CopperWidth; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_COPPERCODE +{ + CPA_ID ID; + wxString Name; + long CopperWidth; + std::vector Reassigns; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_SPACINGCODE +{ + wxString Code; + long Spacing; + + void Parse( XNODE* aNode ); +}; + + +enum class CPA_SHAPE_TYPE +{ + ANNULUS, + BULLET, + CIRCLE, // Reassigns; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_VIAREASSIGN +{ + CPA_ID LayerID; + CPA_PAD_SHAPE Shape; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_VIACODE +{ + CPA_ID ID; + wxString Name; + CPA_PAD_SHAPE Shape; + long ReliefClearance = CPA_UNDEFINED; //< if undefined inherits from design + long ReliefWidth = CPA_UNDEFINED; //< if undefined inherits from design + long DrillDiameter = CPA_UNDEFINED; + long DrillOversize = CPA_UNDEFINED; + + std::vector Reassigns; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_LAYERPAIR +{ + CPA_ID ID; + wxString Name; + CPA_PHYSICAL_LAYER PhysicalLayerStart; + CPA_PHYSICAL_LAYER PhysicalLayerEnd; + CPA_ID ViacodeID; + + void Parse( XNODE* aNode ); +}; + + +enum class CPA_ATTROWNER +{ + ALL_ITEMS, + AREA, + BOARD, + COMPONENT, + CONNECTION, + COPPER, + DOCSYMBOL, + FIGURE, + NET, + NETCLASS, + PART, //< Only library Attributes + PART_DEFINITION, //< Only library Attributes + PIN, + SYMDEF, + TEMPLATE, + TESTPOINT +}; + + +enum class CPA_ATTRUSAGE +{ + BOTH, //< From CADSTAR Help: Assigned to both Schematic symbols and PCB components, + // and displayed on Schematic and PCB designs. + COMPONENT, //< From CADSTAR Help: Assigned to PCB components and displayed on PCB designs + PART_DEFINITION, //< From CADSTAR Help: Assigned to Parts library Definitions and displayed + // by the Library searcher + PART_LIBRARY, //< From CADSTAR Help: Only used by non-Cadstar applicationws + SYMBOL, //< From CADSTAR Help: Assigned to Schematic Symbols and displayed on + // Schematic Designs + UNDEFINED //< Note: It seems that some attribute have no "ATTRUSAGE" defined. It appears + // that the attributes that fall under this category arethe ones associated + // with the design itself (i.e. not inherited from the library) +}; + +/** + * @brief NOTE from CADSTAR help: To convert a Part Definition Attribute into a hyperlink, prefix + * the attribute name with "Link " + */ +struct CPA_ATTRNAME +{ + CPA_ID ID; + wxString Name; + CPA_ATTROWNER AttributeOwner = CPA_ATTROWNER::ALL_ITEMS; + CPA_ATTRUSAGE AttributeUsage = CPA_ATTRUSAGE::UNDEFINED; + bool NoTransfer = false; //< True="All Design Types", False="Current Design Type" + // "All Design Types" Description from CADSTAR Help: "The selected + // attribute name will beavailable when any design is displayed" + // "Current Design Type" From CADSTAR Help: This restricts the + // availability of the selectedattribute name to the current design. + + void Parse( XNODE* aNode ); +}; + + +struct CPA_ATTRIBUTE_VALUE +{ + CPA_ID AttributeID; + wxString Value; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_NETCLASS +{ + CPA_ID ID; + wxString Name; + std::vector Attributes; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_SPCCLASSNAME +{ + CPA_ID ID; + wxString Name; + + void Parse( XNODE* aNode ); +}; + +const CPA_ID CPA_NO_SPACE_CLASS_ID = wxT( "NO_SPACE_CLASS" ); //< Default spacing class + +struct CPA_SPCCLASSSPACE +{ + CPA_ID SpacingClassID1; + CPA_ID SpacingClassID2; + CPA_ID LayerID; //< Normally LAY0, which corresponds to (All Layers) + long Spacing; + + void Parse( XNODE* aNode ); +}; + + +struct CPA_CODEDEFS +{ + std::map LineCodes; + std::map HatchCodes; + std::map TextCodes; + std::map RouteCodes; + std::map CopperCodes; + std::vector SpacingCodes; // PadCodes; + std::map ViaCodes; + std::map LayerPairs; //< Default vias to use between pairs of layers + std::map AttributeNames; + std::map NetClasses; + std::map SpacingClassNames; + std::vector SpacingClasses; + + void Parse( XNODE* aNode ); //TODO Implement +}; + + struct CPA_ASSIGNMENTS { CPA_LAYERDEFS Layerdefs; - //Todo Add codedefs, technology, grids, etc. + CPA_CODEDEFS Codedefs; + //TODO Add technology, grids, etc. }; + +//================================= +// CPA_FILE +//================================= + /** * @brief Represents a CADSTAR PCB Archive (CPA) file */ @@ -161,13 +552,12 @@ public: wxString Filename; + CPA_HEADER Header; CPA_ASSIGNMENTS Assignments; - //Todo Add Header, Library, Defaults, etc.. + //TODO Add Library, Defaults, Parts, etc.. + + int KiCadUnitMultiplier; //