KiCad PCB EDA Suite
Loading...
Searching...
No Matches
allegro_db.cpp
Go to the documentation of this file.
1/*
2* This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright Quilter
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/gpl-3.0.html
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include "convert/allegro_db.h"
25
26#include <set>
27
28#include <wx/log.h>
29
30#include <ki_exception.h>
31
33
34using namespace ALLEGRO;
35
36
37#define BLK_DATA( BLK, T ) static_cast<const BLOCK<T>&>( BLK ).GetData()
38
39
40static std::optional<uint32_t> GetBlockKey( const BLOCK_BASE& block )
41{
42 // clang-format off
43 switch( block.GetBlockType() )
44 {
45 case 0x01: return static_cast<const BLOCK<BLK_0x01_ARC>&>( block ).GetData().m_Key;
46 case 0x03: return static_cast<const BLOCK<BLK_0x03_FIELD>&>( block ).GetData().m_Key;
47 case 0x04: return static_cast<const BLOCK<BLK_0x04_NET_ASSIGNMENT>&>( block ).GetData().m_Key;
48 case 0x05: return static_cast<const BLOCK<BLK_0x05_TRACK>&>( block ).GetData().m_Key;
49 case 0x06: return static_cast<const BLOCK<BLK_0x06_COMPONENT>&>( block ).GetData().m_Key;
50 case 0x07: return static_cast<const BLOCK<BLK_0x07_COMPONENT_INST>&>( block ).GetData().m_Key;
51 case 0x08: return static_cast<const BLOCK<BLK_0x08_PIN_NUMBER>&>( block ).GetData().m_Key;
52 case 0x09: return static_cast<const BLOCK<BLK_0x09_FILL_LINK>&>( block ).GetData().m_Key;
53 case 0x0A: return static_cast<const BLOCK<BLK_0x0A_DRC>&>( block ).GetData().m_Key;
54 case 0x0C: return static_cast<const BLOCK<BLK_0x0C_PIN_DEF>&>( block ).GetData().m_Key;
55 case 0x0D: return static_cast<const BLOCK<BLK_0x0D_PAD>&>( block ).GetData().m_Key;
56 case 0x0E: return static_cast<const BLOCK<BLK_0x0E_RECT>&>( block ).GetData().m_Key;
57 case 0x0F: return static_cast<const BLOCK<BLK_0x0F_FUNCTION_SLOT>&>( block ).GetData().m_Key;
58 case 0x10: return static_cast<const BLOCK<BLK_0x10_FUNCTION_INST>&>( block ).GetData().m_Key;
59 case 0x11: return static_cast<const BLOCK<BLK_0x11_PIN_NAME>&>( block ).GetData().m_Key;
60 case 0x12: return static_cast<const BLOCK<BLK_0x12_XREF>&>( block ).GetData().m_Key;
61 case 0x14: return static_cast<const BLOCK<BLK_0x14_GRAPHIC>&>( block ).GetData().m_Key;
62 case 0x15:
63 case 0x16:
64 case 0x17: return static_cast<const BLOCK<BLK_0x15_16_17_SEGMENT>&>( block ).GetData().m_Key;
65 case 0x1B: return static_cast<const BLOCK<BLK_0x1B_NET>&>( block ).GetData().m_Key;
66 case 0x1C: return static_cast<const BLOCK<BLK_0x1C_PADSTACK>&>( block ).GetData().m_Key;
67 case 0x1D: return static_cast<const BLOCK<BLK_0x1D_CONSTRAINT_SET>&>( block ).GetData().m_Key;
68 case 0x1E: return static_cast<const BLOCK<BLK_0x1E_SI_MODEL>&>( block ).GetData().m_Key;
69 case 0x1F: return static_cast<const BLOCK<BLK_0x1F_PADSTACK_DIM>&>( block ).GetData().m_Key;
70 case 0x20: return static_cast<const BLOCK<BLK_0x20_UNKNOWN>&>( block ).GetData().m_Key;
71 case 0x21: return static_cast<const BLOCK<BLK_0x21_BLOB>&>( block ).GetData().m_Key;
72 case 0x22: return static_cast<const BLOCK<BLK_0x22_UNKNOWN>&>( block ).GetData().m_Key;
73 case 0x23: return static_cast<const BLOCK<BLK_0x23_RATLINE>&>( block ).GetData().m_Key;
74 case 0x24: return static_cast<const BLOCK<BLK_0x24_RECT>&>( block ).GetData().m_Key;
75 case 0x26: return static_cast<const BLOCK<BLK_0x26_MATCH_GROUP>&>( block ).GetData().m_Key;
76 case 0x28: return static_cast<const BLOCK<BLK_0x28_SHAPE>&>( block ).GetData().m_Key;
77 case 0x29: return static_cast<const BLOCK<BLK_0x29_PIN>&>( block ).GetData().m_Key;
78 case 0x2A: return static_cast<const BLOCK<BLK_0x2A_LAYER_LIST>&>( block ).GetData().m_Key;
79 case 0x2B: return static_cast<const BLOCK<BLK_0x2B_FOOTPRINT_DEF>&>( block ).GetData().m_Key;
80 case 0x2C: return static_cast<const BLOCK<BLK_0x2C_TABLE>&>( block ).GetData().m_Key;
81 case 0x2D: return static_cast<const BLOCK<BLK_0x2D_FOOTPRINT_INST>&>( block ).GetData().m_Key;
82 case 0x2E: return static_cast<const BLOCK<BLK_0x2E_CONNECTION>&>( block ).GetData().m_Key;
83 case 0x2F: return static_cast<const BLOCK<BLK_0x2F_UNKNOWN>&>( block ).GetData().m_Key;
84 case 0x30: return static_cast<const BLOCK<BLK_0x30_STR_WRAPPER>&>( block ).GetData().m_Key;
85 case 0x31: return static_cast<const BLOCK<BLK_0x31_SGRAPHIC>&>( block ).GetData().m_Key;
86 case 0x32: return static_cast<const BLOCK<BLK_0x32_PLACED_PAD>&>( block ).GetData().m_Key;
87 case 0x33: return static_cast<const BLOCK<BLK_0x33_VIA>&>( block ).GetData().m_Key;
88 case 0x34: return static_cast<const BLOCK<BLK_0x34_KEEPOUT>&>( block ).GetData().m_Key;
89 case 0x36: return static_cast<const BLOCK<BLK_0x36_DEF_TABLE>&>( block ).GetData().m_Key;
90 case 0x37: return static_cast<const BLOCK<BLK_0x37_PTR_ARRAY>&>( block ).GetData().m_Key;
91 case 0x38: return static_cast<const BLOCK<BLK_0x38_FILM>&>( block ).GetData().m_Key;
92 case 0x39: return static_cast<const BLOCK<BLK_0x39_FILM_LAYER_LIST>&>( block ).GetData().m_Key;
93 case 0x3A: return static_cast<const BLOCK<BLK_0x3A_FILM_LIST_NODE>&>( block ).GetData().m_Key;
94 case 0x3C: return static_cast<const BLOCK<BLK_0x3C_KEY_LIST>&>( block ).GetData().m_Key;
95 default: break;
96 }
97 // clang-format off
98
99 return std::nullopt;
100}
101
102
109static const DB_REF& GetPrimaryNext( const DB_OBJ& obj )
110{
111 return obj.GetNext();
112}
113
114
115uint32_t BLOCK_BASE::GetKey() const
116{
117 std::optional<uint32_t> key = GetBlockKey( *this );
118 return key.value_or( 0 );
119}
120
121
122std::string RESOLVABLE::DebugString() const
123{
124 std::string s = (m_Parent ? m_Parent->TypeName() : "<no parent>") + std::string(":") + (m_DebugName ? m_DebugName : "<unknown>");
125 return s;
126}
127
128
129bool DB_REF::Resolve( const DB_OBJ_RESOLVER& aResolver )
130{
131 if( m_TargetKey == m_EndKey )
132 {
133 m_Target = nullptr;
134 return true;
135 }
136
137 m_Target = aResolver.Resolve( m_TargetKey );
138
139 if( !m_Target )
140 {
141 // V18+ linked list sentinel keys are not in the DB but are valid
142 // null-reference targets (end-of-chain markers)
143 if( aResolver.IsSentinel( m_TargetKey ) )
144 {
145 return true;
146 }
147
148 wxLogTrace( "ALLEGRO_EXTRACT", "Failed to resolve DB_REF target key %#010x for %s",
149 m_TargetKey, m_DebugName ? m_DebugName : "<unknown>" );
150 }
151
152 return m_Target != nullptr;
153}
154
155
156bool DB_STR_REF::Resolve( const DB_OBJ_RESOLVER& aResolver )
157{
158 if( m_StringKey == 0 )
159 {
160 // Null string reference
161 m_String = nullptr;
162 return true;
163 }
164
165 m_String = aResolver.ResolveString( m_StringKey );
166
167 if( !m_String )
168 {
169 wxLogTrace( "ALLEGRO_EXTRACT", "Failed to resolve DB_STR_REF string key %#010x for %s", m_StringKey, m_DebugName ? m_DebugName : "<unknown>" );
170 }
171
172 return m_String != nullptr;
173}
174
175
177{
178 wxCHECK_MSG( m_NextRefGetter != nullptr, false, wxString::Format(
179 "%s: Must set m_NextRefGetter before resolving DB_REF_CHAIN", DebugString() ) );
180
181 if( m_Head == m_Tail )
182 {
183 return true;
184 }
185
186 if( m_Head == 0 )
187 {
188 // Empty chain
189 return true;
190 }
191
192 DB_OBJ* n = aResolver.Resolve( m_Head );
193 std::set<uint32_t> visitedKeys;
194
195 while( n != nullptr )
196 {
197 m_Chain.push_back( n );
198
199 const DB_REF& nextRef = m_NextRefGetter( *n );
200
201 const uint32_t nextKey = nextRef.m_TargetKey;
202
203 if( visitedKeys.count( nextKey ) > 0 )
204 {
205 THROW_IO_ERROR( wxString::Format( "Detected loop in DB_REF_CHAIN at key %#010x for %s",
206 nextKey, m_DebugName ? m_DebugName : "<unknown>" ) );
207 }
208 visitedKeys.insert( nextKey );
209
210 if( nextKey == m_Tail )
211 {
212 return true;
213 }
214
215 if( nextKey == 0 )
216 {
217 // Reached end of chain before tail
218 break;
219 }
220
221 n = aResolver.Resolve( nextKey );
222 }
223
224 // Ended before the tail
225 wxLogTrace( "ALLEGRO_EXTRACT", "Failed to resolve DB_REF_CHAIN up to tail %#010x for %s", m_Tail, m_DebugName ? m_DebugName : "<unknown>" );
226 return false;
227}
228
229
230void DB_REF_CHAIN::Visit( std::function<void ( const DB_OBJ& aObj )> aVisitor ) const
231{
232 for( const DB_OBJ* node : m_Chain )
233 {
234 aVisitor( *node );
235 }
236}
237
238
239void DB_REF_CHAIN::Visit( std::function<void ( DB_OBJ& aObj )> aVisitor )
240{
241 for( DB_OBJ* node : m_Chain )
242 {
243 aVisitor( *node );
244 }
245}
246
247
248void BRD_DB::ReserveCapacity( size_t aObjectCount, size_t aStringCount )
249{
250 // The object and strings count come from user input directly
251 // clamp them in case we get a gigantic number
252 aObjectCount = std::min( aObjectCount, static_cast<size_t>( 1e6 ) );
253 aStringCount = std::min( aStringCount, static_cast<size_t>( 1e6 ) );
254
255 m_Blocks.reserve( aObjectCount );
256 m_ObjectKeyMap.reserve( aObjectCount );
257 reserveObjects( aObjectCount );
258 m_StringTable.reserve( aStringCount );
259}
260
261
262void BRD_DB::InsertBlock( std::unique_ptr<BLOCK_BASE> aBlock )
263{
264 bool skipDbObj = false;
265
266 if( m_leanMode )
267 {
268 // Skip DB_OBJ creation for high-volume types that the BOARD_BUILDER accesses
269 // exclusively through raw BLOCK_BASE via m_ObjectKeyMap and LL_WALKER.
270 // Types like NET (0x1B) and FIELD (0x03) must still create DB_OBJ for VisitNets.
271 uint8_t t = aBlock->GetBlockType();
272 skipDbObj = ( t == 0x01 || t == 0x14 || t == 0x15 || t == 0x16 || t == 0x17 );
273 }
274
275 if( !skipDbObj )
276 {
277 std::unique_ptr<DB_OBJ> dbObj = m_ObjFactory.CreateObject( *aBlock );
278
279 if( dbObj )
280 AddObject( std::move( dbObj ) );
281 }
282
283 if( aBlock->GetKey() != 0 )
284 m_ObjectKeyMap[aBlock->GetKey()] = aBlock.get();
285
286 m_Blocks.push_back( std::move( aBlock ) );
287}
288
289std::unique_ptr<DB_OBJ> BRD_DB::OBJ_FACTORY::CreateObject( const BLOCK_BASE& aBlock ) const
290{
291 std::unique_ptr<DB_OBJ> obj;
292
293 switch( aBlock.GetBlockType() )
294 {
295 case 0x01:
296 {
297 const BLK_0x01_ARC& arcBlk = BLK_DATA( aBlock, BLK_0x01_ARC );
298 obj = std::make_unique<ARC>( arcBlk );
299 break;
300 }
301 case 0x03:
302 {
303 const BLK_0x03_FIELD& blk03 = BLK_DATA( aBlock, BLK_0x03_FIELD );
304 obj = std::make_unique<FIELD>( blk03 );
305 break;
306 }
307 case 0x04:
308 {
310 obj = std::make_unique<NET_ASSIGN>( m_brdDb, netBlk );
311 break;
312 }
313 case 0x05:
314 {
315 const BLK_0x05_TRACK& trackBlk = BLK_DATA( aBlock, BLK_0x05_TRACK );
316 obj = std::make_unique<TRACK>( m_brdDb, trackBlk );
317 break;
318 }
319 case 0x06:
320 {
321 const BLK_0x06_COMPONENT& compBlk = BLK_DATA( aBlock, BLK_0x06_COMPONENT );
322 obj = std::make_unique<COMPONENT>( m_brdDb, compBlk );
323 break;
324 }
325 case 0x07:
326 {
328 obj = std::make_unique<COMPONENT_INST>( strBlk );
329 break;
330 }
331 case 0x08:
332 {
333 const BLK_0x08_PIN_NUMBER& symbolBlk = BLK_DATA( aBlock, BLK_0x08_PIN_NUMBER );
334 obj = std::make_unique<PIN_NUMBER>( symbolBlk );
335 break;
336 }
337 case 0x0E:
338 {
339 const BLK_0x0E_RECT& pinBlk = BLK_DATA( aBlock, BLK_0x0E_RECT );
340 obj = std::make_unique<RECT_OBJ>( m_brdDb, pinBlk );
341 break;
342 }
343 case 0x0F:
344 {
345 const BLK_0x0F_FUNCTION_SLOT& funcSlotBlk = BLK_DATA( aBlock, BLK_0x0F_FUNCTION_SLOT );
346 obj = std::make_unique<FUNCTION_SLOT>( funcSlotBlk );
347 break;
348 }
349 case 0x10:
350 {
351 const BLK_0x10_FUNCTION_INST& funcInstBlk = BLK_DATA( aBlock, BLK_0x10_FUNCTION_INST );
352 obj = std::make_unique<FUNCTION_INSTANCE>( funcInstBlk );
353 break;
354 }
355 case 0x11:
356 {
357 const BLK_0x11_PIN_NAME& pinNameBlk = BLK_DATA( aBlock, BLK_0x11_PIN_NAME );
358 obj = std::make_unique<PIN_NAME>( pinNameBlk );
359 break;
360 }
361 case 0x12:
362 {
363 const BLK_0x12_XREF& blk = BLK_DATA( aBlock, BLK_0x12_XREF );
364 obj = std::make_unique<XREF_OBJ>( blk );
365 break;
366 }
367 case 0x14:
368 {
369 const BLK_0x14_GRAPHIC& lineBlk = BLK_DATA( aBlock, BLK_0x14_GRAPHIC );
370 obj = std::make_unique<GRAPHIC_SEG>( m_brdDb, lineBlk );
371 break;
372 }
373 case 0x15:
374 case 0x16:
375 case 0x17:
376 {
378 obj = std::make_unique<LINE>( seg );
379 break;
380 }
381 case 0x1b:
382 {
383 const BLK_0x1B_NET& netBlk = BLK_DATA( aBlock, BLK_0x1B_NET );
384 obj = std::make_unique<NET>( m_brdDb, netBlk );
385 break;
386 }
387 case 0x20:
388 {
389 const BLK_0x20_UNKNOWN& blk = BLK_DATA( aBlock, BLK_0x20_UNKNOWN );
390 obj = std::make_unique<UNKNOWN_0x20>( m_brdDb, blk );
391 break;
392 }
393 case 0x28:
394 {
395 const BLK_0x28_SHAPE& shapeBlk = BLK_DATA( aBlock, BLK_0x28_SHAPE );
396 obj = std::make_unique<SHAPE>( m_brdDb, shapeBlk );
397 break;
398 }
399 case 0x2b: // Footprint
400 {
402 obj = std::make_unique<FOOTPRINT_DEF>( m_brdDb, fpBlk );
403 break;
404 }
405 case 0x2d:
406 {
407 const BLK_0x2D_FOOTPRINT_INST& fpInstBlk = BLK_DATA( aBlock, BLK_0x2D_FOOTPRINT_INST );
408 obj = std::make_unique<FOOTPRINT_INSTANCE>( fpInstBlk );
409 break;
410 }
411 case 0x2e:
412 {
413 const BLK_0x2E_CONNECTION& padBlk = BLK_DATA( aBlock, BLK_0x2E_CONNECTION );
414 obj = std::make_unique<CONNECTION_OBJ>( m_brdDb, padBlk );
415 break;
416 }
417 case 0x32:
418 {
419 const BLK_0x32_PLACED_PAD& placedPadBlk = BLK_DATA( aBlock, BLK_0x32_PLACED_PAD );
420 obj = std::make_unique<PLACED_PAD>( m_brdDb, placedPadBlk );
421 break;
422 }
423 case 0x33:
424 {
425 const BLK_0x33_VIA& viaBlk = BLK_DATA( aBlock, BLK_0x33_VIA );
426 obj = std::make_unique<VIA>( m_brdDb, viaBlk );
427 break;
428 }
429 case 0x37:
430 {
431 const BLK_0x37_PTR_ARRAY& arrBlk = BLK_DATA( aBlock, BLK_0x37_PTR_ARRAY );
432 obj = std::make_unique<PTR_ARRAY>( m_brdDb, arrBlk );
433 break;
434 }
435 default:
436 break;
437 }
438
439 if( obj )
440 {
441 obj->m_Loc = DB_OBJ::FILE_LOC{ aBlock.GetOffset(), aBlock.GetBlockType() };
442 }
443
444 return obj;
445}
446
447
449{
450}
451
452
454{
455}
456
457
458void DB::AddObject( std::unique_ptr<DB_OBJ> aObject )
459{
460 m_Objects[aObject->GetKey()] = std::move( aObject );
461}
462
463
464DB_OBJ* DB::Resolve( uint32_t aKey ) const
465{
466 auto it = m_Objects.find( aKey );
467 if( it != m_Objects.end() )
468 {
469 return it->second.get();
470 }
471 return nullptr;
472}
473
474
475const wxString* DB::ResolveString( uint32_t aKey ) const
476{
477 auto it = m_StringTable.find( aKey );
478 if( it != m_StringTable.end() )
479 {
480 return &it->second;
481 }
482
483 return nullptr;
484}
485
486
488{
489 for( auto& [key, obj] : m_Objects )
490 {
491 obj->m_Valid = obj->ResolveRefs( *this );
492
493 if( !obj->m_Valid )
494 {
495 // If we can't resolve the references, the DB is invalid and we cannot easily continue
496 // as any references could explode later.
497 THROW_IO_ERROR( wxString::Format( "Failed to resolve references for object key %#010x", key ) );
498 }
499 }
500}
501
502
504{
505 for( auto& [key, obj] : m_Objects )
506 obj->m_Valid = obj->ResolveRefs( *this );
507}
508
509
511 std::function<const DB_REF&( const DB_OBJ& aObj )> aVisitor ) const
512{
513 const DB_OBJ* node = Resolve( aLList.m_Head );
514
515 size_t iterations = 0;
516
517 while( node )
518 {
519 const DB_REF& nextRef = aVisitor( *node );
520
521 if( !nextRef.m_Target && nextRef.m_TargetKey != aLList.m_Tail
522 && !IsSentinel( nextRef.m_TargetKey ) )
523 {
524 THROW_IO_ERROR( wxString::Format( "Unexpected end of linked list: could not find %#010x", nextRef.m_TargetKey ) );
525 }
526
527 if( iterations++ >= 1e6 )
528 {
529 THROW_IO_ERROR( wxString::Format( "Excessive list length: key was %#010x", nextRef.m_TargetKey ) );
530 }
531
532 node = nextRef.m_Target;
533 }
534}
535
536
537static bool CheckTypeIs( const DB_REF& aRef, DB_OBJ::TYPE_ID aType, bool aCanBeNull )
538{
539 if( aRef.m_Target == nullptr )
540 return aCanBeNull;
541
542 const DB_OBJ::TYPE_ID objType = aRef.m_Target->GetType();
543 return objType == aType;
544}
545
546static bool CheckTypeIsOneOf( const DB_REF& aRef, const std::vector<DB_OBJ::TYPE_ID>& aTypes, bool aCanBeNull )
547{
548 if( aRef.m_Target == nullptr )
549 return aCanBeNull;
550
551 const DB_OBJ::TYPE_ID objType = aRef.m_Target->GetType();
552 return std::find( aTypes.begin(), aTypes.end(), objType ) != aTypes.end();
553}
554
555
556// static DB_REF& FollowFootprintInstanceNext( DB_OBJ& aObj )
557// {
558// switch( aObj.GetType() )
559// {
560// case DB_OBJ::BRD_FP_INST:
561// return static_cast<const FOOTPRINT_INSTANCE&>(aObj).m_Next.m_TargetKey;
562// }
563// }
564
565
566ARC::ARC( const BLK_0x01_ARC& aBlk ) :
567 BRD_DB_OBJ( BRD_ARC, aBlk.m_Key, aBlk.m_Next ),
568 m_Parent( this, aBlk.m_Parent, "m_parent" )
569{
570}
571
572
573bool ARC::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
574{
575 bool ok = true;
576 // m_Parent may point to objects of types we don't parse, so don't fail if it can't be resolved.
577 m_Parent.Resolve( aResolver );
578 ok &= m_Next.Resolve( aResolver );
579
580 return ok;
581}
582
583
585 BRD_DB_OBJ( BRD_NET_ASSIGN, aBlk.m_Key, aBlk.m_Next ),
586 m_Net( this, aBlk.m_Net, "m_Net" ),
587 m_ConnItem( this, aBlk.m_ConnItem, "m_ConnItem" )
588{
589}
590
591
593{
594 bool ok = true;
595
596 ok &= m_Next.Resolve( aResolver );
597 ok &= m_Net.Resolve( aResolver );
598 ok &= m_ConnItem.Resolve( aResolver );
599
600 ok &= CheckTypeIs( m_Net, BRD_NET, false );
601
602 return ok;
603}
604
605
607{
608 if( m_Net.m_Target == nullptr )
609 {
610 THROW_IO_ERROR( wxString::Format( "NET_ASSIGN::GetNet: NET reference is null for key %#010x", m_Key ) );
611 }
612
613 return static_cast<const ALLEGRO::NET&>( *m_Net.m_Target );
614}
615
616
617TRACK::TRACK( const BRD_DB& aBrd, const BLK_0x05_TRACK& aBlk ):
618 BRD_DB_OBJ( BRD_TRACK, aBlk.m_Key, aBlk.m_Next )
619{
620}
621
622
623bool TRACK::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
624{
625 bool ok = true;
626
627 ok &= m_Next.Resolve( aResolver );
628
629 return ok;
630}
631
632
634 BRD_DB_OBJ( BRD_FIELD, aBlk.m_Key, aBlk.m_Next )
635{
636 m_SubType = aBlk.m_SubType;
637 m_Hdr1 = aBlk.m_Hdr1;
638 m_Hdr2 = aBlk.m_Hdr2;
639
640 switch ( aBlk.m_SubType )
641 {
642 case 0x68:
643 {
644 m_FieldValue = wxString(std::get<std::string>( aBlk.m_Substruct ) );
645 break;
646 }
647 case 0x66:
648 {
649 m_FieldValue = std::get<uint32_t>( aBlk.m_Substruct );
650 break;
651 }
652 }
653}
654
655
656const wxString& FIELD::ExpectString() const
657{
658 try
659 {
660 return std::get<wxString>( m_FieldValue );
661 }
662 catch( const std::bad_variant_access& )
663 {
664 THROW_IO_ERROR( "FIELD::ExpectString: Field value is not a string" );
665 }
666}
667
668
669std::optional<int> FIELD_LIST::GetOptFieldExpectInt( uint16_t aFieldCode ) const
670{
671 for( const DB_OBJ* obj : m_Chain.m_Chain )
672 {
673 // Some chains can contain non-FIELD objects like 0x30
674 // not clear if that is always true
675 if( !obj || obj->GetType() != BRD_FIELD )
676 continue;
677
678 const FIELD& field = static_cast<const FIELD&>( *obj );
679 if( field.m_Hdr1 == aFieldCode )
680 {
681 try
682 {
683 return std::get<uint32_t>( field.m_FieldValue );
684 }
685 catch( const std::bad_variant_access& )
686 {
687 THROW_IO_ERROR( wxString::Format( "FIELD code %#04x is not an integer (subtype: %#04x )", aFieldCode,
688 field.m_SubType ) );
689 }
690 }
691 }
692
693 return std::nullopt;
694}
695
696
697const wxString* FIELD_LIST::GetOptFieldExpectString( uint16_t aFieldCode ) const
698{
699 for( const DB_OBJ* obj : m_Chain.m_Chain )
700 {
701 // Some chains can contain non-FIELD objects like 0x30
702 // not clear if that is always true
703 if( !obj || obj->GetType() != BRD_FIELD)
704 continue;
705
706 const FIELD& field = static_cast<const FIELD&>( *obj );
707 if( field.m_Hdr1 == aFieldCode )
708 {
709 try
710 {
711 return &std::get<wxString>( field.m_FieldValue );
712 }
713 catch( const std::bad_variant_access& )
714 {
715 THROW_IO_ERROR( wxString::Format( "FIELD code %#04x is not a string (subtype: %#04x )", aFieldCode,
716 field.m_SubType ) );
717 }
718 }
719 }
720
721 return nullptr;
722}
723
724
725std::optional<std::variant<wxString, uint32_t>> FIELD_LIST::GetOptField( uint16_t aFieldCode ) const
726{
727 for( const DB_OBJ* obj : m_Chain.m_Chain )
728 {
729 if( !obj || obj->GetType() != BRD_FIELD )
730 continue;
731
732 const FIELD& field = static_cast<const FIELD&>( *obj );
733
734 if( field.m_Hdr1 == aFieldCode )
735 return field.m_FieldValue;
736 }
737
738 return std::nullopt;
739}
740
741
743 BRD_DB_OBJ( BRD_COMPONENT, aBlk.m_Key, aBlk.m_Next ),
744 m_CompDeviceType( this, aBlk.m_CompDeviceType, "m_CompDeviceType" ),
745 m_SymbolName( this, aBlk.m_SymbolName, "m_SymbolName" ),
746 m_Instances( this, aBlk.m_FirstInstPtr, aBlk.m_Key, "m_Instances" ),
747 m_PtrFunctionSlot( this, aBlk.m_PtrFunctionSlot, "m_PtrFunctionSlot" ),
748 m_PtrPinNumber( this, aBlk.m_PtrPinNumber, "m_PtrPinNumber" ),
749 m_Fields( this, aBlk.m_Fields, "m_Fields" )
750{
751 m_Instances.m_NextRefGetter = GetPrimaryNext;
752}
753
754
756{
757 bool ok = true;
758
759 ok &= m_Next.Resolve( aResolver );
760 ok &= m_CompDeviceType.Resolve( aResolver );
761 ok &= m_SymbolName.Resolve( aResolver );
762 ok &= m_Instances.Resolve( aResolver );
763 ok &= m_PtrFunctionSlot.Resolve( aResolver );
764 ok &= m_PtrPinNumber.Resolve( aResolver );
765 ok &= m_Fields.Resolve( aResolver );
766
768
769 return ok;
770}
771
772
774{
775 return m_CompDeviceType.m_String;
776}
777
778
781 m_TextStr( this, aBlk.m_RefDesStrPtr, "m_TextStr" ),
782 m_FunctionInst( this, aBlk.m_FunctionInstPtr, "m_FunctionInst" ),
783 m_X03Chain( this, aBlk.m_X03Ptr, aBlk.m_Key, "m_X03Chain" ),
784 m_Pads( this, aBlk.m_FirstPadPtr, aBlk.m_Key, "m_Pads" )
785{
786 m_Pads.m_NextRefGetter = []( const DB_OBJ& aObj ) -> const DB_REF&
787 {
788 const PLACED_PAD& pad = static_cast<const PLACED_PAD&>( aObj );
789 return pad.m_NextInCompInst;
790 };
791}
792
793
795{
796 bool ok = true;
797
798 ok &= m_TextStr.Resolve( aResolver );
799 ok &= m_Next.Resolve( aResolver );
800 ok &= m_FunctionInst.Resolve( aResolver );
801 ok &= m_Pads.Resolve( aResolver );
802
803 return ok;
804}
805
806
807const wxString* COMPONENT_INST::GetRefDesStr() const
808{
809 return m_TextStr.m_String;
810}
811
812
814{
815 if( m_FunctionInst.m_Target == nullptr )
816 {
817 THROW_IO_ERROR( "COMPONENT_INST::GetFunctionInstance: Null reference to FUNCTION_INSTANCE" );
818 }
819
820 return static_cast<const FUNCTION_INSTANCE&>( *m_FunctionInst.m_Target );
821}
822
823
825{
826 if( m_Next.m_Target == nullptr )
827 {
828 wxLogTrace( "ALLEGRO_EXTRACT", "COMPONENT_INST::GetNextInstance: Null m_Next reference for key %#010x", m_Key );
829 return nullptr;
830 }
831
832 // If the next is not a COMPONENT_INST, it's the end of the list
833 if( m_Next.m_Target->GetType() != BRD_COMPONENT_INST )
834 {
835 return nullptr;
836 }
837
838 return static_cast<const COMPONENT_INST*>( m_Next.m_Target );
839}
840
841
843 BRD_DB_OBJ( BRD_PIN_NUMBER, aBlk.m_Key, aBlk.m_Next ),
844 m_PinNumberStr( this, aBlk.GetStrPtr(), "m_PinNumberStr" ),
845 m_PinName( this, aBlk.m_PinNamePtr, "m_PinName" )
846{
847}
848
849
851{
852 bool ok = true;
853
854 ok &= m_Next.Resolve( aResolver );
855 ok &= m_PinNumberStr.Resolve( aResolver );
856 ok &= m_PinName.Resolve( aResolver );
857
858 ok &= CheckTypeIs( m_PinName, BRD_PIN_NAME, true );
859
860 return ok;
861}
862
863
864const wxString* PIN_NUMBER::GetNumber() const
865{
866 return m_PinNumberStr.m_String;
867}
868
869
871{
872 if( m_PinName.m_Target == nullptr )
873 {
874 return nullptr;
875 }
876
877 return static_cast<const PIN_NAME*>( m_PinName.m_Target );
878}
879
880
881RECT_OBJ::RECT_OBJ( const BRD_DB& aBrd, const BLK_0x0E_RECT& aBlk ) :
882 BRD_DB_OBJ( BRD_x0e_RECT, aBlk.m_Key, aBlk.m_Next )
883{
884 m_Rotation = EDA_ANGLE( static_cast<double>( aBlk.m_Rotation ) / 1000.0, DEGREES_T );
885}
886
887
889{
890 bool ok = true;
891
892 ok &= m_Next.Resolve( aResolver );
893
894 return ok;
895}
896
897
899 BRD_DB_OBJ( BRD_PIN_NAME, aBlk.m_Key, aBlk.m_Next ),
900 m_PinNameStr( this, aBlk.m_PinNameStrPtr, "m_PinNameStr" ),
901 m_PinNumber( this, aBlk.m_PinNumberPtr, "m_PinNumber" )
902{
903}
904
906{
907 bool ok = true;
908
909 ok &= m_PinNameStr.Resolve( aResolver );
910 ok &= m_Next.Resolve( aResolver );
911 ok &= m_PinNumber.Resolve( aResolver );
912
913 ok &= CheckTypeIs( m_PinNumber, BRD_PIN_NUMBER, true );
914
915 return ok;
916}
917
918
919const wxString* PIN_NAME::GetName() const
920{
921 return m_PinNameStr.m_String;
922}
923
924
926{
927 if( m_PinNumber.m_Target == nullptr )
928 {
929 return nullptr;
930 }
931
932 return static_cast<const PIN_NUMBER*>( m_PinNumber.m_Target );
933}
934
935
937 BRD_DB_OBJ( BRD_XREF, aBlk.m_Key, 0 ),
938 m_Ptr1( this, aBlk.m_Ptr1, "m_Ptr1" ),
939 m_Ptr2( this, aBlk.m_Ptr2, "m_Ptr2" ),
940 m_Ptr3( this, aBlk.m_Ptr3, "m_Ptr3" )
941{
942}
943
944
946{
947 // These pointers may point to objects we don't parse, so don't fail if resolution fails
948 m_Ptr1.Resolve( aResolver );
949 m_Ptr2.Resolve( aResolver );
950 m_Ptr3.Resolve( aResolver );
951
952 return true;
953}
954
955
957 BRD_DB_OBJ( BRD_GRAPHIC_SEG, aBlk.m_Key, aBlk.m_Next ),
958 m_Parent( this, aBlk.m_Parent, "m_Parent" ),
959 m_Segment( this, aBlk.m_SegmentPtr, "m_Segment" )
960{
961}
962
963
965{
966 bool ok = true;
967
968 ok &= m_Parent.Resolve( aResolver );
969 ok &= m_Next.Resolve( aResolver );
970 ok &= m_Segment.Resolve( aResolver );
971
973 {
974 BRD_LINE,
975 BRD_ARC,
976 },
977 false );
978
979 return ok;
980}
981
982
984 BRD_DB_OBJ( BRD_LINE, aBlk.m_Key, aBlk.m_Next ),
985 m_Parent( this, aBlk.m_Parent, "m_Parent" )
986{
987 m_Start.x = aBlk.m_StartX;
988 m_Start.y = aBlk.m_StartY;
989 m_End.x = aBlk.m_EndX;
990 m_End.y = aBlk.m_EndY;
991
992 m_Width = aBlk.m_Width;
993}
994
995
996bool LINE::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
997{
998 // m_Next may point to objects we don't parse (terminator values), so don't fail if it
999 // can't be resolved. Segments are iterated by following the parent SHAPE/TRACK.
1000 m_Next.Resolve( aResolver );
1001
1002 return true;
1003}
1004
1005
1007 BRD_DB_OBJ( BRD_FP_DEF, aBlk.m_Key, aBlk.m_Next ),
1008 m_FpStr( this, aBlk.m_FpStrRef, "m_FpStr" ),
1009 m_SymLibPath( this, aBlk.m_SymLibPathPtr, "m_SymLibPath" ),
1010 m_Instances( this, aBlk.m_FirstInstPtr, aBlk.m_Key, "m_Instances" )
1011{
1012 // 0x2Bs are linked together in a list from the board header
1013 m_Next.m_EndKey = aBrd.m_Header->m_LL_0x2B.m_Tail;
1014
1015 m_Instances.m_NextRefGetter = GetPrimaryNext;
1016}
1017
1018
1020{
1021 bool ok = true;
1022
1023 ok &= m_Next.Resolve( aResolver );
1024 ok &= m_FpStr.Resolve( aResolver );
1025
1026 // Follow the chain of 0x2Ds until we get back here
1027 ok &= m_Instances.Resolve( aResolver );
1028
1029 // Set backlink from instances to parent
1030 m_Instances.Visit( [&]( DB_OBJ& aObj )
1031 {
1032 if( aObj.GetType() != BRD_FP_INST )
1033 {
1034 wxLogTrace( "ALLEGRO_EXTRACT", "FOOTPRINT_DEF::ResolveRefs: Unexpected type in footprint instance chain: %d", static_cast<int>( aObj.GetType() ) );
1035 return;
1036 }
1037
1038 FOOTPRINT_INSTANCE& fpInst = static_cast<FOOTPRINT_INSTANCE&>( aObj );
1039 fpInst.m_Parent = this;
1040 } );
1041
1042 wxLogTrace( "ALLEGRO_EXTRACT", "Resolved %zu footprint instances for footprint def key %#010x", m_Instances.m_Chain.size(), GetKey() );
1043
1044 ok &= m_SymLibPath.Resolve( aResolver );
1045
1046 ok &= CheckTypeIs( m_Next, BRD_FP_DEF, true );
1047
1048 return ok;
1049}
1050
1051
1052const wxString* FOOTPRINT_DEF::GetLibPath() const
1053{
1054 if( m_SymLibPath.m_Target == nullptr )
1055 return nullptr;
1056
1057 const FIELD& symLibPath = static_cast<const FIELD&>( *m_SymLibPath.m_Target );
1058 return &symLibPath.ExpectString();
1059}
1060
1061
1063 BRD_DB_OBJ( BRD_FP_INST, aBlk.m_Key, aBlk.m_Next ),
1064 m_ComponentInstance( this, aBlk.GetInstRef(), "m_ComponentInstance" ),
1065 m_Pads( this, aBlk.m_FirstPadPtr, aBlk.m_Key, "m_Pads" ),
1066 m_Graphics( this, aBlk.m_GraphicPtr, aBlk.m_Key, "m_Graphics" )
1067{
1068 m_Pads.m_NextRefGetter = []( const DB_OBJ& aObj ) -> const DB_REF&
1069 {
1070
1071 if (aObj.GetType() != BRD_PLACED_PAD )
1072 {
1073 wxLogTrace( "ALLEGRO_EXTRACT", "FOOTPRINT_INSTANCE::m_Pads: Unexpected type in pad chain: %d", static_cast<int>( aObj.GetType() ) );
1074 return DB_NULLREF;
1075 }
1076
1077 return static_cast<const PLACED_PAD&>( aObj ).m_NextInFp;
1078 };
1079
1080 m_Graphics.m_NextRefGetter = GetPrimaryNext;
1081
1082 // This will be filled in by the 0x2B resolution
1083 m_Parent = nullptr;
1084
1085 m_X = aBlk.m_CoordX;
1086 m_Y = aBlk.m_CoordY;
1087 m_Rotation = aBlk.m_Rotation;
1088 m_Mirrored = ( aBlk.m_Layer != 0 );
1089}
1090
1091
1093{
1094 bool ok = true;
1095
1096 ok &= m_Next.Resolve( aResolver );
1097 ok &= m_ComponentInstance.Resolve( aResolver );
1098 ok &= m_Pads.Resolve( aResolver );
1099 ok &= m_Graphics.Resolve( aResolver );
1100
1102
1103 return ok;
1104}
1105
1106
1108{
1109 // The component instance is found in the 0x07 string ref
1110 // But it can be null (e.g. for dimensions)
1111 if( m_ComponentInstance.m_Target == nullptr )
1112 return nullptr;
1113
1114 const COMPONENT_INST* componentInstance = static_cast<const COMPONENT_INST*>( m_ComponentInstance.m_Target );
1115 return componentInstance;
1116}
1117
1118
1119
1120const wxString* FOOTPRINT_INSTANCE::GetName() const
1121{
1122 if( m_Parent == nullptr )
1123 return nullptr;
1124
1125 return m_Parent->m_FpStr.m_String;
1126}
1127
1128
1131 m_SlotName( this, aBlk.m_SlotName, "m_SlotName" ),
1132 m_Component( this, aBlk.m_Ptr0x06, "m_Component" ),
1133 m_PinName( this, aBlk.m_Ptr0x11, "m_PinName" )
1134{
1135}
1136
1137
1139{
1140 bool ok = true;
1141
1142 ok &= m_SlotName.Resolve( aResolver );
1143
1144 // m_Component may point to objects we don't parse, so don't fail if resolution fails
1145 m_Component.Resolve( aResolver );
1146
1147 ok &= m_PinName.Resolve( aResolver );
1148
1149 return ok;
1150}
1151
1152
1153const wxString* FUNCTION_SLOT::GetName() const
1154{
1155 return m_SlotName.m_String;
1156}
1157
1158
1161 m_Slot( this, aBlk.m_Slots, "m_Slot" ),
1162 m_Fields( this, aBlk.m_Fields, "m_Fields" ),
1163 m_FunctionName( this, aBlk.m_FunctionName, "m_FunctionName" ),
1164 m_ComponentInstance( this, aBlk.m_ComponentInstPtr, "m_ComponentInstance" )
1165{
1166}
1167
1168
1170{
1171 bool ok = true;
1172
1173 ok &= m_Slot.Resolve( aResolver );
1174 ok &= m_Fields.Resolve( aResolver );
1175 ok &= m_FunctionName.Resolve( aResolver );
1176 ok &= m_ComponentInstance.Resolve( aResolver );
1177
1178 return ok;
1179}
1180
1181
1182const wxString* FUNCTION_INSTANCE::GetName() const
1183{
1184 return m_FunctionName.m_String;
1185}
1186
1187
1189{
1190 if( m_ComponentInstance.m_Target == nullptr )
1191 {
1193 "FUNCTION_INSTANCE::GetComponentInstance: Null reference to COMPONENT_INST" );
1194 }
1195
1196 return static_cast<const COMPONENT_INST&>( *m_ComponentInstance.m_Target );
1197}
1198
1199
1201{
1202 if( m_Slot.m_Target == nullptr )
1203 {
1204 THROW_IO_ERROR( "FUNCTION_INSTANCE::GetFunctionSlot: Null reference to FUNCTION_SLOT" );
1205 }
1206
1207 return static_cast<const FUNCTION_SLOT&>( *m_Slot.m_Target );
1208}
1209
1210
1211NET::NET( const BRD_DB& aBrd, const BLK_0x1B_NET& aBlk ):
1212 BRD_DB_OBJ( BRD_NET, aBlk.m_Key, aBlk.m_Next ),
1213 m_NetNameStr( this, aBlk.m_NetName, "m_NetNameStr" ),
1214 m_NetAssignments( this, aBlk.m_Assignment, aBlk.m_Key, "m_NetAssignments" ),
1215 m_FieldsChain( this, aBlk.m_FieldsPtr, aBlk.m_Key, "m_FieldsChain" ),
1218{
1219 m_NetAssignments.m_NextRefGetter = GetPrimaryNext;
1220 m_FieldsChain.m_NextRefGetter = GetPrimaryNext;
1221
1222 // Unsure where status is stored; default to REGULAR
1223}
1224
1225
1226bool NET::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
1227{
1228 bool ok = true;
1229
1230 ok &= m_Next.Resolve( aResolver );
1231 ok &= m_NetNameStr.Resolve( aResolver );
1232 ok &= m_NetAssignments.Resolve( aResolver );
1233 ok &= m_FieldsChain.Resolve( aResolver );
1234 return ok;
1235}
1236
1237
1238const wxString* NET::GetName() const
1239{
1240 return m_NetNameStr.m_String;
1241}
1242
1243
1245{
1246 return m_Status;
1247}
1248
1249
1250const wxString* NET::GetLogicalPath() const
1251{
1252 return m_Fields.GetOptFieldExpectString( FIELD_KEYS::LOGICAL_PATH );
1253}
1254
1255
1256std::optional<int> NET::GetNetMinLineWidth() const
1257{
1258 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MIN_LINE_WIDTH );
1259}
1260
1261
1262std::optional<int> NET::GetNetMaxLineWidth() const
1263{
1264 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MAX_LINE_WIDTH );
1265}
1266
1267
1268std::optional<int> NET::GetNetMinNeckWidth() const
1269{
1270 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MIN_NECK_WIDTH );
1271}
1272
1273
1274std::optional<int> NET::GetNetMaxNeckLength() const
1275{
1276 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MAX_NECK_LENGTH );
1277}
1278
1279
1281 BRD_DB_OBJ( BRD_x20, aBlk.m_Key, aBlk.m_Next )
1282{
1283}
1284
1285
1287{
1288 // m_Next may point to objects we don't parse, so don't fail if it can't be resolved.
1289 m_Next.Resolve( aResolver );
1290
1291 return true;
1292}
1293
1294
1295SHAPE::SHAPE( const BRD_DB& aBrd, const BLK_0x28_SHAPE& aBlk ):
1296 BRD_DB_OBJ( BRD_SHAPE, aBlk.m_Key, aBlk.m_Next ),
1297 m_Segments( this, aBlk.m_FirstSegmentPtr, aBlk.m_Key, "m_Segments" )
1298{
1299 m_Segments.m_Tail = aBrd.m_Header->m_LL_Shapes.m_Tail;
1300 m_Segments.m_NextRefGetter = GetPrimaryNext;
1301}
1302
1303
1304bool SHAPE::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
1305{
1306 bool ok = true;
1307
1308 // m_Next may point to objects we don't parse, so don't fail if it can't be resolved.
1309 // The SHAPE linked list is used internally by Allegro but not needed for board building.
1310 m_Next.Resolve( aResolver );
1311
1312 ok &= m_Segments.Resolve( aResolver );
1313
1314 return ok;
1315}
1316
1317
1319 BRD_DB_OBJ( BRD_CONNECTION, aBlk.m_Key, aBlk.m_Next ),
1320 m_NetAssign( this, aBlk.m_NetAssignment, "m_NetAssign" ),
1321 m_Connection( this, aBlk.m_Connection, "m_Connection" ),
1322 m_Position( aBlk.m_CoordX, aBlk.m_CoordY )
1323{
1324}
1325
1326
1328{
1329 bool ok = true;
1330
1331 ok &= m_Next.Resolve( aResolver );
1332 ok &= m_NetAssign.Resolve( aResolver );
1333
1334 // m_Connection may point to objects we don't parse, so don't fail if resolution fails
1335 m_Connection.Resolve( aResolver );
1336
1337 return ok;
1338}
1339
1340
1342 BRD_DB_OBJ( BRD_PLACED_PAD, aBlk.m_Key, aBlk.m_Next ),
1343 m_NextInFp( this, aBlk.m_NextInFp, "m_NextInFp" ),
1344 m_NextInCompInst( this, aBlk.m_NextInCompInst, "m_NextInCompInst" ),
1345 m_NetAssign( this, aBlk.m_NetPtr, "m_NetAssign" ),
1346 m_PinNumber( this, aBlk.m_PtrPinNumber, "m_PinNumber" ),
1347 m_PinNumText( this, aBlk.m_NameText, "m_PinNumText" )
1348{
1349 m_Bounds = BOX2I(
1350 {aBlk.m_Coords[0], aBlk.m_Coords[1] },
1351 { aBlk.m_Coords[2], aBlk.m_Coords[3] }
1352 );
1353}
1354
1355
1357{
1358 bool ok = true;
1359
1360 ok &= m_Next.Resolve( aResolver );
1361 ok &= m_NextInFp.Resolve( aResolver );
1362 ok &= m_NextInCompInst.Resolve( aResolver );
1363 // ok &= m_Padstack.Resolve( aResolver );
1364 ok &= m_PinNumber.Resolve( aResolver );
1365 ok &= m_NetAssign.Resolve( aResolver );
1366
1367 ok &= CheckTypeIs( m_PinNumber, BRD_PIN_NUMBER, true );
1368
1369
1370 return ok;
1371}
1372
1373
1374const wxString* PLACED_PAD::GetPinNumber() const
1375{
1376 if( m_PinNumber.m_Target == nullptr )
1377 return nullptr;
1378
1379 return static_cast<const PIN_NUMBER*>( m_PinNumber.m_Target )->GetNumber();
1380}
1381
1382
1383const wxString* PLACED_PAD::GetPinName() const
1384{
1385 if( m_PinNumber.m_Target == nullptr )
1386 return nullptr;
1387
1388 const PIN_NUMBER* pinNumber = static_cast<const PIN_NUMBER*>( m_PinNumber.m_Target );
1389 const PIN_NAME* pinName = pinNumber->GetPinName();
1390
1391 if( pinName == nullptr )
1392 return nullptr;
1393
1394 return pinName->GetName();
1395}
1396
1397
1399{
1400 if( m_NetAssign.m_Target == nullptr )
1401 return nullptr;
1402
1403 const NET_ASSIGN* netAssign = static_cast<const NET_ASSIGN*>( m_NetAssign.m_Target );
1404
1405 return &netAssign->GetNet();
1406}
1407
1408
1409VIA::VIA( const BRD_DB& aBrd, const BLK_0x33_VIA& aBlk ):
1410 BRD_DB_OBJ( BRD_VIA, aBlk.m_Key, aBlk.m_Next ),
1411 m_NetAssign( this, aBlk.m_NetPtr, "m_NetAssign" )
1412{
1413}
1414
1415
1416bool VIA::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
1417{
1418 bool ok = true;
1419
1420 ok &= m_Next.Resolve( aResolver );
1421
1422 return ok;
1423}
1424
1425
1427 BRD_DB_OBJ( BRD_PTR_ARRAY, aBlk.m_Key, aBlk.m_Next ),
1428 m_Parent( this, aBlk.m_GroupPtr, "m_GroupPtr" )
1429{
1430 m_Ptrs.reserve( aBlk.m_Count );
1431 for( size_t i = 0; i < aBlk.m_Count; ++i )
1432 {
1433 m_Ptrs.emplace_back( this, aBlk.m_Ptrs[i], nullptr );
1434 }
1435}
1436
1437
1439{
1440 bool ok = true;
1441
1442 ok &= m_Next.Resolve( aResolver );
1443 ok &= m_Parent.Resolve( aResolver );
1444
1445 for( auto& ptr : m_Ptrs )
1446 {
1447 // These may point to objects we don't parse, so don't fail if resolution fails
1448 ptr.Resolve( aResolver );
1449 }
1450
1451 return ok;
1452}
1453
1454
1455static void collectSentinelKeys( const FILE_HEADER& aHeader, DB& aDb )
1456{
1457 auto addTail = [&]( const FILE_HEADER::LINKED_LIST& aLL )
1458 {
1459 aDb.AddSentinelKey( aLL.m_Tail );
1460 };
1461
1462 addTail( aHeader.m_LL_0x04 );
1463 addTail( aHeader.m_LL_0x06 );
1464 addTail( aHeader.m_LL_0x0C );
1465 addTail( aHeader.m_LL_Shapes );
1466 addTail( aHeader.m_LL_0x14 );
1467 addTail( aHeader.m_LL_0x1B_Nets );
1468 addTail( aHeader.m_LL_0x1C );
1469 addTail( aHeader.m_LL_0x24_0x28 );
1470 addTail( aHeader.m_LL_Unknown1 );
1471 addTail( aHeader.m_LL_0x2B );
1472 addTail( aHeader.m_LL_0x03_0x30 );
1473 addTail( aHeader.m_LL_0x0A );
1474 addTail( aHeader.m_LL_0x1D_0x1E_0x1F );
1475 addTail( aHeader.m_LL_Unknown2 );
1476 addTail( aHeader.m_LL_0x38 );
1477 addTail( aHeader.m_LL_0x2C );
1478 addTail( aHeader.m_LL_0x0C_2 );
1479 addTail( aHeader.m_LL_Unknown3 );
1480 addTail( aHeader.m_LL_0x36 );
1481 addTail( aHeader.GetUnknown5() );
1482 addTail( aHeader.m_LL_Unknown6 );
1483 addTail( aHeader.m_LL_0x0A_2 );
1484
1485 if( aHeader.m_LL_V18_1.has_value() )
1486 {
1487 addTail( aHeader.m_LL_V18_1.value() );
1488 addTail( aHeader.m_LL_V18_2.value() );
1489 addTail( aHeader.m_LL_V18_3.value() );
1490 addTail( aHeader.m_LL_V18_4.value() );
1491 addTail( aHeader.m_LL_V18_5.value() );
1492 addTail( aHeader.m_LL_V18_6.value() );
1493 }
1494}
1495
1496
1499 m_ObjFactory( *this ),
1500 m_leanMode( false )
1501{
1502}
1503
1504
1506{
1507 if( m_FmtVer >= FMT_VER::V_180 )
1508 collectSentinelKeys( *m_Header, *this );
1509
1510 if( m_leanMode )
1511 {
1512 // In lean mode, DB_OBJ was not created for high-volume types (segments, graphics,
1513 // arcs). Other DB_OBJ types that reference those keys will fail to resolve, so we
1514 // attempt best-effort resolution. The NET and FIELD objects the builder needs only
1515 // reference each other and will resolve correctly.
1517 return true;
1518 }
1519
1520 // Try strict resolution first. If it fails (some boards have object types the parser
1521 // doesn't fully support), fall back to best-effort which allows partial imports.
1522 try
1523 {
1525 }
1526 catch( const IO_ERROR& e )
1527 {
1528 wxLogTrace( "ALLEGRO_EXTRACT",
1529 "Strict reference resolution failed (%s), retrying with best-effort",
1530 e.Problem() );
1531
1533 }
1534
1535 return true;
1536}
1537
1538
1540{
1541 const auto fpDefNextFunc = [&]( const DB_OBJ& aObj ) -> const DB_REF&
1542 {
1543 if( aObj.GetType() != BRD_FP_DEF )
1544 return DB_NULLREF;
1545
1546 const FOOTPRINT_DEF& fpDef = static_cast<const FOOTPRINT_DEF&>( aObj );
1547
1548 aVisitor( fpDef );
1549
1550 return fpDef.m_Next;
1551 };
1552
1553 visitLinkedList( m_Header->m_LL_0x2B, fpDefNextFunc );
1554}
1555
1556
1558{
1559 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting footprint instances for footprint def key %#010x", aFpDef.GetKey() );
1560
1561 VIEW_OBJS viewObjs;
1562 viewObjs.m_Board = this;
1563
1564 const auto fpInstNextFunc = [&]( const DB_OBJ& aObj )
1565 {
1566 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting footprint instance key %#010x", aObj.GetKey() );
1567 if( aObj.GetType() != BRD_FP_INST )
1568 {
1569 wxLogTrace( "ALLEGRO_EXTRACT", " Not a footprint instance, skipping key %#010x", aObj.GetKey() );
1570 return;
1571 }
1572
1573 const FOOTPRINT_INSTANCE& fpInst = static_cast<const FOOTPRINT_INSTANCE&>( aObj );
1574
1575 // viewObjs.m_FootprintDef = &aFpDef;
1576 viewObjs.m_FootprintInstance = &fpInst;
1577
1578 const COMPONENT_INST* componentInstance = fpInst.GetComponentInstance();
1579 if( componentInstance )
1580 {
1581 viewObjs.m_Function = &componentInstance->GetFunctionInstance();
1582 viewObjs.m_Component = componentInstance->GetParentComponent();
1583 }
1584
1585 aVisitor( viewObjs );
1586 };
1587
1588 aFpDef.m_Instances.Visit( fpInstNextFunc );
1589}
1590
1591
1593{
1594 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting footprint instances" );
1595
1596 VIEW_OBJS viewObjs;
1597 viewObjs.m_Board = this;
1598
1599 // And now visit all the footprint instances, and then visit each field on each one
1601 [&]( const FOOTPRINT_DEF& aFpDef )
1602 {
1603 visitFootprintInstances( aFpDef, aVisitor );
1604 } );
1605}
1606
1607
1609{
1610 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting function instances" );
1611
1612 const auto componentVisitor = [&]( const VIEW_OBJS& aViewObjs )
1613 {
1614 aVisitor( aViewObjs );
1615 };
1616
1617 // When is FUNCTION != COMPONENT? how should we iterate this?
1618 VisitComponents( componentVisitor );
1619}
1620
1621
1623{
1624 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting components" );
1625
1626 VIEW_OBJS viewObjs;
1627
1628 viewObjs.m_Board = this;
1629
1630 const auto x06NextFunc = [&]( const DB_OBJ& aObj ) -> const DB_REF&
1631 {
1632 if( aObj.GetType() != BRD_COMPONENT )
1633 {
1634 wxLogTrace( "ALLEGRO_EXTRACT", " Not a component object, skipping key %#010x", aObj.GetKey() );
1635 return DB_NULLREF;
1636 }
1637
1638 const COMPONENT& component = static_cast<const COMPONENT&>( aObj );
1639
1640 viewObjs.m_Component = &component;
1641
1642 const auto compInstVisitor = [&]( const DB_OBJ& aCompInst )
1643 {
1644 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting component instance key %#010x", aCompInst.GetKey() );
1645
1646 if( aCompInst.GetType() != BRD_COMPONENT_INST )
1647 {
1648 wxLogTrace( "ALLEGRO_EXTRACT", " Not a component instance, skipping key %#010x", aCompInst.GetKey() );
1649 return;
1650 }
1651
1652 const COMPONENT_INST& compInst = static_cast<const COMPONENT_INST&>( aCompInst );
1653
1654 const FUNCTION_INSTANCE& funcInst = compInst.GetFunctionInstance();
1655 viewObjs.m_ComponentInstance = &compInst;
1656 viewObjs.m_Function = &funcInst;
1657
1658 aVisitor( viewObjs );
1659 };
1660
1661 component.m_Instances.Visit( compInstVisitor );
1662
1663 return component.m_Next;
1664 };
1665
1666 visitLinkedList( m_Header->m_LL_0x06, x06NextFunc );
1667}
1668
1669
1671{
1672 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting component pins" );
1673
1674 const auto componentVisitor = [&]( const VIEW_OBJS& aViewObjs )
1675 {
1676 // For each footprint instance, visit all the pins of the component
1677 const COMPONENT_INST* compInst = aViewObjs.m_ComponentInstance;
1678
1679 if( compInst == nullptr )
1680 {
1681 wxLogTrace( "ALLEGRO_EXTRACT", " No component instance in view objs, skipping" );
1682 return;
1683 }
1684
1685 const auto padVisitor = [&]( const DB_OBJ& aObj )
1686 {
1687 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting pad key %#010x", aObj.GetKey() );
1688 if( aObj.GetType() != BRD_PLACED_PAD )
1689 {
1690 wxLogTrace( "ALLEGRO_EXTRACT", " Not a placed pad, skipping key %#010x, type", aObj.GetKey() );
1691 return;
1692 }
1693
1694 const PLACED_PAD& placedPad = static_cast<const PLACED_PAD&>( aObj );
1695
1696 VIEW_OBJS viewObj = aViewObjs;
1697 viewObj.m_Pad = &placedPad;
1698 viewObj.m_Net = placedPad.GetNet();
1699
1700 aVisitor( viewObj );
1701 };
1702
1703 compInst->m_Pads.Visit( padVisitor );
1704 };
1705
1706 VisitComponents( componentVisitor );
1707}
1708
1709
1711{
1712 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting nets" );
1713
1714 VIEW_OBJS viewObjs;
1715 viewObjs.m_Board = this;
1716
1717 const auto netNextFunc = [&]( const DB_OBJ& aObj ) -> const DB_REF&
1718 {
1719 if( aObj.GetType() != BRD_NET )
1720 {
1721 wxLogTrace( "ALLEGRO_EXTRACT", " Not a net object, skipping key %#010x", aObj.GetKey() );
1722 return DB_NULLREF;
1723 }
1724
1725 const NET& net = static_cast<const NET&>( aObj );
1726
1727 viewObjs.m_Net = &net;
1728
1729 aVisitor( viewObjs );
1730
1731 return net.m_Next;
1732 };
1733
1734 visitLinkedList( m_Header->m_LL_0x1B_Nets, netNextFunc );
1735}
1736
1737
1739{
1740 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting connected geometry" );
1741
1742 VIEW_OBJS viewObjs;
1743 viewObjs.m_Board = this;
1744
1745 const auto netVisitor = [&]( const VIEW_OBJS& aViewObjs )
1746 {
1747 // const NET& net = *aViewObjs.m_Net;
1748
1749 // const NET_ASSIGN* netAssign = net.GetAssignment();
1750
1751 // if( netAssign == nullptr )
1752 // {
1753 // wxLogTrace( "ALLEGRO_EXTRACT", " Net %#010x has no assignment, skipping", net.GetKey() );
1754 // return;
1755 // }
1756 };
1757
1758 VisitNets( netVisitor );
1759}
static uint32_t GetPrimaryNext(const BLOCK_BASE &aBlock)
Gets the next block in the linked list.
static const DB_REF & GetPrimaryNext(const DB_OBJ &obj)
Next ref getter for any chain where all objects uses the default "next" field.
static void collectSentinelKeys(const FILE_HEADER &aHeader, DB &aDb)
static bool CheckTypeIsOneOf(const DB_REF &aRef, const std::vector< DB_OBJ::TYPE_ID > &aTypes, bool aCanBeNull)
static bool CheckTypeIs(const DB_REF &aRef, DB_OBJ::TYPE_ID aType, bool aCanBeNull)
#define BLK_DATA(BLK, T)
static std::optional< uint32_t > GetBlockKey(const BLOCK_BASE &block)
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
The base class for all blocks in the main body of an Allegro file.
uint32_t GetKey() const
uint8_t GetBlockType() const
std::unique_ptr< DB_OBJ > CreateObject(const BLOCK_BASE &aBlock) const
An Allegro database that represents a .brd file (amd presumably .dra)
Definition allegro_db.h:948
void VisitConnectedGeometry(VIEW_OBJS_VISITOR aVisitor) const
std::unordered_map< uint32_t, BLOCK_BASE * > m_ObjectKeyMap
std::unique_ptr< FILE_HEADER > m_Header
std::vector< std::unique_ptr< BLOCK_BASE > > m_Blocks
void visitFootprintInstances(const FOOTPRINT_DEF &aFpDef, VIEW_OBJS_VISITOR aVisitor) const
void VisitNets(VIEW_OBJS_VISITOR aVisitor) const
void VisitFunctionInstances(VIEW_OBJS_VISITOR aVisitor) const
Access the function instances in the database.
std::function< void(const FOOTPRINT_DEF &aFpDef)> FP_DEF_VISITOR
Definition allegro_db.h:999
void VisitFootprintDefs(FP_DEF_VISITOR aFpDef) const
Access the footprint defs in the database.
void ReserveCapacity(size_t aObjectCount, size_t aStringCount)
Pre-allocate storage for the expected number of objects and strings.
bool ResolveAndValidate()
Iterate all the links we know about and fill in the object links.
void VisitComponents(VIEW_OBJS_VISITOR aVisitor) const
OBJ_FACTORY m_ObjFactory
void VisitFootprintInstances(VIEW_OBJS_VISITOR aVisitor) const
Access the footprint instances in the database.
void InsertBlock(std::unique_ptr< BLOCK_BASE > aBlock) override
void VisitComponentPins(VIEW_OBJS_VISITOR aVisitor) const
Visit all component pins in the database.
Some interface that can yield DB_OBJs for keys.
Definition allegro_db.h:145
virtual DB_OBJ * Resolve(uint32_t aKey) const =0
Resolve the given reference.
virtual bool IsSentinel(uint32_t aKey) const
In v18+ files, linked list sentinel nodes are real blocks with small keys.
Definition allegro_db.h:160
virtual const wxString * ResolveString(uint32_t aKey) const =0
An ALLEGRO::DB is the represention of the actual data stored within an Allegro file,...
Definition allegro_db.h:249
const wxString * ResolveString(uint32_t aRef) const override
std::unordered_map< uint32_t, wxString > m_StringTable
Definition allegro_db.h:313
void AddObject(std::unique_ptr< DB_OBJ > aObject)
void ResolveObjectLinksBestEffort()
Resolve all DB_OBJ references without throwing on failure.
std::unordered_map< uint32_t, std::unique_ptr< DB_OBJ > > m_Objects
Definition allegro_db.h:307
void AddSentinelKey(uint32_t aKey)
Definition allegro_db.h:285
void visitLinkedList(const FILE_HEADER::LINKED_LIST aLList, std::function< const DB_REF &(const DB_OBJ &aObj)> aVisitor) const
bool IsSentinel(uint32_t aKey) const override
In v18+ files, linked list sentinel nodes are real blocks with small keys.
Definition allegro_db.h:280
void ResolveObjectLinks()
Iterate the database and resolve links.
DB_OBJ * Resolve(uint32_t aRef) const override
Implement the object resolver interface.
void reserveObjects(size_t aCount)
Definition allegro_db.h:297
std::optional< int > GetOptFieldExpectInt(uint16_t aFieldCode) const
Get the integer value of the field with the given code, if in the list.
DB_REF_CHAIN & m_Chain
Definition allegro_db.h:458
const wxString * GetOptFieldExpectString(uint16_t aFieldCode) const
std::optional< std::variant< wxString, uint32_t > > GetOptField(uint16_t aFieldCode) const
Get the raw variant value of the field with the given code, if present.
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
DB_REF_CHAIN m_Segments
Definition allegro_db.h:766
SHAPE(const BRD_DB &aBrd, const BLK_0x28_SHAPE &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
UNKNOWN_0x20(const BRD_DB &aBrd, const BLK_0x20_UNKNOWN &aBlk)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString Problem() const
what was the problem?
@ DEGREES_T
Definition eda_angle.h:31
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
std::function< void(const VIEW_OBJS &aViewObjs)> VIEW_OBJS_VISITOR
Definition allegro_db.h:941
static DB_REF DB_NULLREF
Definition allegro_db.h:85
FMT_VER
The format of an Allego file.
@ BRD_FP_INST
Definition allegro_db.h:337
@ BRD_FUNCTION_SLOT
Definition allegro_db.h:327
@ BRD_PLACED_PAD
Definition allegro_db.h:339
@ BRD_NET_ASSIGN
Definition allegro_db.h:322
@ BRD_GRAPHIC_SEG
Definition allegro_db.h:331
@ BRD_COMPONENT
Definition allegro_db.h:323
@ BRD_FUNCTION_INST
Definition allegro_db.h:328
@ BRD_x0e_RECT
Definition allegro_db.h:326
@ BRD_COMPONENT_INST
Definition allegro_db.h:324
@ BRD_PIN_NAME
Definition allegro_db.h:329
@ BRD_PTR_ARRAY
Definition allegro_db.h:344
@ BRD_PIN_NUMBER
Definition allegro_db.h:325
@ BRD_CONNECTION
Definition allegro_db.h:338
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
ARC(const BLK_0x01_ARC &aBlk)
DB_REF m_Parent
Definition allegro_db.h:396
Arc segment used in tracks, zone outlines, and shape boundaries.
Field/property references with variable-typed substructs.
Net assignment linking a net (0x1B) to its member objects.
Track segment container.
Component/symbol definitions.
Component instance reference data.
Pin number within a component.
uint32_t m_Rotation
Rotation in millidegrees.
Function slot in a multi-slot component (e.g.
Function instance linking a component instance (0x07) to its schematic function, pin cross-references...
Pin name within a component, linked from function slots (0x0F).
Cross-reference between objects.
Graphics container holding a chain of line segments and arcs.
0x15 , 0x16, 0x17 are segments:
0x1B objects are nets.
Polygon shape defined by a linked list of segments starting at m_FirstSegmentPtr (0x15/0x16/0x17 line...
Footprint definition (template) shared by multiple placed instances.
Placed footprint instance on the board.
uint32_t m_Rotation
Millidegrees (divide by 1000 for degrees)
Connection point at a track junction or pad-to-track transition.
Placed pad instance linking a pad definition (0x0D via m_PadPtr) to its parent footprint (m_ParentFp)...
std::array< int32_t, 4 > m_Coords
Via instance with board position, padstack reference (m_Padstack for drill/annular ring definitions),...
Fixed-capacity pointer array (100 entries).
BRD_DB_OBJ(BRD_TYPE aType, uint32_t aKey, uint32_t aNextKey)
Definition allegro_db.h:353
COMPONENT_INST 0x07 objects.
Definition allegro_db.h:525
const wxString * GetRefDesStr() const
const COMPONENT_INST * GetNextInstance() const
COMPONENT_INST(const BLK_0x07_COMPONENT_INST &aBlk)
const COMPONENT * GetParentComponent() const
Definition allegro_db.h:539
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
const FUNCTION_INSTANCE & GetFunctionInstance() const
DB_REF_CHAIN m_X03Chain
Definition allegro_db.h:534
COMPONENT 0x06 objects.
Definition allegro_db.h:500
const wxString * GetComponentDeviceType() const
DB_REF_CHAIN m_Instances
Definition allegro_db.h:509
DB_STR_REF m_SymbolName
Definition allegro_db.h:508
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
DB_STR_REF m_CompDeviceType
Definition allegro_db.h:507
COMPONENT(const BRD_DB &aBrd, const BLK_0x06_COMPONENT &aBlk)
CONNECTION_OBJ(const BRD_DB &aBrd, const BLK_0x2E_CONNECTION &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
A DB_OBJ represents one object in an Allegro database.
Definition allegro_db.h:168
uint32_t GetKey() const
Definition allegro_db.h:219
virtual TYPE_ID GetType() const =0
All blocks are denoted by a type which allows dispatch to the appropriate subclass.
virtual const DB_REF & GetNext() const
Return the reference to the next object in the default chain for this object.
Definition allegro_db.h:227
std::vector< DB_OBJ * > m_Chain
Definition allegro_db.h:120
void Visit(std::function< void(const DB_OBJ &aObj)> aVisitor) const
Visit all objects in the chain.
std::function< const DB_REF &(const DB_OBJ &)> m_NextRefGetter
Definition allegro_db.h:113
bool Resolve(const DB_OBJ_RESOLVER &aResolver) override
uint32_t m_EndKey
Definition allegro_db.h:81
uint32_t m_TargetKey
Definition allegro_db.h:76
DB_OBJ * m_Target
Definition allegro_db.h:82
bool Resolve(const DB_OBJ_RESOLVER &aResolver) override
const wxString * m_String
Definition allegro_db.h:136
bool Resolve(const DB_OBJ_RESOLVER &aResolver) override
0x03 FIELD objects
Definition allegro_db.h:410
uint32_t m_Hdr2
Definition allegro_db.h:421
uint8_t m_SubType
Definition allegro_db.h:417
const wxString & ExpectString() const
uint32_t m_Hdr1
Definition allegro_db.h:420
std::variant< wxString, uint32_t > m_FieldValue
Definition allegro_db.h:423
FIELD(const BLK_0x03_FIELD &aBlk)
This is apparently some kind of linked list that chains though subsets objects in the file.
Allegro files start with this header.
COND_GE< FMT_VER::V_180, LINKED_LIST > m_LL_V18_4
COND_GE< FMT_VER::V_180, LINKED_LIST > m_LL_V18_5
COND_GE< FMT_VER::V_180, LINKED_LIST > m_LL_V18_3
COND_GE< FMT_VER::V_180, LINKED_LIST > m_LL_V18_6
const LINKED_LIST & GetUnknown5() const
COND_GE< FMT_VER::V_180, LINKED_LIST > m_LL_V18_1
COND_GE< FMT_VER::V_180, LINKED_LIST > m_LL_V18_2
FOOTPRINT_DEF(const BRD_DB &aBrd, const BLK_0x2B_FOOTPRINT_DEF &aBlk)
const wxString * GetLibPath() const
Get the library path for this footprint definition.
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
DB_REF_CHAIN m_Instances
Definition allegro_db.h:780
const wxString * GetName() const
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
FOOTPRINT_INSTANCE(const BLK_0x2D_FOOTPRINT_INST &aBlk)
const COMPONENT_INST * GetComponentInstance() const
A FUNCTION (0x10) object represents a logical function, which is an instance of a single function slo...
Definition allegro_db.h:608
const FUNCTION_SLOT & GetFunctionSlot() const
const COMPONENT_INST & GetComponentInstance() const
FUNCTION_INSTANCE(const BLK_0x10_FUNCTION_INST &aBlk)
const wxString * GetName() const
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
A FUNCTION_SLOT (0x0F) object represents a single function slot within a symbol.
Definition allegro_db.h:586
FUNCTION_SLOT(const BLK_0x0F_FUNCTION_SLOT &aBlk)
const wxString * GetName() const
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
GRAPHIC_SEG(const BRD_DB &aBrd, const BLK_0x14_GRAPHIC &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
DB_REF m_Parent
Definition allegro_db.h:693
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
VECTOR2I m_End
Definition allegro_db.h:696
VECTOR2I m_Start
Definition allegro_db.h:695
LINE(const BLK_0x15_16_17_SEGMENT &aBlk)
0x04 NET_ASSIGN objects
Definition allegro_db.h:466
const ALLEGRO::NET & GetNet() const
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
NET_ASSIGN(const BRD_DB &aBrd, const BLK_0x04_NET_ASSIGNMENT &aBlk)
DB_REF m_Net
Reference to an 0x05 TRACK or 0x32 PLACED_PAD object.
Definition allegro_db.h:474
0x1B NET objects
Definition allegro_db.h:705
DB_STR_REF m_NetNameStr
Definition allegro_db.h:719
const wxString * GetLogicalPath() const
std::optional< int > GetNetMaxNeckLength() const
NET(const BRD_DB &aBrd, const BLK_0x1B_NET &aBlk)
std::optional< int > GetNetMinLineWidth() const
std::optional< int > GetNetMaxLineWidth() const
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
const wxString * GetName() const
STATUS GetStatus() const
FIELD_LIST m_Fields
Definition allegro_db.h:724
DB_REF_CHAIN m_FieldsChain
Definition allegro_db.h:723
STATUS m_Status
Definition allegro_db.h:726
DB_REF_CHAIN m_NetAssignments
Definition allegro_db.h:721
std::optional< int > GetNetMinNeckWidth() const
0x11 objects.
Definition allegro_db.h:630
const PIN_NUMBER * GetPinNumber() const
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
PIN_NAME(const BLK_0x11_PIN_NAME &aBlk)
DB_STR_REF m_PinNameStr
Definition allegro_db.h:637
const wxString * GetName() const
0x08 objects.
Definition allegro_db.h:552
DB_STR_REF m_PinNumberStr
Definition allegro_db.h:559
const wxString * GetNumber() const
PIN_NUMBER(const BLK_0x08_PIN_NUMBER &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
const PIN_NAME * GetPinName() const
0x32 Placed Pad objects.
Definition allegro_db.h:850
const NET * GetNet() const
PLACED_PAD(const BRD_DB &aBrd, const BLK_0x32_PLACED_PAD &aBlk)
const wxString * GetPinName() const
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
const wxString * GetPinNumber() const
std::vector< DB_REF > m_Ptrs
Definition allegro_db.h:904
PTR_ARRAY(const BRD_DB &aBrd, const BLK_0x37_PTR_ARRAY &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
EDA_ANGLE m_Rotation
Definition allegro_db.h:578
RECT_OBJ(const BRD_DB &aBrd, const BLK_0x0E_RECT &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
const char * m_DebugName
Definition allegro_db.h:61
const DB_OBJ * m_Parent
Definition allegro_db.h:60
virtual std::string DebugString() const
TRACK(const BRD_DB &aBrd, const BLK_0x05_TRACK &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
DB_REF m_NetAssign
Definition allegro_db.h:884
VIA(const BRD_DB &aBrd, const BLK_0x33_VIA &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.
When processing a view, some objects are available and some are not.
Definition allegro_db.h:914
const FOOTPRINT_INSTANCE * m_FootprintInstance
Definition allegro_db.h:932
const FUNCTION_INSTANCE * m_Function
Definition allegro_db.h:930
const NET * m_Net
Definition allegro_db.h:937
const COMPONENT * m_Component
Definition allegro_db.h:926
const COMPONENT_INST * m_ComponentInstance
Definition allegro_db.h:928
const BRD_DB * m_Board
Definition allegro_db.h:924
const PLACED_PAD * m_Pad
Definition allegro_db.h:935
XREF_OBJ(const BLK_0x12_XREF &aBlk)
bool ResolveRefs(const DB_OBJ_RESOLVER &aResolver) override
Called when all objects in the DB are read and can be resolved by their IDs by other objects.