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 <wx/log.h>
27
28#include <ki_exception.h>
29
31
32using namespace ALLEGRO;
33
34
35#define BLK_DATA( BLK, T ) static_cast<const BLOCK<T>&>( BLK ).GetData()
36
37
38static std::optional<uint32_t> GetBlockKey( const BLOCK_BASE& block )
39{
40 // clang-format off
41 switch( block.GetBlockType() )
42 {
43 case 0x01: return static_cast<const BLOCK<BLK_0x01_ARC>&>( block ).GetData().m_Key;
44 case 0x03: return static_cast<const BLOCK<BLK_0x03_FIELD>&>( block ).GetData().m_Key;
45 case 0x04: return static_cast<const BLOCK<BLK_0x04_NET_ASSIGNMENT>&>( block ).GetData().m_Key;
46 case 0x05: return static_cast<const BLOCK<BLK_0x05_TRACK>&>( block ).GetData().m_Key;
47 case 0x06: return static_cast<const BLOCK<BLK_0x06_COMPONENT>&>( block ).GetData().m_Key;
48 case 0x07: return static_cast<const BLOCK<BLK_0x07_COMPONENT_INST>&>( block ).GetData().m_Key;
49 case 0x08: return static_cast<const BLOCK<BLK_0x08_PIN_NUMBER>&>( block ).GetData().m_Key;
50 case 0x09: return static_cast<const BLOCK<BLK_0x09_FILL_LINK>&>( block ).GetData().m_Key;
51 case 0x0A: return static_cast<const BLOCK<BLK_0x0A_DRC>&>( block ).GetData().m_Key;
52 case 0x0C: return static_cast<const BLOCK<BLK_0x0C_PIN_DEF>&>( block ).GetData().m_Key;
53 case 0x0D: return static_cast<const BLOCK<BLK_0x0D_PAD>&>( block ).GetData().m_Key;
54 case 0x0E: return static_cast<const BLOCK<BLK_0x0E_SHAPE_SEG>&>( block ).GetData().m_Key;
55 case 0x0F: return static_cast<const BLOCK<BLK_0x0F_FUNCTION_SLOT>&>( block ).GetData().m_Key;
56 case 0x10: return static_cast<const BLOCK<BLK_0x10_FUNCTION_INST>&>( block ).GetData().m_Key;
57 case 0x11: return static_cast<const BLOCK<BLK_0x11_PIN_NAME>&>( block ).GetData().m_Key;
58 case 0x12: return static_cast<const BLOCK<BLK_0x12_XREF>&>( block ).GetData().m_Key;
59 case 0x14: return static_cast<const BLOCK<BLK_0x14_GRAPHIC>&>( block ).GetData().m_Key;
60 case 0x15:
61 case 0x16:
62 case 0x17: return static_cast<const BLOCK<BLK_0x15_16_17_SEGMENT>&>( block ).GetData().m_Key;
63 case 0x1B: return static_cast<const BLOCK<BLK_0x1B_NET>&>( block ).GetData().m_Key;
64 case 0x1C: return static_cast<const BLOCK<BLK_0x1C_PADSTACK>&>( block ).GetData().m_Key;
65 case 0x1D: return static_cast<const BLOCK<BLK_0x1D_CONSTRAINT_SET>&>( block ).GetData().m_Key;
66 case 0x1E: return static_cast<const BLOCK<BLK_0x1E_SI_MODEL>&>( block ).GetData().m_Key;
67 case 0x1F: return static_cast<const BLOCK<BLK_0x1F_PADSTACK_DIM>&>( block ).GetData().m_Key;
68 case 0x20: return static_cast<const BLOCK<BLK_0x20_UNKNOWN>&>( block ).GetData().m_Key;
69 case 0x21: return static_cast<const BLOCK<BLK_0x21_BLOB>&>( block ).GetData().m_Key;
70 case 0x22: return static_cast<const BLOCK<BLK_0x22_UNKNOWN>&>( block ).GetData().m_Key;
71 case 0x23: return static_cast<const BLOCK<BLK_0x23_RATLINE>&>( block ).GetData().m_Key;
72 case 0x24: return static_cast<const BLOCK<BLK_0x24_RECT>&>( block ).GetData().m_Key;
73 case 0x26: return static_cast<const BLOCK<BLK_0x26_MATCH_GROUP>&>( block ).GetData().m_Key;
74 case 0x28: return static_cast<const BLOCK<BLK_0x28_SHAPE>&>( block ).GetData().m_Key;
75 case 0x29: return static_cast<const BLOCK<BLK_0x29_PIN>&>( block ).GetData().m_Key;
76 case 0x2A: return static_cast<const BLOCK<BLK_0x2A_LAYER_LIST>&>( block ).GetData().m_Key;
77 case 0x2B: return static_cast<const BLOCK<BLK_0x2B_FOOTPRINT_DEF>&>( block ).GetData().m_Key;
78 case 0x2C: return static_cast<const BLOCK<BLK_0x2C_TABLE>&>( block ).GetData().m_Key;
79 case 0x2D: return static_cast<const BLOCK<BLK_0x2D_FOOTPRINT_INST>&>( block ).GetData().m_Key;
80 case 0x2E: return static_cast<const BLOCK<BLK_0x2E_CONNECTION>&>( block ).GetData().m_Key;
81 case 0x2F: return static_cast<const BLOCK<BLK_0x2F_UNKNOWN>&>( block ).GetData().m_Key;
82 case 0x30: return static_cast<const BLOCK<BLK_0x30_STR_WRAPPER>&>( block ).GetData().m_Key;
83 case 0x31: return static_cast<const BLOCK<BLK_0x31_SGRAPHIC>&>( block ).GetData().m_Key;
84 case 0x32: return static_cast<const BLOCK<BLK_0x32_PLACED_PAD>&>( block ).GetData().m_Key;
85 case 0x33: return static_cast<const BLOCK<BLK_0x33_VIA>&>( block ).GetData().m_Key;
86 case 0x34: return static_cast<const BLOCK<BLK_0x34_KEEPOUT>&>( block ).GetData().m_Key;
87 case 0x36: return static_cast<const BLOCK<BLK_0x36_DEF_TABLE>&>( block ).GetData().m_Key;
88 case 0x37: return static_cast<const BLOCK<BLK_0x37_PTR_ARRAY>&>( block ).GetData().m_Key;
89 case 0x38: return static_cast<const BLOCK<BLK_0x38_FILM>&>( block ).GetData().m_Key;
90 case 0x39: return static_cast<const BLOCK<BLK_0x39_FILM_LAYER_LIST>&>( block ).GetData().m_Key;
91 case 0x3A: return static_cast<const BLOCK<BLK_0x3A_FILM_LIST_NODE>&>( block ).GetData().m_Key;
92 case 0x3C: return static_cast<const BLOCK<BLK_0x3C_KEY_LIST>&>( block ).GetData().m_Key;
93 default: break;
94 }
95 // clang-format off
96
97 return std::nullopt;
98}
99
100
101uint32_t BLOCK_BASE::GetKey() const
102{
103 std::optional<uint32_t> key = GetBlockKey( *this );
104 return key.value_or( 0 );
105}
106
107
108bool DB_REF::Resolve( const DB_OBJ_RESOLVER& aResolver )
109{
110 if( m_TargetKey == m_EndKey )
111 {
112 m_Target = nullptr;
113 return true;
114 }
115
116 m_Target = aResolver.Resolve( m_TargetKey );
117
118 if( !m_Target )
119 {
120 // V18+ linked list sentinel keys are not in the DB but are valid
121 // null-reference targets (end-of-chain markers)
122 if( aResolver.IsSentinel( m_TargetKey ) )
123 {
124 return true;
125 }
126
127 wxLogTrace( "ALLEGRO_EXTRACT", "Failed to resolve DB_REF target key %#010x for %s",
128 m_TargetKey, m_DebugName ? m_DebugName : "<unknown>" );
129 }
130
131 return m_Target != nullptr;
132}
133
134
135bool DB_STR_REF::Resolve( const DB_OBJ_RESOLVER& aResolver )
136{
137 if( m_StringKey == 0 )
138 {
139 // Null string reference
140 m_String = nullptr;
141 return true;
142 }
143
144 m_String = aResolver.ResolveString( m_StringKey );
145
146 if( !m_String )
147 {
148 wxLogTrace( "ALLEGRO_EXTRACT", "Failed to resolve DB_STR_REF string key %#010x for %s", m_StringKey, m_DebugName ? m_DebugName : "<unknown>" );
149 }
150
151 return m_String != nullptr;
152}
153
154
156{
157 if( m_Head == m_Tail )
158 {
159 return true;
160 }
161
162 if( m_Head == 0 )
163 {
164 // Empty chain
165 return true;
166 }
167
168 DB_OBJ* n = aResolver.Resolve( m_Head );
169
170 while( n != nullptr )
171 {
172 m_Chain.push_back( n );
173
174 uint32_t nextKey = m_NextKeyGetter( *n );
175
176 if( nextKey == m_Tail )
177 {
178 return true;
179 }
180
181 n = aResolver.Resolve( nextKey );
182 }
183
184 // Ended before the tail
185 wxLogTrace( "ALLEGRO_EXTRACT", "Failed to resolve DB_REF_CHAIN up to tail %#010x for %s", m_Tail, m_DebugName ? m_DebugName : "<unknown>" );
186 return false;
187}
188
189
190void DB_REF_CHAIN::Visit( std::function<void ( const DB_OBJ& aObj )> aVisitor ) const
191{
192 for( const DB_OBJ* node : m_Chain )
193 {
194 aVisitor( *node );
195 }
196}
197
198
199void DB_REF_CHAIN::Visit( std::function<void ( DB_OBJ& aObj )> aVisitor )
200{
201 for( DB_OBJ* node : m_Chain )
202 {
203 aVisitor( *node );
204 }
205}
206
207
208void BRD_DB::ReserveCapacity( size_t aObjectCount, size_t aStringCount )
209{
210 m_Blocks.reserve( aObjectCount );
211 m_ObjectKeyMap.reserve( aObjectCount );
212 reserveObjects( aObjectCount );
213 m_StringTable.reserve( aStringCount );
214}
215
216
217void BRD_DB::InsertBlock( std::unique_ptr<BLOCK_BASE> aBlock )
218{
219 bool skipDbObj = false;
220
221 if( m_leanMode )
222 {
223 // Skip DB_OBJ creation for high-volume types that the BOARD_BUILDER accesses
224 // exclusively through raw BLOCK_BASE via m_ObjectKeyMap and LL_WALKER.
225 // Types like NET (0x1B) and FIELD (0x03) must still create DB_OBJ for VisitNets.
226 uint8_t t = aBlock->GetBlockType();
227 skipDbObj = ( t == 0x01 || t == 0x14 || t == 0x15 || t == 0x16 || t == 0x17 );
228 }
229
230 if( !skipDbObj )
231 {
232 std::unique_ptr<DB_OBJ> dbObj = m_ObjFactory.CreateObject( *aBlock );
233
234 if( dbObj )
235 AddObject( std::move( dbObj ) );
236 }
237
238 if( aBlock->GetKey() != 0 )
239 m_ObjectKeyMap[aBlock->GetKey()] = aBlock.get();
240
241 m_Blocks.push_back( std::move( aBlock ) );
242}
243
244std::unique_ptr<DB_OBJ> BRD_DB::OBJ_FACTORY::CreateObject( const BLOCK_BASE& aBlock ) const
245{
246 std::unique_ptr<DB_OBJ> obj;
247
248 switch( aBlock.GetBlockType() )
249 {
250 case 0x01:
251 {
252 const BLK_0x01_ARC& arcBlk = BLK_DATA( aBlock, BLK_0x01_ARC );
253 obj = std::make_unique<ARC>( arcBlk );
254 break;
255 }
256 case 0x03:
257 {
258 const BLK_0x03_FIELD& blk03 = BLK_DATA( aBlock, BLK_0x03_FIELD );
259 obj = std::make_unique<FIELD>( blk03 );
260 break;
261 }
262 case 0x04:
263 {
265 obj = std::make_unique<NET_ASSIGN>( m_brdDb, netBlk );
266 break;
267 }
268 case 0x05:
269 {
270 const BLK_0x05_TRACK& trackBlk = BLK_DATA( aBlock, BLK_0x05_TRACK );
271 obj = std::make_unique<TRACK>( m_brdDb, trackBlk );
272 break;
273 }
274 case 0x06:
275 {
276 const BLK_0x06_COMPONENT& compBlk = BLK_DATA( aBlock, BLK_0x06_COMPONENT );
277 obj = std::make_unique<COMPONENT>( m_brdDb, compBlk );
278 break;
279 }
280 case 0x07:
281 {
283 obj = std::make_unique<COMPONENT_INST>( strBlk );
284 break;
285 }
286 case 0x08:
287 {
288 const BLK_0x08_PIN_NUMBER& symbolBlk = BLK_DATA( aBlock, BLK_0x08_PIN_NUMBER );
289 obj = std::make_unique<PIN_NUMBER>( symbolBlk );
290 break;
291 }
292 case 0x0E:
293 {
294 const BLK_0x0E_SHAPE_SEG& pinBlk = BLK_DATA( aBlock, BLK_0x0E_SHAPE_SEG );
295 obj = std::make_unique<SHAPE_SEG_OBJ>( m_brdDb, pinBlk );
296 break;
297 }
298 case 0x0F:
299 {
300 const BLK_0x0F_FUNCTION_SLOT& funcSlotBlk = BLK_DATA( aBlock, BLK_0x0F_FUNCTION_SLOT );
301 obj = std::make_unique<FUNCTION_SLOT>( funcSlotBlk );
302 break;
303 }
304 case 0x10:
305 {
306 const BLK_0x10_FUNCTION_INST& funcInstBlk = BLK_DATA( aBlock, BLK_0x10_FUNCTION_INST );
307 obj = std::make_unique<FUNCTION_INSTANCE>( funcInstBlk );
308 break;
309 }
310 case 0x11:
311 {
312 const BLK_0x11_PIN_NAME& pinNameBlk = BLK_DATA( aBlock, BLK_0x11_PIN_NAME );
313 obj = std::make_unique<PIN_NAME>( pinNameBlk );
314 break;
315 }
316 case 0x12:
317 {
318 const BLK_0x12_XREF& blk = BLK_DATA( aBlock, BLK_0x12_XREF );
319 obj = std::make_unique<XREF_OBJ>( blk );
320 break;
321 }
322 case 0x14:
323 {
324 const BLK_0x14_GRAPHIC& lineBlk = BLK_DATA( aBlock, BLK_0x14_GRAPHIC );
325 obj = std::make_unique<GRAPHIC_SEG>( m_brdDb, lineBlk );
326 break;
327 }
328 case 0x15:
329 case 0x16:
330 case 0x17:
331 {
333 obj = std::make_unique<LINE>( seg );
334 break;
335 }
336 case 0x1b:
337 {
338 const BLK_0x1B_NET& netBlk = BLK_DATA( aBlock, BLK_0x1B_NET );
339 obj = std::make_unique<NET>( m_brdDb, netBlk );
340 break;
341 }
342 case 0x20:
343 {
344 const BLK_0x20_UNKNOWN& blk = BLK_DATA( aBlock, BLK_0x20_UNKNOWN );
345 obj = std::make_unique<UNKNOWN_0x20>( m_brdDb, blk );
346 break;
347 }
348 case 0x28:
349 {
350 const BLK_0x28_SHAPE& shapeBlk = BLK_DATA( aBlock, BLK_0x28_SHAPE );
351 obj = std::make_unique<SHAPE>( m_brdDb, shapeBlk );
352 break;
353 }
354 case 0x2b: // Footprint
355 {
357 obj = std::make_unique<FOOTPRINT_DEF>( m_brdDb, fpBlk );
358 break;
359 }
360 case 0x2d:
361 {
362 const BLK_0x2D_FOOTPRINT_INST& fpInstBlk = BLK_DATA( aBlock, BLK_0x2D_FOOTPRINT_INST );
363 obj = std::make_unique<FOOTPRINT_INSTANCE>( fpInstBlk );
364 break;
365 }
366 case 0x2e:
367 {
368 const BLK_0x2E_CONNECTION& padBlk = BLK_DATA( aBlock, BLK_0x2E_CONNECTION );
369 obj = std::make_unique<CONNECTION_OBJ>( m_brdDb, padBlk );
370 break;
371 }
372 case 0x32:
373 {
374 const BLK_0x32_PLACED_PAD& placedPadBlk = BLK_DATA( aBlock, BLK_0x32_PLACED_PAD );
375 obj = std::make_unique<PLACED_PAD>( m_brdDb, placedPadBlk );
376 break;
377 }
378 case 0x33:
379 {
380 const BLK_0x33_VIA& viaBlk = BLK_DATA( aBlock, BLK_0x33_VIA );
381 obj = std::make_unique<VIA>( m_brdDb, viaBlk );
382 break;
383 }
384 default:
385 break;
386 }
387
388 if( obj )
389 {
390 obj->m_Loc = DB_OBJ::FILE_LOC{ aBlock.GetOffset(), aBlock.GetBlockType() };
391 }
392
393 return obj;
394}
395
396
398{
399}
400
401
403{
404}
405
406
407void DB::AddObject( std::unique_ptr<DB_OBJ> aObject )
408{
409 m_Objects[aObject->GetKey()] = std::move( aObject );
410}
411
412
413DB_OBJ* DB::Resolve( uint32_t aKey ) const
414{
415 auto it = m_Objects.find( aKey );
416 if( it != m_Objects.end() )
417 {
418 return it->second.get();
419 }
420 return nullptr;
421}
422
423
424const wxString* DB::ResolveString( uint32_t aKey ) const
425{
426 auto it = m_StringTable.find( aKey );
427 if( it != m_StringTable.end() )
428 {
429 return &it->second;
430 }
431
432 return nullptr;
433}
434
435
437{
438 for( auto& [key, obj] : m_Objects )
439 {
440 obj->m_Valid = obj->ResolveRefs( *this );
441
442 if( !obj->m_Valid )
443 {
444 // If we can't resolve the references, the DB is invalid and we cannot easily continue
445 // as any references could explode later.
446 THROW_IO_ERROR( wxString::Format( "Failed to resolve references for object key %#010x", key ) );
447 }
448 }
449}
450
451
453{
454 for( auto& [key, obj] : m_Objects )
455 obj->m_Valid = obj->ResolveRefs( *this );
456}
457
458
460 std::function<const DB_REF&( const DB_OBJ& aObj )> aVisitor ) const
461{
462 const DB_OBJ* node = Resolve( aLList.m_Head );
463 uint32_t lastKey = aLList.m_Head;
464
465 size_t iterations = 0;
466
467 while( node )
468 {
469 const DB_REF& nextRef = aVisitor( *node );
470
471 if( !nextRef.m_Target && nextRef.m_TargetKey != aLList.m_Tail
472 && !IsSentinel( nextRef.m_TargetKey ) )
473 {
474 THROW_IO_ERROR( wxString::Format( "Unexpected end of linked list: could not find %#010x", nextRef.m_TargetKey ) );
475 }
476
477 if( iterations++ >= 1e6 )
478 {
479 THROW_IO_ERROR( wxString::Format( "Excessive list length: key was %#010x", nextRef.m_TargetKey ) );
480 }
481
482 lastKey = nextRef.m_TargetKey;
483 node = nextRef.m_Target;
484 }
485}
486
487
488static bool CheckTypeIs( const DB_REF& aRef, DB_OBJ::TYPE aType, bool aCanBeNull )
489{
490 if( aRef.m_Target == nullptr )
491 return aCanBeNull;
492
493 const DB_OBJ::TYPE objType = aRef.m_Target->GetType();
494 return objType == aType;
495}
496
497static bool CheckTypeIsOneOf( const DB_REF& aRef, const std::vector<DB_OBJ::TYPE>& aTypes, bool aCanBeNull )
498{
499 if( aRef.m_Target == nullptr )
500 return aCanBeNull;
501
502 const DB_OBJ::TYPE objType = aRef.m_Target->GetType();
503 return std::find( aTypes.begin(), aTypes.end(), objType ) != aTypes.end();
504}
505
506
507// static DB_REF& FollowFootprintInstanceNext( DB_OBJ& aObj )
508// {
509// switch( aObj.GetType() )
510// {
511// case DB_OBJ::TYPE::FP_INST:
512// return static_cast<const FOOTPRINT_INSTANCE&>(aObj).m_Next.m_TargetKey;
513// }
514// }
515
516
517ARC::ARC( const BLK_0x01_ARC& aBlk ) :
518 DB_OBJ( DB_OBJ::TYPE::ARC, aBlk.m_Key )
519{
520 m_Parent.m_TargetKey = aBlk.m_Parent;
521 m_Parent.m_DebugName = "ARC::m_Parent";
522}
523
524
525bool ARC::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
526{
527 // m_Parent may point to objects of types we don't parse, so don't fail if it can't be resolved.
528 m_Parent.Resolve( aResolver );
529
530 return true;
531}
532
533
536{
537 m_Next.m_TargetKey = aBlk.m_Next;
538 // m_Next.m_EndKey = aBrd.m_Header->m_LL_0x04.m_Tail;
539 m_Next.m_DebugName = "NET_ASSIGN::m_Next";
540
541 m_Net.m_TargetKey = aBlk.m_Net;
542 m_Net.m_DebugName = "NET_ASSIGN::m_Net";
543
544 m_ConnItem.m_TargetKey = aBlk.m_ConnItem;
545 m_ConnItem.m_DebugName = "NET_ASSIGN::m_ConnItem";
546}
547
548
550{
551 bool ok = true;
552
553 ok &= m_Next.Resolve( aResolver );
554 ok &= m_Net.Resolve( aResolver );
555 ok &= m_ConnItem.Resolve( aResolver );
556
557 ok &= CheckTypeIs( m_Net, DB_OBJ::TYPE::NET, false );
558
559 return ok;
560}
561
562
564{
565 if( m_Net.m_Target == nullptr )
566 {
567 THROW_IO_ERROR( wxString::Format( "NET_ASSIGN::GetNet: NET reference is null for key %#010x", m_Key ) );
568 }
569
570 return static_cast<const NET&>( *m_Net.m_Target );
571}
572
573
574TRACK::TRACK( const BRD_DB& aBrd, const BLK_0x05_TRACK& aBlk ):
575 DB_OBJ( DB_OBJ::TYPE::TRACK, aBlk.m_Key )
576{
577 m_Next.m_TargetKey = aBlk.m_Next;
578 // m_Next.m_EndKey = aBrd.m_Header->m_LL_0x05.m_Tail;
579 m_Next.m_DebugName = "TRACK::m_Next";
580}
581
582
583bool TRACK::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
584{
585 bool ok = true;
586
587 ok &= m_Next.Resolve( aResolver );
588
589 return ok;
590}
591
592
594 DB_OBJ( DB_OBJ::TYPE::FIELD, aBlk.m_Key )
595{
596 m_SubType = aBlk.m_SubType;
597 m_Hdr1 = aBlk.m_Hdr1;
598 m_Hdr2 = aBlk.m_Hdr2;
599
600 m_Next.m_TargetKey = aBlk.m_Next;
601 m_Next.m_DebugName = "FIELD::m_Next";
602
603 switch ( aBlk.m_SubType )
604 {
605 case 0x68:
606 {
607 m_FieldValue = wxString(std::get<std::string>( aBlk.m_Substruct ) );
608 break;
609 }
610 case 0x66:
611 {
612 m_FieldValue = std::get<uint32_t>( aBlk.m_Substruct );
613 break;
614 }
615 }
616}
617
618
619const wxString& FIELD::ExpectString() const
620{
621 try
622 {
623 return std::get<wxString>( m_FieldValue );
624 }
625 catch( const std::bad_variant_access& )
626 {
627 THROW_IO_ERROR( "FIELD::ExpectString: Field value is not a string" );
628 }
629}
630
631
632
633
634
635std::optional<int> FIELD_LIST::GetOptFieldExpectInt( uint16_t aFieldCode ) const
636{
637 for( const DB_OBJ* obj : m_Chain.m_Chain )
638 {
639 // Some chains can contain non-FIELD objects like 0x30
640 // not clear if that is always true
641 if( !obj || obj->GetType() != DB_OBJ::TYPE::FIELD)
642 continue;
643
644 const FIELD& field = static_cast<const FIELD&>( *obj );
645 if( field.m_Hdr1 == aFieldCode )
646 {
647 try
648 {
649 return std::get<uint32_t>( field.m_FieldValue );
650 }
651 catch( const std::bad_variant_access& )
652 {
653 THROW_IO_ERROR( wxString::Format( "FIELD code %#04x is not an integer (subtype: %#04x )", aFieldCode,
654 field.m_SubType ) );
655 }
656 }
657 }
658
659 return std::nullopt;
660}
661
662
663const wxString* FIELD_LIST::GetOptFieldExpectString( uint16_t aFieldCode ) const
664{
665 for( const DB_OBJ* obj : m_Chain.m_Chain )
666 {
667 // Some chains can contain non-FIELD objects like 0x30
668 // not clear if that is always true
669 if( !obj || obj->GetType() != DB_OBJ::TYPE::FIELD)
670 continue;
671
672 const FIELD& field = static_cast<const FIELD&>( *obj );
673 if( field.m_Hdr1 == aFieldCode )
674 {
675 try
676 {
677 return &std::get<wxString>( field.m_FieldValue );
678 }
679 catch( const std::bad_variant_access& )
680 {
681 THROW_IO_ERROR( wxString::Format( "FIELD code %#04x is not a string (subtype: %#04x )", aFieldCode,
682 field.m_SubType ) );
683 }
684 }
685 }
686
687 return nullptr;
688}
689
690
691std::optional<std::variant<wxString, uint32_t>> FIELD_LIST::GetOptField( uint16_t aFieldCode ) const
692{
693 for( const DB_OBJ* obj : m_Chain.m_Chain )
694 {
695 if( !obj || obj->GetType() != DB_OBJ::TYPE::FIELD )
696 continue;
697
698 const FIELD& field = static_cast<const FIELD&>( *obj );
699
700 if( field.m_Hdr1 == aFieldCode )
701 return field.m_FieldValue;
702 }
703
704 return std::nullopt;
705}
706
707
709 DB_OBJ( DB_OBJ::TYPE::COMPONENT, aBlk.m_Key )
710{
711 m_Next.m_TargetKey = aBlk.m_Next;
712 m_Next.m_EndKey = aBrd.m_Header->m_LL_0x06.m_Tail;
713 m_Next.m_DebugName = "COMPONENT::m_Next";
714
715 m_CompDeviceType.m_StringKey = aBlk.m_CompDeviceType;
716 m_CompDeviceType.m_DebugName = "COMPONENT::m_CompDeviceType";
717
718 m_SymbolName.m_StringKey = aBlk.m_SymbolName;
719 m_SymbolName.m_DebugName = "COMPONENT::m_SymbolName";
720
721 m_Instances.m_Head = aBlk.m_FirstInstPtr;
722 m_Instances.m_Tail = aBlk.m_Key;
723 m_Instances.m_NextKeyGetter = []( const DB_OBJ& aObj )
724 {
725 const COMPONENT_INST& compInst = static_cast<const COMPONENT_INST&>( aObj );
726 return compInst.m_Next.m_TargetKey;
727 };
728 m_Instances.m_DebugName = "COMPONENT::m_Instances";
729
730 m_PtrFunctionSlot.m_TargetKey = aBlk.m_PtrFunctionSlot;
731 m_PtrFunctionSlot.m_DebugName = "COMPONENT::m_PtrFunctionSlot";
732
733 m_PtrPinNumber.m_TargetKey = aBlk.m_PtrPinNumber;
734 m_PtrPinNumber.m_DebugName = "COMPONENT::m_PtrPinNumber";
735
736 m_Fields.m_TargetKey = aBlk.m_Fields;
737 m_Fields.m_DebugName = "COMPONENT::m_Fields";
738}
739
740
742{
743 bool ok = true;
744
745 ok &= m_Next.Resolve( aResolver );
746 ok &= m_CompDeviceType.Resolve( aResolver );
747 ok &= m_SymbolName.Resolve( aResolver );
748 ok &= m_Instances.Resolve( aResolver );
749 ok &= m_PtrFunctionSlot.Resolve( aResolver );
750 ok &= m_PtrPinNumber.Resolve( aResolver );
751 ok &= m_Fields.Resolve( aResolver );
752
753 ok &= CheckTypeIs( m_PtrFunctionSlot, DB_OBJ::TYPE::FUNCTION_SLOT, true );
754
755 return ok;
756}
757
758
760{
761 return m_CompDeviceType.m_String;
762}
763
764
767{
768 m_TextStr.m_StringKey = aBlk.m_RefDesStrPtr;
769 m_TextStr.m_DebugName = "COMPONENT_INST::m_TextStr";
770 m_Next.m_TargetKey = aBlk.m_Next;
771 m_Next.m_DebugName = "COMPONENT_INST::m_Next";
772
773 m_FunctionInst.m_TargetKey = aBlk.m_FunctionInstPtr;
774 m_FunctionInst.m_DebugName = "COMPONENT_INST::m_FunctionInst";
775
776 m_Pads.m_Head = aBlk.m_FirstPadPtr;
777 m_Pads.m_Tail = aBlk.m_Key;
778 m_Pads.m_NextKeyGetter = []( const DB_OBJ& aObj ) -> uint32_t
779 {
780 const PLACED_PAD& pad = static_cast<const PLACED_PAD&>( aObj );
781 return pad.m_NextInCompInst.m_TargetKey;
782 };
783 m_Pads.m_DebugName = "COMPONENT_INST::m_Pads";
784}
785
786
788{
789 bool ok = true;
790
791 ok &= m_TextStr.Resolve( aResolver );
792 ok &= m_Next.Resolve( aResolver );
793 ok &= m_FunctionInst.Resolve( aResolver );
794 ok &= m_Pads.Resolve( aResolver );
795
796 return ok;
797}
798
799
800const wxString* COMPONENT_INST::GetRefDesStr() const
801{
802 return m_TextStr.m_String;
803}
804
805
807{
808 if( m_FunctionInst.m_Target == nullptr )
809 {
810 THROW_IO_ERROR( "COMPONENT_INST::GetFunctionInstance: Null reference to FUNCTION_INSTANCE" );
811 }
812
813 return static_cast<const FUNCTION_INSTANCE&>( *m_FunctionInst.m_Target );
814}
815
816
818{
819 if( m_Next.m_Target == nullptr )
820 {
821 wxLogTrace( "ALLEGRO_EXTRACT", "COMPONENT_INST::GetNextInstance: Null m_Next reference for key %#010x", m_Key );
822 return nullptr;
823 }
824
825 // If the next is not a COMPONENT_INST, it's the end of the list
826 if( m_Next.m_Target->GetType() != DB_OBJ::TYPE::COMPONENT_INST )
827 {
828 return nullptr;
829 }
830
831 return static_cast<const COMPONENT_INST*>( m_Next.m_Target );
832}
833
834
837{
838 m_PinName.m_TargetKey = aBlk.m_PinNamePtr;
839 m_PinName.m_DebugName = "PIN_NUMBER::m_PinName";
840
841 m_Next.m_TargetKey = aBlk.m_Next;
842 m_Next.m_DebugName = "PIN_NUMBER::m_Next";
843
844 // This can be in one of two fields depending on version
845 if( aBlk.m_StrPtr.has_value() )
846 m_PinNumberStr.m_StringKey = aBlk.m_StrPtr.value();
847 else
848 m_PinNumberStr.m_StringKey = aBlk.m_StrPtr16x.value();
849
850 m_PinNumberStr.m_DebugName = "PIN_NUMBER::m_PinNumberStr";
851}
852
853
855{
856 bool ok = true;
857
858 ok &= m_Next.Resolve( aResolver );
859 ok &= m_PinNumberStr.Resolve( aResolver );
860 ok &= m_PinName.Resolve( aResolver );
861
862 ok &= CheckTypeIs( m_PinName, DB_OBJ::TYPE::PIN_NAME, true );
863
864 return ok;
865}
866
867
868const wxString* PIN_NUMBER::GetNumber() const
869{
870 return m_PinNumberStr.m_String;
871}
872
873
875{
876 if( m_PinName.m_Target == nullptr )
877 {
878 return nullptr;
879 }
880
881 return static_cast<const PIN_NAME*>( m_PinName.m_Target );
882}
883
884
886 DB_OBJ( DB_OBJ::TYPE::SHAPE_SEG, aBlk.m_Key )
887{
888 m_Next.m_TargetKey = aBlk.m_Next;
889 m_Next.m_EndKey = aBrd.m_Header->m_LL_Shapes.m_Tail;
890 m_Next.m_DebugName = "SHAPE_SEG_OBJ::m_Next";
891}
892
893
895{
896 bool ok = true;
897
898 ok &= m_Next.Resolve( aResolver );
899
900 return ok;
901}
902
903
905 DB_OBJ( DB_OBJ::TYPE::PIN_NAME, aBlk.m_Key )
906{
907 m_PinNameStr.m_StringKey = aBlk.m_PinNameStrPtr;
908 m_PinNameStr.m_DebugName = "PIN_NAME::m_PinNameStr";
909
910 m_Next.m_TargetKey = aBlk.m_Next;
911 m_Next.m_DebugName = "PIN_NAME::m_Next";
912
913 m_PinNumber.m_TargetKey = aBlk.m_PinNumberPtr;
914 m_PinNumber.m_DebugName = "PIN_NAME::m_PinNumber";
915}
916
918{
919 bool ok = true;
920
921 ok &= m_PinNameStr.Resolve( aResolver );
922 ok &= m_Next.Resolve( aResolver );
923 ok &= m_PinNumber.Resolve( aResolver );
924
925 ok &= CheckTypeIs( m_PinNumber, DB_OBJ::TYPE::PIN_NUMBER, true );
926
927 return ok;
928}
929
930
931const wxString* PIN_NAME::GetName() const
932{
933 return m_PinNameStr.m_String;
934}
935
936
938{
939 if( m_PinNumber.m_Target == nullptr )
940 {
941 return nullptr;
942 }
943
944 return static_cast<const PIN_NUMBER*>( m_PinNumber.m_Target );
945}
946
947
949 DB_OBJ( DB_OBJ::TYPE::XREF, aBlk.m_Key )
950{
951 m_Ptr1.m_TargetKey = aBlk.m_Ptr1;
952 m_Ptr1.m_DebugName = "XREF_OBJ::m_Ptr1";
953
954 m_Ptr2.m_TargetKey = aBlk.m_Ptr2;
955 m_Ptr2.m_DebugName = "XREF_OBJ::m_Ptr2";
956
957 m_Ptr3.m_TargetKey = aBlk.m_Ptr3;
958 m_Ptr3.m_DebugName = "XREF_OBJ::m_Ptr3";
959}
960
961
963{
964 // These pointers may point to objects we don't parse, so don't fail if resolution fails
965 m_Ptr1.Resolve( aResolver );
966 m_Ptr2.Resolve( aResolver );
967 m_Ptr3.Resolve( aResolver );
968
969 return true;
970}
971
972
975{
976 m_Parent.m_TargetKey = aBlk.m_Parent;
977 m_Parent.m_EndKey = aBrd.m_Header->m_LL_0x14.m_Tail;
978 m_Parent.m_DebugName = "GRAPHIC_SEG::m_Parent";
979
980 m_Next.m_TargetKey = aBlk.m_Next;
981 m_Next.m_EndKey = aBrd.m_Header->m_LL_0x14.m_Tail;
982 m_Next.m_DebugName = "GRAPHIC_SEG::m_Next";
983
984 m_Segment.m_TargetKey = aBlk.m_SegmentPtr;
985 m_Segment.m_DebugName = "GRAPHIC_SEG::m_Segment";
986}
987
988
990{
991 bool ok = true;
992
993 ok &= m_Parent.Resolve( aResolver );
994 ok &= m_Next.Resolve( aResolver );
995 ok &= m_Segment.Resolve( aResolver );
996
998 {
999 DB_OBJ::TYPE::LINE,
1000 DB_OBJ::TYPE::ARC,
1001 },
1002 false );
1003
1004 return ok;
1005}
1006
1007
1009 DB_OBJ( DB_OBJ::TYPE::LINE, aBlk.m_Key )
1010{
1011 m_Parent.m_TargetKey = aBlk.m_Parent;
1012 m_Parent.m_DebugName = "SEGMENT::m_Parent";
1013
1014 m_Next.m_TargetKey = aBlk.m_Next;
1015 m_Next.m_DebugName = "SEGMENT::m_Next";
1016
1017 m_Start.x = aBlk.m_StartX;
1018 m_Start.y = aBlk.m_StartY;
1019 m_End.x = aBlk.m_EndX;
1020 m_End.y = aBlk.m_EndY;
1021
1022 m_Width = aBlk.m_Width;
1023}
1024
1025
1026bool LINE::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
1027{
1028 // m_Next may point to objects we don't parse (terminator values), so don't fail if it
1029 // can't be resolved. Segments are iterated by following the parent SHAPE/TRACK.
1030 m_Next.Resolve( aResolver );
1031
1032 return true;
1033}
1034
1035
1037 DB_OBJ( DB_OBJ::TYPE::FP_DEF, aBlk.m_Key )
1038{
1039 // 0x2Bs are linked together in a list from the board header
1040 m_Next.m_EndKey = aBrd.m_Header->m_LL_0x2B.m_Tail;
1041 m_Next.m_TargetKey = aBlk.m_Next;
1042
1043 m_FpStr.m_StringKey = aBlk.m_FpStrRef;
1044
1045 m_Instances.m_NextKeyGetter = []( const DB_OBJ& aObj )
1046 {
1047 if (aObj.GetType() != DB_OBJ::TYPE::FP_INST )
1048 return 0U;
1049
1050 return static_cast<const FOOTPRINT_INSTANCE&>( aObj ).m_Next.m_TargetKey;
1051 };
1052 m_Instances.m_Head = aBlk.m_FirstInstPtr;
1053 m_Instances.m_Tail = aBlk.m_Key;
1054
1055 m_SymLibPath.m_TargetKey = aBlk.m_SymLibPathPtr;
1056 m_SymLibPath.m_DebugName = "FOOTPRINT_DEF::m_SymLibPath";
1057}
1058
1059
1061{
1062 bool ok = true;
1063
1064 ok &= m_Next.Resolve( aResolver );
1065 ok &= m_FpStr.Resolve( aResolver );
1066
1067 // Follow the chain of 0x2Ds until we get back here
1068 ok &= m_Instances.Resolve( aResolver );
1069
1070 // Set backlink from instances to parent
1071 m_Instances.Visit( [&]( DB_OBJ& aObj )
1072 {
1073 FOOTPRINT_INSTANCE& fpInst = static_cast<FOOTPRINT_INSTANCE&>( aObj );
1074 fpInst.m_Parent = this;
1075 } );
1076
1077 wxLogTrace( "ALLEGRO_EXTRACT", "Resolved %zu footprint instances for footprint def key %#010x", m_Instances.m_Chain.size(), GetKey() );
1078
1079 ok &= m_SymLibPath.Resolve( aResolver );
1080
1081 ok &= CheckTypeIs( m_Next, DB_OBJ::TYPE::FP_DEF, true );
1082
1083 return ok;
1084}
1085
1086
1087const wxString* FOOTPRINT_DEF::GetLibPath() const
1088{
1089 if( m_SymLibPath.m_Target == nullptr )
1090 return nullptr;
1091
1092 const FIELD& symLibPath = static_cast<const FIELD&>( *m_SymLibPath.m_Target );
1093 return &symLibPath.ExpectString();
1094}
1095
1096
1098 DB_OBJ( DB_OBJ::TYPE::FP_INST, aBlk.m_Key )
1099{
1100 m_Next.m_TargetKey = aBlk.m_Next;
1101
1102 // This can be in one of two fields
1103 m_ComponentInstance.m_TargetKey = aBlk.m_InstRef16x.value_or( aBlk.m_InstRef.value_or( 0 ) );
1104
1105 m_Pads.m_Head = aBlk.m_FirstPadPtr;
1106 m_Pads.m_Tail = aBlk.m_Key;
1107 m_Pads.m_NextKeyGetter = []( const DB_OBJ& aObj )
1108 {
1109
1110 if (aObj.GetType() != DB_OBJ::TYPE::PLACED_PAD )
1111 {
1112 wxLogTrace( "ALLEGRO_EXTRACT", "FOOTPRINT_INSTANCE::m_Pads: Unexpected type in pad chain: %d", static_cast<int>( aObj.GetType() ) );
1113 return 0U;
1114 }
1115
1116 return static_cast<const PLACED_PAD&>( aObj ).m_NextInFp.m_TargetKey;
1117 };
1118
1119 // This will be filled in by the 0x2B resolution
1120 m_Parent = nullptr;
1121
1122 m_X = aBlk.m_CoordX;
1123 m_Y = aBlk.m_CoordY;
1124 m_Rotation = aBlk.m_Rotation;
1125 m_Mirrored = ( aBlk.m_Layer != 0 );
1126}
1127
1128
1130{
1131 bool ok = true;
1132
1133 ok &= m_Next.Resolve( aResolver );
1134 ok &= m_ComponentInstance.Resolve( aResolver );
1135 ok &= m_Pads.Resolve( aResolver );
1136
1137 ok &= CheckTypeIs( m_ComponentInstance, DB_OBJ::TYPE::COMPONENT_INST, true );
1138
1139 return ok;
1140}
1141
1142
1144{
1145 // The component instance is found in the 0x07 string ref
1146 // But it can be null (e.g. for dimensions)
1147 if( m_ComponentInstance.m_Target == nullptr )
1148 return nullptr;
1149
1150 const COMPONENT_INST* componentInstance = static_cast<const COMPONENT_INST*>( m_ComponentInstance.m_Target );
1151 return componentInstance;
1152}
1153
1154
1155
1156const wxString* FOOTPRINT_INSTANCE::GetName() const
1157{
1158 if( m_Parent == nullptr )
1159 return nullptr;
1160
1161 return m_Parent->m_FpStr.m_String;
1162}
1163
1164
1167{
1168 m_SlotName.m_StringKey = aBlk.m_SlotName;
1169 m_SlotName.m_DebugName = "FUNCTION_SLOT::m_SlotName";
1170
1171 m_CompDeviceType = wxString::FromUTF8( aBlk.m_CompDeviceType.data() );
1172
1173 m_Component.m_TargetKey = aBlk.m_Ptr0x06;
1174 m_Component.m_DebugName = "FUNCTION_SLOT::m_Component";
1175
1176 m_PinName.m_TargetKey = aBlk.m_Ptr0x11;
1177 m_PinName.m_DebugName = "FUNCTION_SLOT::m_PinName";
1178}
1179
1180
1182{
1183 bool ok = true;
1184
1185 ok &= m_SlotName.Resolve( aResolver );
1186
1187 // m_Component may point to objects we don't parse, so don't fail if resolution fails
1188 m_Component.Resolve( aResolver );
1189
1190 ok &= m_PinName.Resolve( aResolver );
1191
1192 return ok;
1193}
1194
1195
1196const wxString* FUNCTION_SLOT::GetName() const
1197{
1198 return m_SlotName.m_String;
1199}
1200
1201
1204{
1205 m_Slot.m_TargetKey = aBlk.m_Slots;
1206 m_Slot.m_DebugName = "FUNCTION_INSTANCE::m_Slots";
1207
1208 m_Fields.m_TargetKey = aBlk.m_Fields;
1209 m_Fields.m_DebugName = "FUNCTION_INSTANCE::m_Fields";
1210
1211 m_FunctionName.m_StringKey = aBlk.m_FunctionName;
1212 m_FunctionName.m_DebugName = "FUNCTION_INSTANCE::m_FunctionName";
1213
1214 m_ComponentInstance.m_TargetKey = aBlk.m_ComponentInstPtr;
1215 m_ComponentInstance.m_DebugName = "FUNCTION_INSTANCE::m_ComponentInstance";
1216}
1217
1218
1220{
1221 bool ok = true;
1222
1223 ok &= m_Slot.Resolve( aResolver );
1224 ok &= m_Fields.Resolve( aResolver );
1225 ok &= m_FunctionName.Resolve( aResolver );
1226 ok &= m_ComponentInstance.Resolve( aResolver );
1227
1228 return ok;
1229}
1230
1231
1232const wxString* FUNCTION_INSTANCE::GetName() const
1233{
1234 return m_FunctionName.m_String;
1235}
1236
1237
1239{
1240 if( m_ComponentInstance.m_Target == nullptr )
1241 {
1243 "FUNCTION_INSTANCE::GetComponentInstance: Null reference to COMPONENT_INST" );
1244 }
1245
1246 return static_cast<const COMPONENT_INST&>( *m_ComponentInstance.m_Target );
1247}
1248
1249
1251{
1252 if( m_Slot.m_Target == nullptr )
1253 {
1254 THROW_IO_ERROR( "FUNCTION_INSTANCE::GetFunctionSlot: Null reference to FUNCTION_SLOT" );
1255 }
1256
1257 return static_cast<const FUNCTION_SLOT&>( *m_Slot.m_Target );
1258}
1259
1260
1261NET::NET( const BRD_DB& aBrd, const BLK_0x1B_NET& aBlk ):
1262 DB_OBJ( DB_OBJ::TYPE::NET, aBlk.m_Key ),
1265{
1266 m_Next.m_TargetKey = aBlk.m_Next;
1267 m_Next.m_EndKey = aBrd.m_Header->m_LL_0x1B_Nets.m_Tail;
1268 m_Next.m_DebugName = "NET::m_Next";
1269
1270 m_NetNameStr.m_StringKey = aBlk.m_NetName;
1271 m_NetNameStr.m_DebugName = "NET::m_NetNameStr";
1272
1273 m_NetAssignments.m_Head = aBlk.m_Assignment;
1274 m_NetAssignments.m_Tail = aBlk.m_Key;
1275 m_NetAssignments.m_NextKeyGetter = []( const DB_OBJ& aObj )
1276 {
1277 const NET_ASSIGN& netAssign = static_cast<const NET_ASSIGN&>( aObj );
1278 return netAssign.m_Next.m_TargetKey;
1279 };
1280 m_NetAssignments.m_DebugName = "NET::m_NetAssignments";
1281
1282 m_FieldsChain.m_Head = aBlk.m_FieldsPtr;
1283 m_FieldsChain.m_Tail = aBlk.m_Key;
1284 m_FieldsChain.m_NextKeyGetter = []( const DB_OBJ& aObj )
1285 {
1286 if( aObj.GetType() != DB_OBJ::TYPE::FIELD )
1287 return 0U;
1288
1289 const FIELD& field = static_cast<const FIELD&>( aObj );
1290 return field.m_Next.m_TargetKey;
1291 };
1292 m_FieldsChain.m_DebugName = "NET::m_Fields";
1293
1294 // Unsure where status is stored; default to REGULAR
1295}
1296
1297
1298bool NET::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
1299{
1300 bool ok = true;
1301
1302 ok &= m_Next.Resolve( aResolver );
1303 ok &= m_NetNameStr.Resolve( aResolver );
1304 ok &= m_NetAssignments.Resolve( aResolver );
1305 ok &= m_FieldsChain.Resolve( aResolver );
1306 return ok;
1307}
1308
1309
1310const wxString* NET::GetName() const
1311{
1312 return m_NetNameStr.m_String;
1313}
1314
1315
1317{
1318 return m_Status;
1319}
1320
1321
1322const wxString* NET::GetLogicalPath() const
1323{
1324 return m_Fields.GetOptFieldExpectString( FIELD_KEYS::LOGICAL_PATH );
1325}
1326
1327
1328std::optional<int> NET::GetNetMinLineWidth() const
1329{
1330 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MIN_LINE_WIDTH );
1331}
1332
1333
1334std::optional<int> NET::GetNetMaxLineWidth() const
1335{
1336 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MAX_LINE_WIDTH );
1337}
1338
1339
1340std::optional<int> NET::GetNetMinNeckWidth() const
1341{
1342 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MIN_NECK_WIDTH );
1343}
1344
1345
1346std::optional<int> NET::GetNetMaxNeckLength() const
1347{
1348 return m_Fields.GetOptFieldExpectInt( FIELD_KEYS::MAX_NECK_LENGTH );
1349}
1350
1351
1353 DB_OBJ( DB_OBJ::TYPE::x20, aBlk.m_Key )
1354{
1355 m_Next.m_TargetKey = aBlk.m_Next;
1356 m_Next.m_DebugName = "UNKNOWN_0x20::m_Next";
1357}
1358
1359
1361{
1362 // m_Next may point to objects we don't parse, so don't fail if it can't be resolved.
1363 m_Next.Resolve( aResolver );
1364
1365 return true;
1366}
1367
1368
1369SHAPE::SHAPE( const BRD_DB& aBrd, const BLK_0x28_SHAPE& aBlk ):
1370 DB_OBJ( DB_OBJ::TYPE::SHAPE, aBlk.m_Key )
1371{
1372 m_Next.m_TargetKey = aBlk.m_Next;
1373 m_Next.m_EndKey = aBrd.m_Header->m_LL_Shapes.m_Tail;
1374 m_Next.m_DebugName = "SHAPE::m_Next";
1375
1376 m_Segments.m_TargetKey = aBlk.m_FirstSegmentPtr;
1377 m_Segments.m_DebugName = "SHAPE::m_Segments";
1378}
1379
1380
1381bool SHAPE::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
1382{
1383 bool ok = true;
1384
1385 // m_Next may point to objects we don't parse, so don't fail if it can't be resolved.
1386 // The SHAPE linked list is used internally by Allegro but not needed for board building.
1387 m_Next.Resolve( aResolver );
1388
1389 ok &= m_Segments.Resolve( aResolver );
1390
1391 return ok;
1392}
1393
1394
1396 DB_OBJ( DB_OBJ::TYPE::CONNECTION, aBlk.m_Key )
1397{
1398 m_Next.m_TargetKey = aBlk.m_Next;
1399 // m_Next.m_EndKey = aBrd.m_Header->m_LL_0x2E.m_Tail;
1400 m_Next.m_DebugName = "CONNECTION_OBJ::m_Next";
1401
1402 m_NetAssign.m_TargetKey = aBlk.m_NetAssignment;
1403 m_NetAssign.m_DebugName = "CONNECTION_OBJ::m_NetAssign";
1404
1405 m_Connection.m_TargetKey = aBlk.m_Connection;
1406 m_Connection.m_DebugName = "CONNECTION_OBJ::m_Connection";
1407
1408 m_Position.x = aBlk.m_CoordX;
1409 m_Position.y = aBlk.m_CoordY;
1410}
1411
1412
1414{
1415 bool ok = true;
1416
1417 ok &= m_Next.Resolve( aResolver );
1418 ok &= m_NetAssign.Resolve( aResolver );
1419
1420 // m_Connection may point to objects we don't parse, so don't fail if resolution fails
1421 m_Connection.Resolve( aResolver );
1422
1423 return ok;
1424}
1425
1426
1428 DB_OBJ( DB_OBJ::TYPE::PLACED_PAD, aBlk.m_Key )
1429{
1430 m_Next.m_TargetKey = aBlk.m_Next;
1431 // m_Next.m_EndKey = aBrd.m_Header->m_LL_0x32.m_Tail;
1432 m_Next.m_DebugName = "PLACED_PAD::m_Next";
1433
1434 m_NextInFp.m_TargetKey = aBlk.m_NextInFp;
1435 m_NextInFp.m_DebugName = "PLACED_PAD::m_NextInFp";
1436
1437 m_NextInCompInst.m_TargetKey = aBlk.m_NextInCompInst;
1438 m_NextInCompInst.m_DebugName = "PLACED_PAD::m_NextInCompInst";
1439
1440 // m_Padstack.m_TargetKey = aBlk.m_PadstackPtr;
1441 // m_Padstack.m_DebugName = "PLACED_PAD::m_Padstack";
1442
1443 m_PinNumber.m_TargetKey = aBlk.m_PtrPinNumber;
1444 m_PinNumber.m_DebugName = "PLACED_PAD::m_PinNumber";
1445
1446 m_PinNumText.m_TargetKey = aBlk.m_NameText;
1447 m_PinNumText.m_DebugName = "PLACED_PAD::m_PinNumText";
1448
1449 m_NetAssign.m_TargetKey = aBlk.m_NetPtr;
1450 m_NetAssign.m_DebugName = "PLACED_PAD::m_NetAssign";
1451
1452 m_Bounds = BOX2I(
1453 {aBlk.m_Coords[0], aBlk.m_Coords[1] },
1454 { aBlk.m_Coords[2], aBlk.m_Coords[3] }
1455 );
1456}
1457
1458
1460{
1461 bool ok = true;
1462
1463 ok &= m_Next.Resolve( aResolver );
1464 ok &= m_NextInFp.Resolve( aResolver );
1465 ok &= m_NextInCompInst.Resolve( aResolver );
1466 // ok &= m_Padstack.Resolve( aResolver );
1467 ok &= m_PinNumber.Resolve( aResolver );
1468 ok &= m_NetAssign.Resolve( aResolver );
1469
1470 ok &= CheckTypeIs( m_PinNumber, DB_OBJ::TYPE::PIN_NUMBER, true );
1471
1472
1473 return ok;
1474}
1475
1476
1477const wxString* PLACED_PAD::GetPinNumber() const
1478{
1479 if( m_PinNumber.m_Target == nullptr )
1480 return nullptr;
1481
1482 return static_cast<const PIN_NUMBER*>( m_PinNumber.m_Target )->GetNumber();
1483}
1484
1485
1486const wxString* PLACED_PAD::GetPinName() const
1487{
1488 if( m_PinNumber.m_Target == nullptr )
1489 return nullptr;
1490
1491 const PIN_NUMBER* pinNumber = static_cast<const PIN_NUMBER*>( m_PinNumber.m_Target );
1492 const PIN_NAME* pinName = pinNumber->GetPinName();
1493
1494 if( pinName == nullptr )
1495 return nullptr;
1496
1497 return pinName->GetName();
1498}
1499
1500
1502{
1503 if( m_NetAssign.m_Target == nullptr )
1504 return nullptr;
1505
1506 const NET_ASSIGN* netAssign = static_cast<const NET_ASSIGN*>( m_NetAssign.m_Target );
1507
1508 return &netAssign->GetNet();
1509}
1510
1511
1512VIA::VIA( const BRD_DB& aBrd, const BLK_0x33_VIA& aBlk ):
1513 DB_OBJ( DB_OBJ::TYPE::VIA, aBlk.m_Key )
1514{
1515 m_Next.m_TargetKey = aBlk.m_Next;
1516 // m_Next.m_EndKey = aBrd.m_Header->m_LL_0x33.m_Tail;
1517 m_Next.m_DebugName = "VIA::m_Next";
1518}
1519
1520
1521bool VIA::ResolveRefs( const DB_OBJ_RESOLVER& aResolver )
1522{
1523 bool ok = true;
1524
1525 ok &= m_Next.Resolve( aResolver );
1526
1527 return ok;
1528}
1529
1530
1531static void collectSentinelKeys( const FILE_HEADER& aHeader, DB& aDb )
1532{
1533 auto addTail = [&]( const FILE_HEADER::LINKED_LIST& aLL )
1534 {
1535 aDb.AddSentinelKey( aLL.m_Tail );
1536 };
1537
1538 addTail( aHeader.m_LL_0x04 );
1539 addTail( aHeader.m_LL_0x06 );
1540 addTail( aHeader.m_LL_0x0C );
1541 addTail( aHeader.m_LL_Shapes );
1542 addTail( aHeader.m_LL_0x14 );
1543 addTail( aHeader.m_LL_0x1B_Nets );
1544 addTail( aHeader.m_LL_0x1C );
1545 addTail( aHeader.m_LL_0x24_0x28 );
1546 addTail( aHeader.m_LL_Unknown1 );
1547 addTail( aHeader.m_LL_0x2B );
1548 addTail( aHeader.m_LL_0x03_0x30 );
1549 addTail( aHeader.m_LL_0x0A );
1550 addTail( aHeader.m_LL_0x1D_0x1E_0x1F );
1551 addTail( aHeader.m_LL_Unknown2 );
1552 addTail( aHeader.m_LL_0x38 );
1553 addTail( aHeader.m_LL_0x2C );
1554 addTail( aHeader.m_LL_0x0C_2 );
1555 addTail( aHeader.m_LL_Unknown3 );
1556 addTail( aHeader.m_LL_0x36 );
1557 addTail( aHeader.GetUnknown5() );
1558 addTail( aHeader.m_LL_Unknown6 );
1559 addTail( aHeader.m_LL_0x0A_2 );
1560
1561 if( aHeader.m_LL_V18_1.has_value() )
1562 {
1563 addTail( aHeader.m_LL_V18_1.value() );
1564 addTail( aHeader.m_LL_V18_2.value() );
1565 addTail( aHeader.m_LL_V18_3.value() );
1566 addTail( aHeader.m_LL_V18_4.value() );
1567 addTail( aHeader.m_LL_V18_5.value() );
1568 addTail( aHeader.m_LL_V18_6.value() );
1569 }
1570}
1571
1572
1575 m_ObjFactory( *this ),
1576 m_leanMode( false )
1577{
1578}
1579
1580
1582{
1583 if( m_FmtVer >= FMT_VER::V_180 )
1584 collectSentinelKeys( *m_Header, *this );
1585
1586 if( m_leanMode )
1587 {
1588 // In lean mode, DB_OBJ was not created for high-volume types (segments, graphics,
1589 // arcs). Other DB_OBJ types that reference those keys will fail to resolve, so we
1590 // attempt best-effort resolution. The NET and FIELD objects the builder needs only
1591 // reference each other and will resolve correctly.
1593 return true;
1594 }
1595
1596 // Try strict resolution first. If it fails (some boards have object types the parser
1597 // doesn't fully support), fall back to best-effort which allows partial imports.
1598 try
1599 {
1601 }
1602 catch( const IO_ERROR& e )
1603 {
1604 wxLogTrace( "ALLEGRO_EXTRACT",
1605 "Strict reference resolution failed (%s), retrying with best-effort",
1606 e.Problem() );
1607
1609 }
1610
1611 return true;
1612}
1613
1614
1616{
1617 const auto fpDefNextFunc = [&]( const DB_OBJ& aObj ) -> const DB_REF&
1618 {
1619 if( aObj.GetType() != DB_OBJ::TYPE::FP_DEF )
1620 return DB_NULLREF;
1621
1622 const FOOTPRINT_DEF& fpDef = static_cast<const FOOTPRINT_DEF&>( aObj );
1623
1624 aVisitor( fpDef );
1625
1626 return fpDef.m_Next;
1627 };
1628
1629 visitLinkedList( m_Header->m_LL_0x2B, fpDefNextFunc );
1630}
1631
1632
1634{
1635 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting footprint instances for footprint def key %#010x", aFpDef.GetKey() );
1636
1637 VIEW_OBJS viewObjs;
1638 viewObjs.m_Board = this;
1639
1640 const auto fpInstNextFunc = [&]( const DB_OBJ& aObj )
1641 {
1642 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting footprint instance key %#010x", aObj.GetKey() );
1643 if( aObj.GetType() != DB_OBJ::TYPE::FP_INST )
1644 {
1645 wxLogTrace( "ALLEGRO_EXTRACT", " Not a footprint instance, skipping key %#010x", aObj.GetKey() );
1646 return;
1647 }
1648
1649 const FOOTPRINT_INSTANCE& fpInst = static_cast<const FOOTPRINT_INSTANCE&>( aObj );
1650
1651 // viewObjs.m_FootprintDef = &aFpDef;
1652 viewObjs.m_FootprintInstance = &fpInst;
1653
1654 const COMPONENT_INST* componentInstance = fpInst.GetComponentInstance();
1655 if( componentInstance )
1656 {
1657 viewObjs.m_Function = &componentInstance->GetFunctionInstance();
1658 viewObjs.m_Component = componentInstance->GetParentComponent();
1659 }
1660
1661 aVisitor( viewObjs );
1662 };
1663
1664 aFpDef.m_Instances.Visit( fpInstNextFunc );
1665}
1666
1667
1669{
1670 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting footprint instances" );
1671
1672 VIEW_OBJS viewObjs;
1673 viewObjs.m_Board = this;
1674
1675 // And now visit all the footprint instances, and then visit each field on each one
1677 [&]( const FOOTPRINT_DEF& aFpDef )
1678 {
1679 visitFootprintInstances( aFpDef, aVisitor );
1680 } );
1681}
1682
1683
1685{
1686 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting function instances" );
1687
1688 const auto componentVisitor = [&]( const VIEW_OBJS& aViewObjs )
1689 {
1690 aVisitor( aViewObjs );
1691 };
1692
1693 // When is FUNCTION != COMPONENT? how should we iterate this?
1694 VisitComponents( componentVisitor );
1695}
1696
1697
1699{
1700 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting components" );
1701
1702 VIEW_OBJS viewObjs;
1703
1704 viewObjs.m_Board = this;
1705
1706 const auto x06NextFunc = [&]( const DB_OBJ& aObj ) -> const DB_REF&
1707 {
1708 if( aObj.GetType() != DB_OBJ::TYPE::COMPONENT )
1709 {
1710 wxLogTrace( "ALLEGRO_EXTRACT", " Not a component object, skipping key %#010x", aObj.GetKey() );
1711 return DB_NULLREF;
1712 }
1713
1714 const COMPONENT& component = static_cast<const COMPONENT&>( aObj );
1715
1716 viewObjs.m_Component = &component;
1717
1718 const auto compInstVisitor = [&]( const DB_OBJ& aObj )
1719 {
1720 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting component instance key %#010x", aObj.GetKey() );
1721
1722 if( aObj.GetType() != DB_OBJ::TYPE::COMPONENT_INST )
1723 {
1724 wxLogTrace( "ALLEGRO_EXTRACT", " Not a component instance, skipping key %#010x", aObj.GetKey() );
1725 return;
1726 }
1727
1728 const COMPONENT_INST& compInst = static_cast<const COMPONENT_INST&>( aObj );
1729
1730 const FUNCTION_INSTANCE& funcInst = compInst.GetFunctionInstance();
1731 viewObjs.m_ComponentInstance = &compInst;
1732 viewObjs.m_Function = &funcInst;
1733
1734 aVisitor( viewObjs );
1735 };
1736
1737 component.m_Instances.Visit( compInstVisitor );
1738
1739 return component.m_Next;
1740 };
1741
1742 visitLinkedList( m_Header->m_LL_0x06, x06NextFunc );
1743}
1744
1745
1747{
1748 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting component pins" );
1749
1750 const auto componentVisitor = [&]( const VIEW_OBJS& aViewObjs )
1751 {
1752 // For each footprint instance, visit all the pins of the component
1753 const COMPONENT_INST* compInst = aViewObjs.m_ComponentInstance;
1754
1755 if( compInst == nullptr )
1756 {
1757 wxLogTrace( "ALLEGRO_EXTRACT", " No component instance in view objs, skipping" );
1758 return;
1759 }
1760
1761 const auto padVisitor = [&]( const DB_OBJ& aObj )
1762 {
1763 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting pad key %#010x", aObj.GetKey() );
1764 if( aObj.GetType() != DB_OBJ::TYPE::PLACED_PAD )
1765 {
1766 wxLogTrace( "ALLEGRO_EXTRACT", " Not a placed pad, skipping key %#010x, type", aObj.GetKey() );
1767 return;
1768 }
1769
1770 const PLACED_PAD& placedPad = static_cast<const PLACED_PAD&>( aObj );
1771
1772 VIEW_OBJS viewObj = aViewObjs;
1773 viewObj.m_Pad = &placedPad;
1774 viewObj.m_Net = placedPad.GetNet();
1775
1776 aVisitor( viewObj );
1777 };
1778
1779 compInst->m_Pads.Visit( padVisitor );
1780 };
1781
1782 VisitComponents( componentVisitor );
1783}
1784
1785
1787{
1788 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting nets" );
1789
1790 VIEW_OBJS viewObjs;
1791 viewObjs.m_Board = this;
1792
1793 const auto netNextFunc = [&]( const DB_OBJ& aObj ) -> const DB_REF&
1794 {
1795 if( aObj.GetType() != DB_OBJ::TYPE::NET )
1796 {
1797 wxLogTrace( "ALLEGRO_EXTRACT", " Not a net object, skipping key %#010x", aObj.GetKey() );
1798 return DB_NULLREF;
1799 }
1800
1801 const NET& net = static_cast<const NET&>( aObj );
1802
1803 viewObjs.m_Net = &net;
1804
1805 aVisitor( viewObjs );
1806
1807 return net.m_Next;
1808 };
1809
1810 visitLinkedList( m_Header->m_LL_0x1B_Nets, netNextFunc );
1811}
1812
1813
1815{
1816 wxLogTrace( "ALLEGRO_EXTRACT", "Visiting connected geometry" );
1817
1818 VIEW_OBJS viewObjs;
1819 viewObjs.m_Board = this;
1820
1821 const auto netVisitor = [&]( const VIEW_OBJS& aViewObjs )
1822 {
1823 const NET& net = *aViewObjs.m_Net;
1824
1825 // const NET_ASSIGN* netAssign = net.GetAssignment();
1826
1827 // if( netAssign == nullptr )
1828 // {
1829 // wxLogTrace( "ALLEGRO_EXTRACT", " Net %#010x has no assignment, skipping", net.GetKey() );
1830 // return;
1831 // }
1832 };
1833
1834 VisitNets( netVisitor );
1835}
static bool CheckTypeIsOneOf(const DB_REF &aRef, const std::vector< DB_OBJ::TYPE > &aTypes, bool aCanBeNull)
static void collectSentinelKeys(const FILE_HEADER &aHeader, DB &aDb)
#define BLK_DATA(BLK, T)
static bool CheckTypeIs(const DB_REF &aRef, DB_OBJ::TYPE aType, bool aCanBeNull)
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:849
void VisitConnectedGeometry(VIEW_OBJS_VISITOR aVisitor) const
std::unordered_map< uint32_t, BLOCK_BASE * > m_ObjectKeyMap
Definition allegro_db.h:966
std::unique_ptr< FILE_HEADER > m_Header
Definition allegro_db.h:962
std::vector< std::unique_ptr< BLOCK_BASE > > m_Blocks
Definition allegro_db.h:965
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:900
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
Definition allegro_db.h:970
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:139
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:154
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:253
const wxString * ResolveString(uint32_t aRef) const override
std::unordered_map< uint32_t, wxString > m_StringTable
Definition allegro_db.h:317
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:311
void AddSentinelKey(uint32_t aKey)
Definition allegro_db.h:289
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:284
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:301
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:399
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 m_Segments
Definition allegro_db.h:693
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?
#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:842
static constexpr DB_REF DB_NULLREF
Definition allegro_db.h:79
FMT_VER
The format of an Allego file.
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:340
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.
COND_LT< FMT_VER::V_172, uint32_t > m_StrPtr16x
COND_GE< FMT_VER::V_172, uint32_t > m_StrPtr
Pointer to 0x11 PIN_NAME object.
Shape/fill segment linking a copper shape to its parent footprint.
Function slot in a multi-slot component (e.g.
std::array< char, 32 > m_CompDeviceType
Function instance linking a component instance (0x07) to its schematic function, pin cross-references...
Pin name within a component, linked from function slots (0x0F).
uint32_t m_PinNameStrPtr
Pointer to next 0x11 PIN_NAME object or 0x0F SLOT.
uint32_t m_Next
Pointer to 0x08 PIN_NUMBER object.
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.
COND_LT< FMT_VER::V_172, uint32_t > m_InstRef16x
COND_GE< FMT_VER::V_172, uint32_t > m_InstRef
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),...
COMPONENT_INST 0x07 objects.
Definition allegro_db.h:465
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:478
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
COMPONENT 0x06 objects.
Definition allegro_db.h:441
const wxString * GetComponentDeviceType() const
DB_REF_CHAIN m_Instances
Definition allegro_db.h:449
DB_STR_REF m_SymbolName
Definition allegro_db.h:448
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:447
COMPONENT(const BRD_DB &aBrd, const BLK_0x06_COMPONENT &aBlk)
const T & value_or(const T &aDefault) const
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:162
DB_OBJ(TYPE aType, uint32_t aKey)
Definition allegro_db.h:204
uint32_t GetKey() const
Definition allegro_db.h:234
TYPE GetType() const
Definition allegro_db.h:232
std::vector< DB_OBJ * > m_Chain
Definition allegro_db.h:110
void Visit(std::function< void(const DB_OBJ &aObj)> aVisitor) const
Visit all objects in the chain.
std::function< uint32_t(const DB_OBJ &)> m_NextKeyGetter
Definition allegro_db.h:105
bool Resolve(const DB_OBJ_RESOLVER &aResolver) override
uint32_t m_EndKey
Definition allegro_db.h:75
uint32_t m_TargetKey
Definition allegro_db.h:70
DB_OBJ * m_Target
Definition allegro_db.h:76
bool Resolve(const DB_OBJ_RESOLVER &aResolver) override
const wxString * m_String
Definition allegro_db.h:130
bool Resolve(const DB_OBJ_RESOLVER &aResolver) override
0x03 FIELD objects
Definition allegro_db.h:352
uint32_t m_Hdr2
Definition allegro_db.h:362
uint8_t m_SubType
Definition allegro_db.h:357
const wxString & ExpectString() const
uint32_t m_Hdr1
Definition allegro_db.h:361
std::variant< wxString, uint32_t > m_FieldValue
Definition allegro_db.h:364
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:708
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:543
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.
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:620
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:624
VECTOR2I m_Start
Definition allegro_db.h:623
LINE(const BLK_0x15_16_17_SEGMENT &aBlk)
const 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.
DB_REF m_Next
Reference to an 0x1B NET object.
Definition allegro_db.h:412
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:414
0x1B NET objects
Definition allegro_db.h:633
DB_STR_REF m_NetNameStr
Definition allegro_db.h:646
const wxString * GetLogicalPath() const
std::optional< int > GetNetMaxNeckLength() const
NET(const BRD_DB &aBrd, const BLK_0x1B_NET &aBlk)
std::optional< int > GetNetMinLineWidth() const
DB_REF m_Next
Definition allegro_db.h:645
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:651
DB_REF_CHAIN m_FieldsChain
Definition allegro_db.h:650
STATUS m_Status
Definition allegro_db.h:653
DB_REF_CHAIN m_NetAssignments
Definition allegro_db.h:648
std::optional< int > GetNetMinNeckWidth() const
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:569
const wxString * GetName() const
DB_STR_REF m_PinNumberStr
Definition allegro_db.h:496
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:771
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
const char * m_DebugName
Definition allegro_db.h:50
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.
SHAPE_SEG_OBJ(const BRD_DB &aBrd, const BLK_0x0E_SHAPE_SEG &aBlk)
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_Next
Definition allegro_db.h:802
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:815
const FOOTPRINT_INSTANCE * m_FootprintInstance
Definition allegro_db.h:833
const FUNCTION_INSTANCE * m_Function
Definition allegro_db.h:831
const NET * m_Net
Definition allegro_db.h:838
const COMPONENT * m_Component
Definition allegro_db.h:827
const COMPONENT_INST * m_ComponentInstance
Definition allegro_db.h:829
const BRD_DB * m_Board
Definition allegro_db.h:825
const PLACED_PAD * m_Pad
Definition allegro_db.h:836
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.