7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2024-11-25 00:35:01 +00:00
kicad/pcbnew/pcb_io/cadstar/cadstar_pcb_archive_parser.cpp

2649 lines
82 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file cadstar_pcb_archive_parser.cpp
* @brief Parses a CADSTAR PCB Archive file
*/
#include <base_units.h>
#include <cadstar_pcb_archive_parser.h>
#include <macros.h>
#include <progress_reporter.h>
#include <wx/translation.h>
void CADSTAR_PCB_ARCHIVE_PARSER::Parse( bool aLibrary )
{
if( m_progressReporter )
m_progressReporter->BeginPhase( 0 ); // Read file
m_rootNode = LoadArchiveFile( Filename, wxT( "CADSTARPCB" ), m_progressReporter );
if( m_progressReporter )
{
m_progressReporter->BeginPhase( 1 ); // Parse File
std::vector<wxString> subNodeChildrenToCount = { wxT( "LIBRARY" ), wxT( "PARTS" ),
wxT( "LAYOUT" ) };
long numOfSteps = GetNumberOfStepsForReporting( m_rootNode, subNodeChildrenToCount );
m_progressReporter->SetMaxProgress( numOfSteps );
}
m_context.CheckPointCallback = [&](){ checkPoint(); };
XNODE* cNode = m_rootNode->GetChildren();
if( !cNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "HEADER" ), wxT( "CADSTARPCB" ) );
for( ; cNode; cNode = cNode->GetNext() )
{
if( cNode->GetName() == wxT( "HEADER" ) )
{
Header.Parse( cNode, &m_context );
switch( Header.Resolution )
{
case RESOLUTION::HUNDREDTH_MICRON:
KiCadUnitMultiplier = PCB_IU_PER_MM / 1e5;
break;
default:
wxASSERT_MSG( true, wxT( "Unknown File Resolution" ) );
break;
}
if( aLibrary && Header.Format.Type != wxT( "LIBRARY" ) )
{
THROW_IO_ERROR( wxT( "The selected file is not a valid CADSTAR library file." ) );
}
else if( !aLibrary && Header.Format.Type != wxT( "LAYOUT" ) )
{
if( Header.Format.Type == wxT( "LIBRARY" ) )
{
THROW_IO_ERROR(
wxT( "The selected file is a CADSTAR library file (as opposed "
"to a layout file). You can import this library by adding it "
"to the library table." ) );
}
else
{
THROW_IO_ERROR( wxT( "The selected file is an unknown CADSTAR format so "
"cannot be imported into KiCad." ) );
}
}
}
else if( cNode->GetName() == wxT( "ASSIGNMENTS" ) )
{
Assignments.Parse( cNode, &m_context );
}
else if( cNode->GetName() == wxT( "LIBRARY" ) )
{
Library.Parse( cNode, &m_context );
}
else if( cNode->GetName() == wxT( "DEFAULTS" ) )
{
// No design information here (no need to parse)
// Only contains CADSTAR configuration data such as default shapes, text and units
// In future some of this could be converted to KiCad but limited value
}
else if( cNode->GetName() == wxT( "PARTS" ) )
{
Parts.Parse( cNode, &m_context );
}
else if( cNode->GetName() == wxT( "LAYOUT" ) )
{
Layout.Parse( cNode, &m_context );
}
else if( cNode->GetName() == wxT( "DISPLAY" ) )
{
// No design information here (no need to parse)
// Contains CADSTAR Display settings such as layer/element colours and visibility.
// In the future these settings could be converted to KiCad
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "[root]" ) );
}
checkPoint();
}
delete m_rootNode;
m_rootNode = nullptr;
}
void CADSTAR_PCB_ARCHIVE_PARSER::ASSIGNMENTS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "ASSIGNMENTS" ) );
XNODE* cNode = aNode->GetChildren();
if( !cNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "TECHNOLOGY" ), wxT( "ASSIGNMENTS" ) );
for( ; cNode; cNode = cNode->GetNext() )
{
if( cNode->GetName() == wxT( "LAYERDEFS" ) )
Layerdefs.Parse( cNode, aContext );
else if( cNode->GetName() == wxT( "CODEDEFS" ) )
Codedefs.Parse( cNode, aContext );
else if( cNode->GetName() == wxT( "TECHNOLOGY" ) )
Technology.Parse( cNode, aContext );
else if( cNode->GetName() == wxT( "GRIDS" ) )
Grids.Parse( cNode, aContext );
else if( cNode->GetName() == wxT( "NETCLASSEDITATTRIBSETTINGS" ) )
NetclassEditAttributeSettings = true;
else if( cNode->GetName() == wxT( "SPCCLASSEDITATTRIBSETTINGS" ) )
SpacingclassEditAttributeSettings = true;
else
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::LAYERDEFS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) );
wxXmlAttribute* xmlAttribute = nullptr;
XNODE* cNode = aNode->GetChildren();
if( !cNode )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString nodeName = cNode->GetName();
if( nodeName == wxT( "LAYERSTACK" ) )
{
xmlAttribute = cNode->GetAttributes();
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
{
if( !IsValidAttribute( xmlAttribute ) )
continue;
else
LayerStack.push_back( (LAYER_ID) xmlAttribute->GetValue() );
}
CheckNoChildNodes( cNode );
}
else if( nodeName == wxT( "MATERIAL" ) )
{
MATERIAL material;
material.Parse( cNode, aContext );
Materials.insert( std::make_pair( material.ID, material ) );
}
else if( nodeName == wxT( "LAYER" ) )
{
LAYER layer;
layer.Parse( cNode, aContext );
Layers.insert( std::make_pair( layer.ID, layer ) );
}
else if( nodeName == wxT( "SWAPPAIR" ) )
{
LAYER_ID layerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 0 );
LAYER_ID swapLayerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 1 );
Layers[layerId].SwapLayerID = swapLayerId;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::RULESET::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "RULESET" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString nodeName = cNode->GetName();
if( nodeName == wxT( "ROUCODEREF" ) )
{
AreaRouteCodeID = GetXmlAttributeIDString( cNode, 0 );
}
else if( nodeName == wxT( "VIACODEREF" ) )
{
AreaViaCodeID = GetXmlAttributeIDString( cNode, 0 );
}
else if( nodeName == wxT( "SPACINGCODE" ) )
{
SPACINGCODE spacingcode;
spacingcode.Parse( cNode, aContext );
SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::CODEDEFS_PCB::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "CODEDEFS" ) );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString nodeName = cNode->GetName();
if( ParseSubNode( cNode, aContext ) ) // in CADSTAR_ARCHIVE_PARSER::CODEDEFS
{
}
else if( nodeName == wxT( "COPPERCODE" ) )
{
COPPERCODE coppercode;
coppercode.Parse( cNode, aContext );
CopperCodes.insert( std::make_pair( coppercode.ID, coppercode ) );
}
else if( nodeName == wxT( "SPACINGCODE" ) )
{
SPACINGCODE spacingcode;
spacingcode.Parse( cNode, aContext );
SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
}
else if( nodeName == wxT( "RULESET" ) )
{
RULESET ruleset;
ruleset.Parse( cNode, aContext );
Rulesets.insert( std::make_pair( ruleset.ID, ruleset ) );
}
else if( nodeName == wxT( "PADCODE" ) )
{
PADCODE padcode;
padcode.Parse( cNode, aContext );
PadCodes.insert( std::make_pair( padcode.ID, padcode ) );
}
else if( nodeName == wxT( "VIACODE" ) )
{
VIACODE viacode;
viacode.Parse( cNode, aContext );
ViaCodes.insert( std::make_pair( viacode.ID, viacode ) );
}
else if( nodeName == wxT( "LAYERPAIR" ) )
{
LAYERPAIR layerpair;
layerpair.Parse( cNode, aContext );
LayerPairs.insert( std::make_pair( layerpair.ID, layerpair ) );
}
else if( nodeName == wxT( "SPCCLASSSPACE" ) )
{
SPCCLASSSPACE spcclassspace;
spcclassspace.Parse( cNode, aContext );
SpacingClasses.push_back( spcclassspace );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::MATERIAL::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
wxString sType = GetXmlAttributeIDString( aNode, 2 );
if( sType == wxT( "CONSTRUCTION" ) )
{
Type = MATERIAL_LAYER_TYPE::CONSTRUCTION;
}
else if( sType == wxT( "ELECTRICAL" ) )
{
Type = MATERIAL_LAYER_TYPE::ELECTRICAL;
}
else if( sType == wxT( "NONELEC" ) )
{
Type = MATERIAL_LAYER_TYPE::NON_ELECTRICAL;
}
else
{
THROW_UNKNOWN_PARAMETER_IO_ERROR( sType, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
}
XNODE* iNode = aNode->GetChildren();
if( !iNode )
{
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "RESISTIVITY" ),
wxString::Format( wxT( "MATERIAL %s" ), Name ) );
}
for( ; iNode; iNode = iNode->GetNext() )
{
wxString nodeName = iNode->GetName();
if( nodeName == wxT( "RELPERMIT" ) )
{
ParseChildEValue( iNode, aContext, Permittivity );
}
else if( nodeName == wxT( "LOSSTANGENT" ) )
{
ParseChildEValue( iNode, aContext, LossTangent );
}
else if( nodeName == wxT( "RESISTIVITY" ) )
{
ParseChildEValue( iNode, aContext, Resistivity );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::LAYER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "LAYER" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
auto processLayerMaterialDetails = [&]() {
XNODE* tempNode = cNode->GetChildren();
for( ; tempNode; tempNode = tempNode->GetNext() )
{
wxString tempNodeName = tempNode->GetName();
if( tempNodeName == wxT( "MAKE" ) || tempNodeName == wxT( "LAYERHEIGHT" ) )
{
if( tempNodeName == wxT( "LAYERHEIGHT" ) )
{
Thickness = GetXmlAttributeIDLong( tempNode, 0 );
}
else
{
MaterialId = GetXmlAttributeIDString( tempNode, 0 );
Thickness = GetXmlAttributeIDLong( tempNode, 1 );
}
XNODE* childOfTempNode = tempNode->GetChildren();
if( childOfTempNode )
{
if( childOfTempNode->GetName() == wxT( "EMBEDS" ) )
{
wxString embedsValue = GetXmlAttributeIDString( childOfTempNode, 0 );
if( embedsValue == wxT( "UPWARDS" ) )
{
Embedding = EMBEDDING::ABOVE;
}
else if( embedsValue == wxT( "DOWNWARDS" ) )
{
Embedding = EMBEDDING::BELOW;
}
else
{
THROW_UNKNOWN_PARAMETER_IO_ERROR( embedsValue,
wxString::Format( wxT( "LAYER %s -> EMBEDS" ),
Name ) );
}
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( childOfTempNode->GetName(),
wxString::Format( wxT( "LAYER %s->MAKE" ),
Name ) );
}
}
}
else if( tempNodeName == wxT( "BIAS" ) )
{
wxString bias = GetXmlAttributeIDString( tempNode, 0 );
if( bias == wxT( "X_BIASED" ) )
{
RoutingBias = ROUTING_BIAS::X;
}
else if( bias == wxT( "Y_BIASED" ) )
{
RoutingBias = ROUTING_BIAS::Y;
}
else if( bias == wxT( "ANTITRACK" ) )
{
RoutingBias = ROUTING_BIAS::ANTI_ROUTE;
}
else if( bias == wxT( "OBSTACLE" ) )
{
RoutingBias = ROUTING_BIAS::OBSTACLE;
}
else if( bias == wxT( "UNBIASED" ) )
{
RoutingBias = ROUTING_BIAS::UNBIASED;
}
else
{
THROW_UNKNOWN_PARAMETER_IO_ERROR( bias,
wxString::Format( wxT( "LAYER %s -> BIAS" ),
Name ) );
}
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( tempNodeName, wxString::Format( wxT( "LAYER %s" ),
Name ) );
}
}
};
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "ALLDOC" ) )
{
Type = LAYER_TYPE::ALLDOC;
}
else if( cNodeName == wxT( "ALLELEC" ) )
{
Type = LAYER_TYPE::ALLELEC;
}
else if( cNodeName == wxT( "ALLLAYER" ) )
{
Type = LAYER_TYPE::ALLLAYER;
}
else if( cNodeName == wxT( "ASSCOMPCOPP" ) )
{
Type = LAYER_TYPE::ASSCOMPCOPP;
}
else if( cNodeName == wxT( "JUMPERLAYER" ) )
{
Type = LAYER_TYPE::JUMPERLAYER;
}
else if( cNodeName == wxT( "NOLAYER" ) )
{
Type = LAYER_TYPE::NOLAYER;
}
else if( cNodeName == wxT( "POWER" ) )
{
Type = LAYER_TYPE::POWER;
PhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
processLayerMaterialDetails();
}
else if( cNodeName == wxT( "DOC" ) )
{
Type = LAYER_TYPE::DOC;
}
else if( cNodeName == wxT( "CONSTRUCTION" ) )
{
Type = LAYER_TYPE::CONSTRUCTION;
processLayerMaterialDetails();
}
else if( cNodeName == wxT( "ELEC" ) )
{
Type = LAYER_TYPE::ELEC;
PhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
processLayerMaterialDetails();
}
else if( cNodeName == wxT( "NONELEC" ) )
{
Type = LAYER_TYPE::NONELEC;
PhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
processLayerMaterialDetails();
}
else if( cNodeName == wxT( "DESCRIPTION" ) )
{
Description = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REFPLANE" ) )
{
ReferencePlane = true;
}
else if( cNodeName == wxT( "VLAYER" ) )
{
VariantLayer = true;
}
else if( cNodeName == wxT( "LASUBTYP" ) )
{
//Process subtype
wxString sSubType = GetXmlAttributeIDString( cNode, 0 );
if( sSubType == wxT( "LAYERSUBTYPE_ASSEMBLY" ) )
{
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_ASSEMBLY;
}
else if( sSubType == wxT( "LAYERSUBTYPE_PASTE" ) )
{
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_PASTE;
}
else if( sSubType == wxT( "LAYERSUBTYPE_PLACEMENT" ) )
{
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_PLACEMENT;
}
else if( sSubType == wxT( "LAYERSUBTYPE_SILKSCREEN" ) )
{
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_SILKSCREEN;
}
else if( sSubType == wxT( "LAYERSUBTYPE_SOLDERRESIST" ) )
{
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_SOLDERRESIST;
}
else if( sSubType == wxT( "LAYERSUBTYPE_CLEARANCE" ) )
{
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_CLEARANCE;
}
else if( sSubType == wxT( "LAYERSUBTYPE_ROUT" ) )
{
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_ROUT;
}
else
{
THROW_UNKNOWN_PARAMETER_IO_ERROR( sSubType, wxString::Format( wxT( "LAYER %s %s" ),
Name, cNodeName ) );
}
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxString::Format( wxT( "LAYER %s" ), Name ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::COPREASSIGN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "COPREASSIGN" ) );
LayerID = GetXmlAttributeIDString( aNode, 0 );
CopperWidth = GetXmlAttributeIDLong( aNode, 1 );
}
void CADSTAR_PCB_ARCHIVE_PARSER::COPPERCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "COPPERCODE" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
CopperWidth = GetXmlAttributeIDLong( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
if( cNode->GetName() == wxT( "COPREASSIGN" ) )
{
CADSTAR_PCB_ARCHIVE_PARSER::COPREASSIGN reassign;
reassign.Parse( cNode, aContext );
Reassigns.push_back( reassign );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::SPACINGCODE::REASSIGN::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "SPACEREASSIGN" ) );
LayerID = GetXmlAttributeIDString( aNode, 0 );
Spacing = GetXmlAttributeIDLong( aNode, 1 );
CheckNoChildNodes( aNode );
}
void CADSTAR_PCB_ARCHIVE_PARSER::SPACINGCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Spacing = GetXmlAttributeIDLong( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "SPACEREASSIGN" ) )
{
REASSIGN reassign;
reassign.Parse( cNode, aContext );
Reassigns.push_back( reassign );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
bool CADSTAR_PCB_ARCHIVE_PARSER::CADSTAR_PAD_SHAPE::IsPadShape( 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 CADSTAR_PCB_ARCHIVE_PARSER::CADSTAR_PAD_SHAPE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( IsPadShape( aNode ) );
wxString aNodeName = aNode->GetName();
if( aNodeName == wxT( "ANNULUS" ) )
ShapeType = PAD_SHAPE_TYPE::ANNULUS;
else if( aNodeName == wxT( "BULLET" ) )
ShapeType = PAD_SHAPE_TYPE::BULLET;
else if( aNodeName == wxT( "ROUND" ) )
ShapeType = PAD_SHAPE_TYPE::CIRCLE;
else if( aNodeName == wxT( "DIAMOND" ) )
ShapeType = PAD_SHAPE_TYPE::DIAMOND;
else if( aNodeName == wxT( "FINGER" ) )
ShapeType = PAD_SHAPE_TYPE::FINGER;
else if( aNodeName == wxT( "OCTAGON" ) )
ShapeType = PAD_SHAPE_TYPE::OCTAGON;
else if( aNodeName == wxT( "RECTANGLE" ) )
ShapeType = PAD_SHAPE_TYPE::RECTANGLE;
else if( aNodeName == wxT( "ROUNDED" ) )
ShapeType = PAD_SHAPE_TYPE::ROUNDED_RECT;
else if( aNodeName == wxT( "SQUARE" ) )
ShapeType = PAD_SHAPE_TYPE::SQUARE;
else
wxASSERT( true );
switch( ShapeType )
{
case PAD_SHAPE_TYPE::ANNULUS:
Size = GetXmlAttributeIDLong( aNode, 0 );
InternalFeature = GetXmlAttributeIDLong( aNode, 1 );
break;
case PAD_SHAPE_TYPE::ROUNDED_RECT:
InternalFeature = GetXmlAttributeIDLong( aNode, 3 );
KI_FALLTHROUGH;
case PAD_SHAPE_TYPE::BULLET:
case PAD_SHAPE_TYPE::FINGER:
case PAD_SHAPE_TYPE::RECTANGLE:
RightLength = GetXmlAttributeIDLong( aNode, 2 );
LeftLength = GetXmlAttributeIDLong( aNode, 1 );
KI_FALLTHROUGH;
case PAD_SHAPE_TYPE::DIAMOND:
case PAD_SHAPE_TYPE::OCTAGON:
case PAD_SHAPE_TYPE::SQUARE:
if( aNode->GetChildren() )
{
if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) )
{
OrientAngle = GetXmlAttributeIDLong( aNode->GetChildren(), 0 );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
}
CheckNoNextNodes( aNode->GetChildren() );
}
KI_FALLTHROUGH;
case PAD_SHAPE_TYPE::CIRCLE:
Size = GetXmlAttributeIDLong( aNode, 0 );
break;
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::PADREASSIGN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) );
LayerID = GetXmlAttributeIDString( aNode, 0 );
if( CADSTAR_PAD_SHAPE::IsPadShape( aNode->GetChildren() ) )
Shape.Parse( aNode->GetChildren(), aContext );
else
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
CheckNoNextNodes( aNode->GetChildren() );
}
void CADSTAR_PCB_ARCHIVE_PARSER::PADCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "PADCODE" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( wxT( "PADCODE -> %s" ), Name );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
{
Shape.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "CLEARANCE" ) )
{
ReliefClearance = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "RELIEFWIDTH" ) )
{
ReliefWidth = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "DRILL" ) )
{
DrillDiameter = GetXmlAttributeIDLong( 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 = GetXmlAttributeIDLong( subNode, 0 );
else
THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
}
}
else if( cNodeName == wxT( "DRILLLENGTH" ) )
{
SlotLength = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "DRILLORIENTATION" ) )
{
SlotOrientation = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "DRILLXOFFSET" ) )
{
DrillXoffset = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "DRILLYOFFSET" ) )
{
DrillYoffset = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "PADREASSIGN" ) )
{
PADREASSIGN reassign;
reassign.Parse( cNode, aContext );
Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::VIAREASSIGN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) );
LayerID = GetXmlAttributeIDString( aNode, 0 );
if( CADSTAR_PAD_SHAPE::IsPadShape( aNode->GetChildren() ) )
Shape.Parse( aNode->GetChildren(), aContext );
else
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
CheckNoNextNodes( aNode->GetChildren() );
}
void CADSTAR_PCB_ARCHIVE_PARSER::VIACODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "VIACODE" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( wxT( "VIACODE -> %s" ), Name );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
{
Shape.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "CLEARANCE" ) )
{
ReliefClearance = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "RELIEFWIDTH" ) )
{
ReliefWidth = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "DRILL" ) )
{
DrillDiameter = GetXmlAttributeIDLong( cNode, 0 );
XNODE* subNode = cNode->GetChildren();
for( ; subNode; subNode = subNode->GetNext() )
{
wxString subNodeName = subNode->GetName();
if( subNodeName == wxT( "OVERSIZE" ) )
DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
else
THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
}
}
else if( cNodeName == wxT( "VIAREASSIGN" ) )
{
VIAREASSIGN reassign;
reassign.Parse( cNode, aContext );
Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::LAYERPAIR::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
PhysicalLayerStart = GetXmlAttributeIDLong( aNode, 2 );
PhysicalLayerEnd = GetXmlAttributeIDLong( aNode, 3 );
wxString location = wxString::Format( wxT( "LAYERPAIR -> %s" ), Name );
if( aNode->GetChildren() )
{
if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) )
{
ViacodeID = GetXmlAttributeIDString( aNode->GetChildren(), 0 );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
}
CheckNoNextNodes( aNode->GetChildren() );
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::SPCCLASSSPACE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) );
SpacingClassID1 = GetXmlAttributeIDString( aNode, 0 );
SpacingClassID2 = GetXmlAttributeIDString( aNode, 1 );
LayerID = GetXmlAttributeIDString( aNode, 2 );
Spacing = GetXmlAttributeIDLong( aNode, 3 );
}
void CADSTAR_PCB_ARCHIVE_PARSER::TECHNOLOGY_SECTION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "TECHNOLOGY" ) );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( ParseSubNode( cNode, aContext ) ) //CADSTAR_ARCHIVE_PARSER::SETTINGS
{
}
else if( cNodeName == wxT( "MINROUTEWIDTH" ) )
{
MinRouteWidth = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "MINNECKED" ) )
{
MinNeckedLength = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "MINUNNECKED" ) )
{
MinUnneckedLength = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "MINMITER" ) )
{
MinMitre = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "MAXMITER" ) )
{
MaxMitre = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "MAXPHYSLAYER" ) )
{
MaxPhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "TRACKGRID" ) )
{
TrackGrid = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "VIAGRID" ) )
{
ViaGrid = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "BACKOFFJCTS" ) )
{
BackOffJunctions = true;
}
else if( cNodeName == wxT( "BCKOFFWIDCHANGE" ) )
{
BackOffWidthChange = true;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TECHNOLOGY" ) );
}
}
}
CADSTAR_PCB_ARCHIVE_PARSER::PAD_SIDE CADSTAR_PCB_ARCHIVE_PARSER::GetPadSide(
const wxString& aPadSideString )
{
if( aPadSideString == wxT( "THRU" ) )
return PAD_SIDE::THROUGH_HOLE;
else if( aPadSideString == wxT( "BOTTOM" ) )
return PAD_SIDE::MAXIMUM;
else if( aPadSideString == wxT( "TOP" ) )
return PAD_SIDE::MINIMUM;
else
return PAD_SIDE::THROUGH_HOLE; // Assume through hole as default
}
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT_COPPER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "COMPCOPPER" ) );
CopperCodeID = GetXmlAttributeIDString( aNode, 0 );
LayerID = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
bool shapeIsInitialised = false; // Stop more than one Shape Object
wxString location = wxT( "COMPCOPPER" );
if( !cNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !shapeIsInitialised && Shape.IsShape( cNode ) )
{
Shape.Parse( cNode, aContext );
shapeIsInitialised = true;
}
else if( cNodeName == wxT( "SWAPRULE" ) )
{
SwapRule = ParseSwapRule( cNode );
}
else if( cNodeName == wxT( "ASSOCPIN" ) )
{
wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
{
if( !IsValidAttribute( xmlAttribute ) )
continue;
long padId;
if( !xmlAttribute->GetValue().ToLong( &padId ) )
THROW_PARSING_IO_ERROR( wxT( "ASSOCPIN" ), location );
AssociatedPadIDs.push_back( (PAD_ID) padId );
}
CheckNoChildNodes( cNode );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT_AREA::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "COMPAREA" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
LayerID = GetXmlAttributeIDString( aNode, 3 );
XNODE* cNode = aNode->GetChildren();
bool shapeIsInitialised = false; // Stop more than one Shape Object
wxString location = wxString::Format( wxT( "COMPAREA %s" ), ID );
if( !cNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
{
Shape.Parse( cNode, aContext );
shapeIsInitialised = true;
}
else if( cNodeName == wxT( "SWAPRULE" ) )
{
SwapRule = ParseSwapRule( cNode );
}
else if( cNodeName == wxT( "USAGE" ) )
{
wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
{
if( !IsValidAttribute( xmlAttribute ) )
continue;
if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
NoTracks = true;
else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
NoVias = true;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
}
CheckNoChildNodes( cNode );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::PAD_EXITS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "EXITS" ) );
wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
{
if( !IsValidAttribute( xmlAttribute ) )
continue;
if( xmlAttribute->GetValue() == wxT( "FREE" ) )
FreeAngle = true;
else if( xmlAttribute->GetValue() == wxT( "N" ) )
North = true;
else if( xmlAttribute->GetValue() == wxT( "S" ) )
South = true;
else if( xmlAttribute->GetValue() == wxT( "E" ) )
East = true;
else if( xmlAttribute->GetValue() == wxT( "W" ) )
West = true;
else if( xmlAttribute->GetValue() == wxT( "NE" ) )
NorthEast = true;
else if( xmlAttribute->GetValue() == wxT( "NW" ) )
NorthWest = true;
else if( xmlAttribute->GetValue() == wxT( "SE" ) )
SouthEast = true;
else if( xmlAttribute->GetValue() == wxT( "SW" ) )
SouthWest = true;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), wxT( "EXITS" ) );
}
CheckNoChildNodes( aNode );
}
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT_PAD::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "PAD" ) );
ID = GetXmlAttributeIDLong( aNode, 0 );
PadCodeID = GetXmlAttributeIDString( aNode, 2 );
Side = GetPadSide( GetXmlAttributeIDString( aNode, 3 ) );
XNODE* cNode = aNode->GetChildren();
wxString location = wxString::Format( wxT( "PAD %ld" ), ID );
if( !cNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), location );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "ORIENT" ) )
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
else if( cNodeName == wxT( "FIRSTPAD" ) )
FirstPad = true;
else if( cNodeName == wxT( "EXITS" ) )
Exits.Parse( cNode, aContext );
else if( cNodeName == wxT( "PADIDENTIFIER" ) )
Identifier = GetXmlAttributeIDString( cNode, 0 );
else if( cNodeName == wxT( "PCBONLYPAD" ) )
PCBonlyPad = true;
else if( cNodeName == wxT( "PT" ) )
Position.Parse( cNode, aContext );
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::ARROW::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "DIMARROW" ) );
bool arrowStyleInitialised = false;
bool upperAngleInitialised = false;
bool lowerAngleInitialised = false;
ArrowLength = GetXmlAttributeIDLong( aNode, 3 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "ARROWSTYLE" ) )
{
wxString arrowStyleStr = GetXmlAttributeIDString( cNode, 0 );
arrowStyleInitialised = true;
if( arrowStyleStr == wxT( "DIMENSION_ARROWOPEN" ) )
ArrowStyle = STYLE::OPEN;
else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSED" ) )
ArrowStyle = STYLE::CLOSED;
else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLEAR" ) )
ArrowStyle = STYLE::CLEAR;
else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSEDFILLED" ) )
ArrowStyle = STYLE::CLOSED_FILLED;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( arrowStyleStr, cNodeName );
}
else if( cNodeName == wxT( "ARROWANGLEA" ) )
{
UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
upperAngleInitialised = true;
}
else if( cNodeName == wxT( "ARROWANGLEB" ) )
{
UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
lowerAngleInitialised = true;
}
else
{
THROW_UNKNOWN_PARAMETER_IO_ERROR( cNodeName, wxT( "DIMARROW" ) );
}
}
if( !arrowStyleInitialised )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWSTYLE" ), wxT( "DIMARROW" ) );
if( !upperAngleInitialised )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEA" ), wxT( "DIMARROW" ) );
if( !lowerAngleInitialised )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEB" ), wxT( "DIMARROW" ) );
}
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::TEXTFORMAT::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "DIMTEXT" ) );
TextGap = GetXmlAttributeIDLong( aNode, 1 );
TextOffset = GetXmlAttributeIDLong( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
if( !cNode || cNode->GetName() != wxT( "TXTSTYLE" ) )
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "DIMTEXT" ) );
wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
Style = STYLE::INSIDE;
else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
Style = STYLE::OUTSIDE;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, wxT( "TXTSTYLE" ) );
CheckNoNextNodes( cNode );
}
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::EXTENSION_LINE::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "EXTLINE" ) );
LineCodeID = GetXmlAttributeIDString( aNode, 0 );
Overshoot = GetXmlAttributeIDLong( aNode, 3 );
Offset = GetXmlAttributeIDLong( aNode, 4 );
XNODE* cNode = aNode->GetChildren();
int noOfPoints = 0;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( noOfPoints < 2 && cNodeName == wxT( "PT" ) )
{
++noOfPoints;
if( noOfPoints == 1 )
Start.Parse( cNode, aContext );
else
End.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "SUPPRESSFIRST" ) )
{
SuppressFirst = true;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "EXTLINE" ) );
}
}
if( noOfPoints != 2 )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), wxT( "EXTLINE" ) );
}
bool CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::LINE::IsLine( XNODE* aNode )
{
if( aNode->GetName() == wxT( "LEADERLINE" ) || aNode->GetName() == wxT( "LINEARLINE" )
|| aNode->GetName() == wxT( "ANGULARLINE" ) )
{
return true;
}
else
{
return false;
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::LINE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( IsLine( aNode ) );
if( aNode->GetName() == wxT( "LINEARLINE" ) )
Type = TYPE::LINEARLINE;
else if( aNode->GetName() == wxT( "LEADERLINE" ) )
Type = TYPE::LEADERLINE;
else if( aNode->GetName() == wxT( "ANGULARLINE" ) )
Type = TYPE::ANGULARLINE;
else
wxASSERT_MSG( true, wxT( "Not a valid type. What happened to the node Name?" ) );
LineCodeID = GetXmlAttributeIDString( aNode, 0 );
if( Type == TYPE::LEADERLINE )
{
LeaderLineLength = GetXmlAttributeIDLong( aNode, 5 );
LeaderLineExtensionLength = GetXmlAttributeIDLong( aNode, 6 );
}
XNODE* cNode = aNode->GetChildren();
int noOfPoints = 0;
int requiredNoOfPoints = 2;
if( Type == TYPE::ANGULARLINE )
requiredNoOfPoints = 3;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "DIMLINETYPE" ) )
{
wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
Style = STYLE::INTERNAL;
else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
Style = STYLE::EXTERNAL;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, cNodeName );
}
else if( noOfPoints < requiredNoOfPoints && cNodeName == wxT( "PT" ) )
{
++noOfPoints;
if( noOfPoints == 1 )
Start.Parse( cNode, aContext );
else if( noOfPoints == 2 )
End.Parse( cNode, aContext );
else
Centre.Parse( cNode, aContext );
}
else if( Type == TYPE::LEADERLINE && cNodeName == wxT( "LEADERANG" ) )
{
LeaderAngle = GetXmlAttributeIDLong( cNode, 0 );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
if( noOfPoints != requiredNoOfPoints )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
}
bool CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::IsDimension( XNODE* aNode )
{
if( aNode->GetName() == wxT( "LINEARDIM" ) || aNode->GetName() == wxT( "LEADERDIM" )
|| aNode->GetName() == wxT( "ANGLEDIM" ) )
{
return true;
}
else
{
return false;
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( IsDimension( aNode ) );
std::map<wxString, TYPE> typeMap = { { wxT( "LINEARDIM" ), TYPE::LINEARDIM },
{ wxT( "LEADERDIM" ), TYPE::LEADERDIM }, { wxT( "ANGLEDIM" ), TYPE::ANGLEDIM } };
//make sure aNode is valid TYPE
wxASSERT_MSG( typeMap.find( aNode->GetName() ) != typeMap.end(),
wxT( "Not a valid type. What happened to the node Name?" ) );
Type = typeMap[aNode->GetName()];
LayerID = GetXmlAttributeIDString( aNode, 1 );
wxString subTypeStr = GetXmlAttributeIDString( aNode, 2 );
std::map<wxString, SUBTYPE> subTypeMap = {
{ wxT( "DIMENSION_ORTHOGONAL" ), SUBTYPE::ORTHOGONAL },
{ wxT( "DIMENSION_DIRECT" ), SUBTYPE::DIRECT },
{ wxT( "DIMENSION_ANGLED" ), SUBTYPE::ANGLED },
{ wxT( "DIMENSION_DIAMETER" ), SUBTYPE::DIAMETER },
{ wxT( "DIMENSION_RADIUS" ), SUBTYPE::RADIUS },
{ wxT( "DIMENSION_ANGULAR" ), SUBTYPE::ANGULAR } };
if( subTypeMap.find( subTypeStr ) == subTypeMap.end() )
THROW_UNKNOWN_PARAMETER_IO_ERROR( subTypeStr, aNode->GetName() );
Subtype = subTypeMap[subTypeStr];
Precision = GetXmlAttributeIDLong( aNode, 3 );
XNODE* cNode = aNode->GetChildren();
bool idParsed = false;
bool unitsParsed = false; //UNITS or ANGUNITS
bool arrowParsed = false;
bool textFormatParsed = false;
bool extLineParsed = false;
bool lineParsed = false;
bool textParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !idParsed && cNodeName == wxT( "DIMREF" ) )
{
ID = GetXmlAttributeIDString( cNode, 0 );
idParsed = true;
}
else if( !unitsParsed && cNodeName == wxT( "UNITS" ) )
{
LinearUnits = ParseUnits( cNode );
unitsParsed = true;
}
else if( !unitsParsed && cNodeName == wxT( "ANGUNITS" ) )
{
AngularUnits = ParseAngunits( cNode );
unitsParsed = true;
}
else if( !arrowParsed && cNodeName == wxT( "DIMARROW" ) )
{
Arrow.Parse( cNode, aContext );
arrowParsed = true;
}
else if( !textFormatParsed && cNodeName == wxT( "DIMTEXT" ) )
{
TextParams.Parse( cNode, aContext );
textFormatParsed = true;
}
else if( !extLineParsed && cNodeName == wxT( "EXTLINE" ) )
{
ExtensionLineParams.Parse( cNode, aContext );
extLineParsed = true;
}
else if( !lineParsed && LINE::IsLine( cNode ) )
{
Line.Parse( cNode, aContext );
lineParsed = true;
}
else if( !textParsed && cNodeName == wxT( "TEXT" ) )
{
// Do not parse the fields in dimension text (will be done when loading, if required)
Text.Parse( cNode, aContext, false );
textParsed = true;
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else if( cNodeName == wxT( "GROUPREF" ) )
{
GroupID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
{
ReuseBlockRef.Parse( cNode, aContext );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::SYMDEF_PCB::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
ParseIdentifiers( aNode, aContext );
wxString rest;
if( ReferenceName.StartsWith( wxT( "JUMPERNF" ), &rest ) )
Type = SYMDEF_TYPE::JUMPER;
else if( ReferenceName.StartsWith( wxT( "STARPOINTNF" ), &rest ) )
Type = SYMDEF_TYPE::STARPOINT;
else if( ReferenceName == wxT( "TESTPOINT" ) )
Type = SYMDEF_TYPE::TESTPOINT;
else
Type = SYMDEF_TYPE::COMPONENT;
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( ParseSubNode( cNode, aContext ) )
{
continue;
}
else if( cNodeName == wxT( "SYMHEIGHT" ) )
{
SymHeight = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "COMPCOPPER" ) )
{
COMPONENT_COPPER compcopper;
compcopper.Parse( cNode, aContext );
ComponentCoppers.push_back( compcopper );
}
else if( cNodeName == wxT( "COMPAREA" ) )
{
COMPONENT_AREA area;
area.Parse( cNode, aContext );
ComponentAreas.insert( std::make_pair( area.ID, area ) );
}
else if( cNodeName == wxT( "PAD" ) )
{
COMPONENT_PAD pad;
pad.Parse( cNode, aContext );
ComponentPads.insert( std::make_pair( pad.ID, pad ) );
}
else if( cNodeName == wxT( "DIMENSIONS" ) )
{
XNODE* dimensionNode = cNode->GetChildren();
for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
{
if( DIMENSION::IsDimension( dimensionNode ) )
{
DIMENSION dim;
dim.Parse( dimensionNode, aContext );
Dimensions.insert( std::make_pair( dim.ID, dim ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
}
}
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
if( !Stub && ( Origin.x == UNDEFINED_VALUE || Origin.y == UNDEFINED_VALUE ) )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
}
void CADSTAR_PCB_ARCHIVE_PARSER::LIBRARY::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "LIBRARY" ) );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "SYMDEF" ) )
{
SYMDEF_PCB symdef;
symdef.Parse( cNode, aContext );
ComponentDefinitions.insert( std::make_pair( symdef.ID, symdef ) );
}
else if( cNodeName == wxT( "HIERARCHY" ) )
{
// Ignore for now
//
// This node doesn't have any equivalent in KiCad so for now we ignore it. In
// future, we could parse it in detail, to obtain the tree-structure of
// footprints in a cadstar library
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
aContext->CheckPointCallback();
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::CADSTAR_BOARD::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "BOARD" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
bool shapeIsInitialised = false; // Stop more than one Shape Object
wxString location = wxString::Format( wxT( "BOARD %s" ), ID );
if( !cNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
{
Shape.Parse( cNode, aContext );
shapeIsInitialised = true;
}
else if( cNodeName == wxT( "ATTR" ) )
{
ATTRIBUTE_VALUE attr;
attr.Parse( cNode, aContext );
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else if( cNodeName == wxT( "GROUPREF" ) )
{
GroupID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
{
ReuseBlockRef.Parse( cNode, aContext );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::AREA::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "AREA" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
Name = GetXmlAttributeIDString( aNode, 2 );
LayerID = GetXmlAttributeIDString( aNode, 4 );
XNODE* cNode = aNode->GetChildren();
bool shapeIsInitialised = false; // Stop more than one Shape Object
wxString location = wxString::Format( wxT( "AREA %s" ), ID );
if( !cNode )
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
{
Shape.Parse( cNode, aContext );
shapeIsInitialised = true;
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else if( cNodeName == wxT( "USAGE" ) )
{
wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
{
if( !IsValidAttribute( xmlAttribute ) )
continue;
if( xmlAttribute->GetValue() == wxT( "PLACEMENT" ) )
Placement = true;
else if( xmlAttribute->GetValue() == wxT( "ROUTING" ) )
Routing = true;
else if( xmlAttribute->GetValue() == wxT( "KEEPOUT" ) )
Keepout = true;
else if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
NoTracks = true;
else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
NoVias = true;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
}
CheckNoChildNodes( cNode );
}
else if( cNodeName == wxT( "AREAHEIGHT" ) )
{
AreaHeight = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "GROUPREF" ) )
{
GroupID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
{
ReuseBlockRef.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "ATTR" ) )
{
ATTRIBUTE_VALUE attr;
attr.Parse( cNode, aContext );
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::PIN_ATTRIBUTE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "PINATTR" ) );
Pin = GetXmlAttributeIDLong( aNode, 0 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "ATTR" ) )
{
ATTRIBUTE_VALUE attrVal;
attrVal.Parse( cNode, aContext );
AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
}
else if( cNodeName == wxT( "TESTLAND" ) )
{
TestlandSide = ParseTestlandSide( cNode );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::PADEXCEPTION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "PADEXCEPTION" ) );
ID = GetXmlAttributeIDLong( aNode, 0 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "PADCODEREF" ) )
{
PadCode = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "EXITS" ) )
{
OverrideExits = true;
Exits.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "SIDE" ) )
{
OverrideSide = true;
Side = GetPadSide( GetXmlAttributeIDString( cNode, 0 ) );
}
else if( cNodeName == wxT( "ORIENT" ) )
{
OverrideOrientation = true;
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "COMP" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Name = GetXmlAttributeIDString( aNode, 1 );
PartID = GetXmlAttributeIDString( aNode, 2 );
SymdefID = GetXmlAttributeIDString( aNode, 3 );
XNODE* cNode = aNode->GetChildren();
bool originParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !originParsed && cNodeName == wxT( "PT" ) )
{
Origin.Parse( cNode, aContext );
originParsed = true;
}
else if( cNodeName == wxT( "GROUPREF" ) )
{
GroupID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
{
ReuseBlockRef.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "TESTPOINT" ) )
{
TestPoint = true;
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else if( cNodeName == wxT( "MIRROR" ) )
{
Mirror = true;
}
else if( cNodeName == wxT( "READABILITY" ) )
{
Readability = ParseReadability( cNode );
}
else if( cNodeName == wxT( "ORIENT" ) )
{
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "VCOMPMASTER" ) )
{
VariantParentComponentID = GetXmlAttributeIDString( cNode, 0 );
VariantID = GetXmlAttributeIDString( cNode, 1 );
}
else if( cNodeName == wxT( "TEXTLOC" ) )
{
TEXT_LOCATION textloc;
textloc.Parse( cNode, aContext );
TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
}
else if( cNodeName == wxT( "ATTR" ) )
{
ATTRIBUTE_VALUE attrVal;
attrVal.Parse( cNode, aContext );
AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
}
else if( cNodeName == wxT( "PINATTR" ) )
{
PIN_ATTRIBUTE pinAttr;
pinAttr.Parse( cNode, aContext );
PinAttributes.insert( std::make_pair( pinAttr.Pin, pinAttr ) );
}
else if( cNodeName == wxT( "COMPPINLABEL" ) )
{
PART_DEFINITION_PIN_ID pinID = GetXmlAttributeIDLong( cNode, 0 );
wxString pinLabel = GetXmlAttributeIDString( cNode, 1 );
PinLabels.insert( std::make_pair( pinID, pinLabel ) );
}
else if( cNodeName == wxT( "PADEXCEPTION" ) )
{
PADEXCEPTION padExcept;
padExcept.Parse( cNode, aContext );
PadExceptions.insert( std::make_pair( padExcept.ID, padExcept ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
if( !originParsed )
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
}
CADSTAR_PCB_ARCHIVE_PARSER::TESTLAND_SIDE CADSTAR_PCB_ARCHIVE_PARSER::ParseTestlandSide(
XNODE* aNode )
{
wxASSERT( aNode->GetName() == wxT( "TESTLAND" ) );
wxString side = GetXmlAttributeIDString( aNode, 0 );
if( side == wxT( "MIN_SIDE" ) )
return TESTLAND_SIDE::MIN;
else if( side == wxT( "MAX_SIDE" ) )
return TESTLAND_SIDE::MAX;
else if( side == wxT( "BOTH_SIDES" ) )
return TESTLAND_SIDE::BOTH;
else
THROW_UNKNOWN_PARAMETER_IO_ERROR( side, aNode->GetName() );
return TESTLAND_SIDE::NONE;
}
void CADSTAR_PCB_ARCHIVE_PARSER::TRUNK::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "TRUNK" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
Definition = GetXmlAttributeIDString( aNode, 1 );
}
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::PIN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "PIN" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
ComponentID = GetXmlAttributeIDString( aNode, 1 );
PadID = GetXmlAttributeIDLong( aNode, 2 );
CheckNoChildNodes( aNode );
}
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::JUNCTION_PCB::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
ParseIdentifiers( aNode, aContext );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
if( ParseSubNode( cNode, aContext ) )
continue;
else if( cNode->GetName() == wxT( "TRUNKREF" ) )
TrunkID = GetXmlAttributeIDString( cNode, 0 );
else
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::VIA::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "VIA" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
ViaCodeID = GetXmlAttributeIDString( aNode, 1 );
LayerPairID = GetXmlAttributeIDString( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "PT" ) )
Location.Parse( cNode, aContext );
else if( cNodeName == wxT( "FIX" ) )
Fixed = true;
else if( cNodeName == wxT( "GROUPREF" ) )
GroupID = GetXmlAttributeIDString( cNode, 0 );
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
ReuseBlockRef.Parse( cNode, aContext );
else if( cNodeName == wxT( "TESTLAND" ) )
TestlandSide = ParseTestlandSide( cNode );
else if( cNode->GetName() == wxT( "TRUNKREF" ) )
TrunkID = GetXmlAttributeIDString( cNode, 0 );
else
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::COPPER_TERMINAL::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "COPTERM" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
CopperID = GetXmlAttributeIDString( aNode, 1 );
CopperTermNum = GetXmlAttributeIDLong( aNode, 2 );
}
XNODE* CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::ROUTE_VERTEX::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "ROUTEWIDTH" ) );
RouteWidth = GetXmlAttributeIDLong( aNode, 0 );
XNODE* prevNode = aNode;
XNODE* nextNode = aNode->GetNext();
for( ; nextNode; nextNode = nextNode->GetNext() )
{
if( nextNode->GetName() == wxT( "FIX" ) )
{
Fixed = true;
}
else if( nextNode->GetName() == wxT( "TDROPATSTART" ) )
{
TeardropAtStart = true;
TeardropAtStartAngle = GetXmlAttributeIDLong( nextNode, 0 );
}
else if( nextNode->GetName() == wxT( "TDROPATEND" ) )
{
TeardropAtEnd = true;
TeardropAtEndAngle = GetXmlAttributeIDLong( nextNode, 0 );
}
else if( VERTEX::IsVertex( nextNode ) )
{
Vertex.Parse( nextNode, aContext );
}
else if( nextNode->GetName() == wxT( "ROUTEWIDTH" ) )
{
return prevNode;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( nextNode->GetName(), wxT( "ROUTE" ) );
}
prevNode = nextNode;
}
return prevNode;
}
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::ROUTE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "ROUTE" ) );
LayerID = GetXmlAttributeIDString( aNode, 0 );
//Parse child nodes
XNODE* cNode = aNode->GetChildren();
bool startPointParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !startPointParsed && cNodeName == wxT( "PT" ) )
{
startPointParsed = true;
StartPoint.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "ROUTEWIDTH" ) )
{
ROUTE_VERTEX rtVert;
cNode = rtVert.Parse( cNode, aContext );
RouteVertices.push_back( rtVert );
assert( cNode != nullptr );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "ROUTE" ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::CONNECTION_PCB::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
ParseIdentifiers( aNode, aContext );
//Parse child nodes
XNODE* cNode = aNode->GetChildren();
bool routeParsed = false; //assume only one route per connection
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( ParseSubNode( cNode, aContext ) )
{
continue;
}
else if( !Unrouted && !routeParsed && cNodeName == wxT( "ROUTE" ) )
{
Route.Parse( cNode, aContext );
routeParsed = true;
}
else if( !routeParsed && cNodeName == wxT( "UNROUTE" ) )
{
Unrouted = true;
UnrouteLayerID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNode->GetName() == wxT( "TRUNKREF" ) )
{
TrunkID = GetXmlAttributeIDString( cNode, 0 );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "CONN" ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
ParseIdentifiers( aNode, aContext );
//Parse child nodes
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "JPT" ) )
{
JUNCTION_PCB jpt;
jpt.Parse( cNode, aContext );
Junctions.insert( std::make_pair( jpt.ID, jpt ) );
}
else if( ParseSubNode( cNode, aContext ) )
{
continue;
}
else if( cNodeName == wxT( "PIN" ) )
{
PIN pin;
pin.Parse( cNode, aContext );
Pins.insert( std::make_pair( pin.ID, pin ) );
}
else if( cNodeName == wxT( "VIA" ) )
{
VIA via;
via.Parse( cNode, aContext );
Vias.insert( std::make_pair( via.ID, via ) );
}
else if( cNodeName == wxT( "COPTERM" ) )
{
COPPER_TERMINAL cterm;
cterm.Parse( cNode, aContext );
CopperTerminals.insert( std::make_pair( cterm.ID, cterm ) );
}
else if( cNodeName == wxT( "CONN" ) )
{
CONNECTION_PCB conn;
conn.Parse( cNode, aContext );
Connections.push_back( conn );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NET" ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::TEMPLATE::POURING::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "POURING" ) );
CopperCodeID = GetXmlAttributeIDString( aNode, 0 );
ReliefCopperCodeID = GetXmlAttributeIDString( aNode, 1 );
ClearanceWidth = GetXmlAttributeIDLong( aNode, 2 );
SliverWidth = GetXmlAttributeIDLong( aNode, 3 );
AdditionalIsolation = GetXmlAttributeIDLong( aNode, 4 );
ThermalReliefPadsAngle = GetXmlAttributeIDLong( aNode, 5 );
ThermalReliefViasAngle = GetXmlAttributeIDLong( aNode, 6 );
wxString MinIsolCopStr = GetXmlAttributeIDString( aNode, 7 );
if( MinIsolCopStr == wxT( "NONE" ) )
MinIsolatedCopper = UNDEFINED_VALUE;
else
MinIsolatedCopper = GetXmlAttributeIDLong( aNode, 7 );
wxString MinDisjCopStr = GetXmlAttributeIDString( aNode, 8 );
if( MinDisjCopStr == wxT( "NONE" ) )
MinDisjointCopper = UNDEFINED_VALUE;
else
MinDisjointCopper = GetXmlAttributeIDLong( aNode, 8 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "NOPINRELIEF" ) )
{
ThermalReliefOnPads = false;
}
else if( cNodeName == wxT( "NOVIARELIEF" ) )
{
ThermalReliefOnVias = false;
}
else if( cNodeName == wxT( "IGNORETRN" ) )
{
AllowInNoRouting = true;
}
else if( cNodeName == wxT( "BOXPINS" ) )
{
BoxIsolatedPins = true;
}
else if( cNodeName == wxT( "REGENERATE" ) )
{
AutomaticRepour = true;
}
else if( cNodeName == wxT( "AUTOROUTETARGET" ) )
{
TargetForAutorouting = true;
}
else if( cNodeName == wxT( "THERMALCUTOUT" ) )
{
ReliefType = RELIEF_TYPE::CUTOUTS;
}
else if( cNodeName == wxT( "FILLED" ) )
{
FillType = COPPER_FILL_TYPE::FILLED;
}
else if( cNodeName == wxT( "HATCHCODEREF" ) )
{
FillType = COPPER_FILL_TYPE::HATCHED;
HatchCodeID = GetXmlAttributeIDString( cNode, 0 );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "POURING" ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::TEMPLATE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "TEMPLATE" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
Name = GetXmlAttributeIDString( aNode, 2 );
NetID = GetXmlAttributeIDString( aNode, 3 );
LayerID = GetXmlAttributeIDString( aNode, 4 );
XNODE* cNode = aNode->GetChildren();
bool shapeParsed = false;
bool pouringParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !shapeParsed && SHAPE::IsShape( cNode ) )
{
Shape.Parse( cNode, aContext );
shapeParsed = true;
}
else if( !pouringParsed && cNodeName == wxT( "POURING" ) )
{
Pouring.Parse( cNode, aContext );
pouringParsed = true;
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else if( cNodeName == wxT( "GROUPREF" ) )
{
GroupID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
{
ReuseBlockRef.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "ATTR" ) )
{
ATTRIBUTE_VALUE attr;
attr.Parse( cNode, aContext );
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::COPPER::NETREF::COPPER_TERM::Parse( XNODE* aNode,
PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "TERM" ) );
ID = GetXmlAttributeIDLong( aNode, 0 );
XNODE* cNode = aNode->GetChildren();
bool locationParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !locationParsed && cNodeName == wxT( "PT" ) )
{
Location.Parse( cNode, aContext );
locationParsed = true;
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::COPPER::NETREF::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "NETREF" ) );
NetID = GetXmlAttributeIDString( aNode, 0 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "TERM" ) )
{
COPPER_TERM term;
term.Parse( cNode, aContext );
CopperTerminals.insert( std::make_pair( term.ID, term ) );
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NETREF" ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::COPPER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "COPPER" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
CopperCodeID = GetXmlAttributeIDString( aNode, 1 );
LayerID = GetXmlAttributeIDString( aNode, 2 );
XNODE* cNode = aNode->GetChildren();
bool shapeParsed = false;
bool netRefParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !shapeParsed && SHAPE::IsShape( cNode ) )
{
Shape.Parse( cNode, aContext );
shapeParsed = true;
}
else if( !netRefParsed && cNodeName == wxT( "NETREF" ) )
{
NetRef.Parse( cNode, aContext );
netRefParsed = true;
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else if( cNodeName == wxT( "GROUPREF" ) )
{
GroupID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
{
ReuseBlockRef.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "POURED" ) )
{
PouredTemplateID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "ATTR" ) )
{
ATTRIBUTE_VALUE attr;
attr.Parse( cNode, aContext );
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::DRILL_TABLE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "DRILLTABLE" ) );
ID = GetXmlAttributeIDString( aNode, 0 );
LayerID = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
bool positionParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !positionParsed && cNodeName == wxT( "PT" ) )
{
Position.Parse( cNode, aContext );
positionParsed = true;
}
else if( cNodeName == wxT( "ORIENT" ) )
{
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
}
else if( cNodeName == wxT( "MIRROR" ) )
{
Mirror = true;
}
else if( cNodeName == wxT( "FIX" ) )
{
Fixed = true;
}
else if( cNodeName == wxT( "READABILITY" ) )
{
Readability = ParseReadability( cNode );
}
else if( cNodeName == wxT( "GROUPREF" ) )
{
GroupID = GetXmlAttributeIDString( cNode, 0 );
}
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
{
ReuseBlockRef.Parse( cNode, aContext );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_PCB_ARCHIVE_PARSER::LAYOUT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "LAYOUT" ) );
XNODE* cNode = aNode->GetChildren();
bool netSynchParsed = false;
bool dimensionsParsed = false;
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( !netSynchParsed && cNodeName == wxT( "NETSYNCH" ) )
{
std::map<wxString, NETSYNCH> netSynchMap = { { wxT( "WARNING" ), NETSYNCH::WARNING },
{ wxT( "FULL" ), NETSYNCH::FULL } };
wxString nsString = GetXmlAttributeIDString( cNode, 0 );
if( netSynchMap.find( nsString ) == netSynchMap.end() )
THROW_UNKNOWN_PARAMETER_IO_ERROR( nsString, aNode->GetName() );
NetSynch = netSynchMap[nsString];
netSynchParsed = true;
}
else if( cNodeName == wxT( "GROUP" ) )
{
GROUP group;
group.Parse( cNode, aContext );
Groups.insert( std::make_pair( group.ID, group ) );
}
else if( cNodeName == wxT( "REUSEBLOCK" ) )
{
REUSEBLOCK reuseblock;
reuseblock.Parse( cNode, aContext );
ReuseBlocks.insert( std::make_pair( reuseblock.ID, reuseblock ) );
}
else if( cNodeName == wxT( "BOARD" ) )
{
CADSTAR_BOARD board;
board.Parse( cNode, aContext );
Boards.insert( std::make_pair( board.ID, board ) );
}
else if( cNodeName == wxT( "FIGURE" ) )
{
FIGURE figure;
figure.Parse( cNode, aContext );
Figures.insert( std::make_pair( figure.ID, figure ) );
}
else if( cNodeName == wxT( "AREA" ) )
{
AREA area;
area.Parse( cNode, aContext );
Areas.insert( std::make_pair( area.ID, area ) );
}
else if( cNodeName == wxT( "COMP" ) )
{
COMPONENT comp;
comp.Parse( cNode, aContext );
Components.insert( std::make_pair( comp.ID, comp ) );
}
else if( cNodeName == wxT( "TRUNK" ) )
{
TRUNK trunk;
trunk.Parse( cNode, aContext );
Trunks.insert( std::make_pair( trunk.ID, trunk ) );
}
else if( cNodeName == wxT( "NET" ) )
{
NET_PCB net;
net.Parse( cNode, aContext );
Nets.insert( std::make_pair( net.ID, net ) );
}
else if( cNodeName == wxT( "TEMPLATE" ) )
{
TEMPLATE temp;
temp.Parse( cNode, aContext );
Templates.insert( std::make_pair( temp.ID, temp ) );
}
else if( cNodeName == wxT( "COPPER" ) )
{
COPPER copper;
copper.Parse( cNode, aContext );
Coppers.insert( std::make_pair( copper.ID, copper ) );
}
else if( cNodeName == wxT( "TEXT" ) )
{
TEXT txt;
txt.Parse( cNode, aContext );
Texts.insert( std::make_pair( txt.ID, txt ) );
}
else if( cNodeName == wxT( "DOCSYMBOL" ) )
{
DOCUMENTATION_SYMBOL docsym;
docsym.Parse( cNode, aContext );
DocumentationSymbols.insert( std::make_pair( docsym.ID, docsym ) );
}
else if( !dimensionsParsed && cNodeName == wxT( "DIMENSIONS" ) )
{
XNODE* dimensionNode = cNode->GetChildren();
for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
{
if( DIMENSION::IsDimension( dimensionNode ) )
{
DIMENSION dim;
dim.Parse( dimensionNode, aContext );
Dimensions.insert( std::make_pair( dim.ID, dim ) );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
}
}
dimensionsParsed = true;
}
else if( cNodeName == wxT( "DRILLTABLE" ) )
{
DRILL_TABLE drilltable;
drilltable.Parse( cNode, aContext );
DrillTables.insert( std::make_pair( drilltable.ID, drilltable ) );
}
else if( cNodeName == wxT( "VHIERARCHY" ) )
{
VariantHierarchy.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "ERRORMARK" ) )
{
//ignore (this is a DRC error marker in cadstar)
continue;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
aContext->CheckPointCallback();
}
}