KiCad PCB EDA Suite
Loading...
Searching...
No Matches
easypc_classes_library.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22
23namespace EASYPC
24{
25
26namespace
27{
28
30 void serializeFormat( ARCHIVE& aAr, SELF_VERSIONED& aItem )
31 {
32 SOURCE_DESIGN_ITEM::LoadFormatted( aAr, aItem.Format );
33 aAr.SetBooleanIsByte( aItem.Format > 7999 );
34 }
35
36} // namespace
37
38
40{
41 serializeFormat( aAr, *this );
42 co_await SOURCE_DESIGN_ITEM::Load( aAr );
43 LoadOldFormat( aAr, Format );
44
45 const int v = Format;
46
47 const bool nameFirst = v >= 22000 || aAr.Product() != PRODUCT_DESIGNSPARK;
48
49 if( nameFirst )
50 Name = aAr.ReadString();
51
52 Shapes = co_await aAr.Object();
53 Pads = co_await aAr.Object();
54 Texts = co_await aAr.Object();
55
56 if( !nameFirst )
57 Name = aAr.ReadString();
58
59 if( v > 10002 )
60 ValuePositions = co_await aAr.Object();
61
62 OriginX = aAr.I32();
63 OriginY = aAr.I32();
64 Timestamp = aAr.I32();
65
66 if( v < 10003 )
67 {
68 NameOrigin = ARCHIVE::Create( "CSymbolNameOrigin" );
69
70 if( v > 2999 )
71 aAr.MapObject( NameOrigin.get() );
72
73 co_await aAr.Embedded( *NameOrigin, "CSymbolNameOrigin" );
74
75 // An old symbol's name origin becomes its name position; types 0x1f without a layer, 0xf with one
76 const SOURCE_ORIGIN& origin = static_cast<const SOURCE_ORIGIN&>( *NameOrigin );
77 DerivedNamePosition = std::make_unique<SOURCE_VALUE_POSITION>();
78 DerivedNamePosition->Position = origin.Position;
79 DerivedNamePosition->Layer = origin.Layer;
80 DerivedNamePosition->TextStyle = origin.TextStyle;
81 DerivedNamePosition->Types = origin.Layer ? 0xf : 0x1f;
82
83 DerivedValuePositions = std::make_unique<SOURCE_DESIGN_LIST>();
84 DerivedValuePositions->Items.push_back( DerivedNamePosition.get() );
86 }
87 else if( v >= 12003 )
88 {
89 bool tail = true;
90
91 co_await aAr.Object(); // origins
92
93 if( v < 14001 )
94 {
95 co_await SkipMember( aAr, "CScreenGrid" );
96 co_await SkipMember( aAr, "CUnits" );
97 co_await SkipMember( aAr, "COldWorkingGrid" );
98 tail = v > 12006;
99 }
100 else
101 {
102 co_await SkipMember( aAr, "CGrid" );
103 co_await SkipMember( aAr, "CUnits" );
104 }
105
106 if( tail )
107 {
108 aAr.InBool();
109 aAr.Skip( 16 ); // system and relative origins
110
111 if( v > 12999 )
112 co_await aAr.Object();
113
114 if( v > 15001 )
115 {
116 Library = aAr.ReadString();
117 aAr.Skip( 1 );
118 }
119 }
120 }
121
122 if( v > 28000 )
123 co_await aAr.Object();
124}
125
126
128{
129 co_await SOURCE_DESIGN_ITEM::Load( aAr );
130 co_await LoadRemainder( aAr );
131
132 if( ItemFormat( aAr ) > 2103 )
133 Visible = aAr.InBool();
134}
135
136
138{
139 co_await SOURCE_DESIGN_ITEM::Load( aAr );
140
141 Definition = co_await aAr.Object();
142
143 if( ItemFormat( aAr ) > 2103 )
144 Visible = aAr.InBool();
145}
146
147
149{
150 co_await SOURCE_DESIGN_ITEM::Load( aAr );
151
152 Symbol = aAr.ReadString();
153
154 for( int32_t i = aAr.I32(); i > 0; --i )
155 PinNames.push_back( aAr.ReadString() );
156
157 if( ItemFormat( aAr ) > 2003 )
158 Library = aAr.ReadString();
159}
160
161
162const std::vector<OBJECT*>& ListItems( const OBJECT* aList )
163{
164 static const std::vector<OBJECT*> empty;
165
166 if( const SOURCE_DESIGN_LIST* list = dynamic_cast<const SOURCE_DESIGN_LIST*>( aList ) )
167 return list->Items;
168
169 if( const SOURCE_DESIGN_ARRAY* array = dynamic_cast<const SOURCE_DESIGN_ARRAY*>( aList ) )
170 return array->Items;
171
172 return empty;
173}
174
175
177{
178 Parent = co_await aAr.Object();
179
180 for( uint32_t i = aAr.Count(); i > 0; --i )
181 Items.push_back( co_await aAr.Object() );
182}
183
184
186{
187 co_await SOURCE_DESIGN_ITEM::Load( aAr );
188
189 if( ItemFormat( aAr ) > 8999 )
190 {
191 Pins = co_await aAr.Object();
192 co_return;
193 }
194
195 for( int32_t i = aAr.I32(); i > 0; --i )
196 PcbSymbolPins.push_back( aAr.I32() );
197}
198
199
201{
202 co_await SOURCE_DESIGN_ITEM::Load( aAr );
203
204 if( ItemFormat( aAr ) < 12005 )
205 PcbSymbolPin = wxString::Format( wxS( "%d" ), aAr.I32() );
206 else
207 PcbSymbolPin = aAr.ReadString();
208
209 PinNumber = aAr.ReadString();
210 NetName = aAr.ReadString();
211
212 if( ItemFormat( aAr ) > 22999 )
213 PinType = aAr.U32();
214}
215
216
218{
219 serializeFormat( aAr, *this );
220 co_await SOURCE_DESIGN_ITEM::Load( aAr );
221 LoadOldFormat( aAr, Format );
222
223 const int f = Format;
224 const int32_t product = aAr.Product();
225
226 // The DesignSpark products store the package first
227 if( product == PRODUCT_DESIGNSPARK || product == PRODUCT_DESIGNSPARK_CREATOR || product == PRODUCT_DESIGNSPARK_PRO )
228 {
229 Package = aAr.ReadString();
230 Name = aAr.ReadString();
231 }
232 else
233 {
234 Name = aAr.ReadString();
235 Package = aAr.ReadString();
236 }
237
238 Gates = co_await aAr.Object();
240 Description = aAr.ReadString();
241
242 if( f > 4999 )
243 aAr.Skip( 4 ); // show flags
244
245 if( f > 15001 )
246 {
247 Library = aAr.ReadString();
248 aAr.Skip( 1 );
249 }
250
251 if( f > 16999 )
252 SuppressionFlags = aAr.U32();
253
254 if( f > 21999 )
255 aAr.Skip( 1 );
256
257 // Reset once loaded, so later objects chaining to this one gate on 30001
259}
260
261
263{
264 serializeFormat( aAr, *this );
265 co_await SOURCE_DESIGN_ITEM::Load( aAr );
266 LoadOldFormat( aAr, Format );
267
268 Package = aAr.ReadString();
269 Symbol = aAr.ReadString();
270 GateMaps = co_await aAr.Object();
271 aAr.SkipString(); // package description
272 aAr.Skip( 4 ); // version
273
274 if( Format > 2003 )
275 Library = aAr.ReadString();
276
277 // A null tag in every known file
278 if( Format > 21999 )
279 co_await aAr.Object();
280
282}
283
284
286{
287 co_await SOURCE_DESIGN_ITEM::Load( aAr );
288
289 Board = co_await aAr.ObjectAs<SOURCE_PCB_COMPONENT>();
290 Schematic = co_await aAr.ObjectAs<SOURCE_SCM_COMPONENT>();
291}
292
293
294bool IsPadList( const wxString& aPcbSymbolPin )
295{
296 if( aPcbSymbolPin.Contains( wxS( "," ) ) || aPcbSymbolPin.Contains( wxS( "+" ) )
297 || aPcbSymbolPin.Contains( wxS( "=" ) ) )
298 {
299 return true;
300 }
301
302 // "-1" is the unmapped marker, any other '-' is a range
303 return aPcbSymbolPin.Find( '-' ) > 0;
304}
305
306
307std::vector<wxString> ExpandPinNumberList( const wxString& aList, wxString* aDisplay )
308{
309 // A range wider than any part is file damage and stays one literal item
310 constexpr uint64_t MAX_PIN_RANGE = 100000;
311
312 std::vector<wxString> out;
313 wxString list = aList;
314 int eq = list.Find( '=' );
315
316 if( eq != wxNOT_FOUND )
317 {
318 if( aDisplay )
319 *aDisplay = list.Left( eq );
320
321 list = list.Mid( eq + 1 );
322 }
323
324 wxString item;
325
326 auto flush = [&]()
327 {
328 long first = 0;
329 long last = 0;
330 int dash = item.Find( '-' );
331
332 if( dash > 0 && item.Left( dash ).ToLong( &first ) && item.Mid( dash + 1 ).ToLong( &last ) && first <= last
333 && uint64_t( last ) - uint64_t( first ) < MAX_PIN_RANGE )
334 {
335 // Stopping before the increment keeps a range ending at LONG_MAX from overflowing
336 for( long n = first;; ++n )
337 {
338 out.push_back( wxString::Format( wxS( "%ld" ), n ) );
339
340 if( n == last )
341 break;
342 }
343 }
344 else if( !item.IsEmpty() )
345 {
346 out.push_back( item );
347 }
348
349 item.Clear();
350 };
351
352 for( wxUniChar ch : list )
353 {
354 if( ch == ',' || ch == '+' )
355 flush();
356 else
357 item += ch;
358 }
359
360 flush();
361 return out;
362}
363
364
366{
367 Register<SOURCE_SYMBOL>( aReg, { "CSymbol" } );
368 Register<SOURCE_SCM_COMPONENT>( aReg, { "CScmComponent" } );
369 Register<SOURCE_PCB_COMPONENT>( aReg, { "CPcbComponent" } );
370 Register<SOURCE_COMPONENT>( aReg, { "CComponent" } );
371 Register<SOURCE_GATE>( aReg, { "CGate" } );
372 Register<SOURCE_GATE_MAP>( aReg, { "CGateMap" } );
373 Register<SOURCE_GATE_PIN>( aReg, { "CGatePin" } );
374 Register<SOURCE_DESIGN_ARRAY>( aReg, { "CDesignArray", "CGateArray", "CGateMapArray", "CGatePinArray" } );
375 Register<SOURCE_DESIGN_LIST>( aReg, { "CSymbolArray", "CComponentArray", "CScmComponentArray" } );
376 Register<SOURCE_PIN_NAME>( aReg, { "CPinName", "CPinNumber" } );
377 Register<SOURCE_PIN_NAME_INSTANCE>( aReg, { "CPinNameInstance", "CPinNumberInstance" } );
378
379 // These carry the plain text position and origin fields
380 Register<SOURCE_TEXT_POSITION>( aReg, { "CSymbolName" } );
381 Register<SOURCE_ORIGIN>( aReg, { "CSymbolNameOrigin" } );
382}
383
384} // namespace EASYPC
One archive load stream; it owns every object it creates.
void Skip(size_t aLen)
void MapObject(OBJECT *aObject)
A load-array slot for an object not read through a tag.
EMBEDDED_AWAITER Embedded(OBJECT &aObject, const char *aClass)
static std::unique_ptr< OBJECT > Create(const char *aClass)
An object of a registered class, not yet loaded.
wxString ReadString()
ANSI (windows-1252) or the 0xFF 0xFFFE UTF-16 form.
TYPED_AWAITER< T > ObjectAs()
int32_t Product() const
bool InBool()
one or four bytes, depending on the active format
uint32_t Count()
a 16-bit count, 0xFFFF escaping to 32 bits
OBJECT_AWAITER Object()
A loader coroutine. Awaiting one queues it on its archive's frame stack instead of nesting the call.
static bool empty(const wxTextEntryBase *aCtrl)
Symbols, components and gates, embedded in designs or the single object of a library item stream.
std::vector< wxString > ExpandPinNumberList(const wxString &aList, wxString *aDisplay)
Expand a gate pin's component pin list by Easy-PC's pin list syntax: items separated by ,...
std::map< std::string, std::function< std::unique_ptr< OBJECT >()>, std::less<> > REGISTRY
LOAD_TASK SkipMember(ARCHIVE &aAr, const char *aClass, bool aDesignOwned)
Load and drop an embedded member of a registered class; aDesignOwned marks its design as owner.
constexpr int NEWEST_ITEM_FORMAT
The newest item format a file can carry (30001)
void RegisterLibraryClasses(REGISTRY &aReg)
@ PRODUCT_DESIGNSPARK
@ PRODUCT_DESIGNSPARK_CREATOR
@ PRODUCT_DESIGNSPARK_PRO
bool IsPadList(const wxString &aPcbSymbolPin)
Whether a gate pin's pad reference names several pads ("-1", the unmapped marker, does not)
const std::vector< OBJECT * > & ListItems(const OBJECT *aList)
The items of a design list or array, empty for anything else.
void Register(REGISTRY &aReg, std::initializer_list< const char * > aNames)
Register the class names whose objects load as a T.
Root of every deserialized object.
The item's own format, returned by the self-versioned classes' ItemFormat.
SOURCE_SCM_COMPONENT * Schematic
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
An array: owner tag, then a counted list of objects.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
int ItemFormat(const ARCHIVE &aAr) const override
The version this object gates on; the base is the archive's current read format.
void LoadOldFormat(ARCHIVE &aAr, int &aFormat) const
An older item format, stored only while the format is still 0.
static void LoadFormatted(ARCHIVE &aAr, int &aFormat)
An item format, stored only from object schema 2, which governs what follows.
A list: owner tag, then the items.
OBJECT * Pins
gate pin array, format above 8999
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
std::vector< int32_t > PcbSymbolPins
older formats: pad number per terminal, -1 unmapped
wxString NetName
default net, or a net class in parentheses
wxString PcbSymbolPin
pad number, "-1", or a pad list
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
std::vector< wxString > PinNames
terminal t is the symbol pad numbered t + 1
Also placement and symbol name origins.
The package half of a component.
OBJECT * GateMaps
one per schematic gate in order
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
OBJECT * Definition
the pin name or number instantiated
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
std::unique_ptr< SOURCE_DESIGN_LIST > DerivedValuePositions
OBJECT * Shapes
free copper list
OBJECT * Texts
free text list
std::unique_ptr< OBJECT > NameOrigin
The symbol name origin of formats below 10003, which becomes the only value position.
std::unique_ptr< SOURCE_VALUE_POSITION > DerivedNamePosition
OBJECT * Pads
free pad list
LOAD_TASK LoadRemainder(ARCHIVE &aAr)
The text position fields that follow the item fields.