/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 Roberto Fernandez Bautista * Copyright (C) 2020-2021 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 . */ /** * @file cadstar_pcb_archive_parser.cpp * @brief Parses a CADSTAR PCB Archive file */ #include #include #include #include #include void CADSTAR_PCB_ARCHIVE_PARSER::Parse() { if( m_progressReporter ) m_progressReporter->BeginPhase( 0 ); // Read file XNODE* fileRootNode = LoadArchiveFile( Filename, wxT( "CADSTARPCB" ), m_progressReporter ); if( m_progressReporter ) { m_progressReporter->BeginPhase( 1 ); // Parse File std::vector subNodeChildrenToCount = { wxT( "LIBRARY" ), wxT( "PARTS" ), wxT( "LAYOUT" ) }; long numOfSteps = GetNumberOfStepsForReporting( fileRootNode, subNodeChildrenToCount ); m_progressReporter->SetMaxProgress( numOfSteps ); } m_context.CheckPointCallback = [&](){ checkPoint(); }; XNODE* cNode = fileRootNode->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( 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). CADSTAR libraries cannot yet be " "imported into KiCad." ) ); } 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 fileRootNode; } 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 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 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.IsFullySpecified() ) 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 { 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 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(); } }