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#include <wx/arrstr.h> // Imports wx's std::vector<wxString> specialization on MSVC.
22
23
24namespace EASYPC
25{
26
27namespace
28{
29
31 void serializeFormat( ARCHIVE& aAr, SELF_VERSIONED& aItem )
32 {
33 SOURCE_DESIGN_ITEM::LoadFormatted( aAr, aItem.Format );
34 aAr.SetBooleanIsByte( aItem.Format > 7999 );
35 }
36
37} // namespace
38
39
41{
42 serializeFormat( aAr, *this );
43 co_await SOURCE_DESIGN_ITEM::Load( aAr );
44 LoadOldFormat( aAr, Format );
45
46 const int v = Format;
47
48 const bool nameFirst = v >= 22000 || aAr.Product() != PRODUCT_DESIGNSPARK;
49
50 if( nameFirst )
51 Name = aAr.ReadString();
52
53 Shapes = co_await aAr.Object();
54 Pads = co_await aAr.Object();
55 Texts = co_await aAr.Object();
56
57 if( !nameFirst )
58 Name = aAr.ReadString();
59
60 if( v > 10002 )
61 ValuePositions = co_await aAr.Object();
62
63 OriginX = aAr.I32();
64 OriginY = aAr.I32();
65 Timestamp = aAr.I32();
66
67 if( v < 10003 )
68 {
69 NameOrigin = ARCHIVE::Create( "CSymbolNameOrigin" );
70
71 if( v > 2999 )
72 aAr.MapObject( NameOrigin.get() );
73
74 co_await aAr.Embedded( *NameOrigin, "CSymbolNameOrigin" );
75
76 // An old symbol's name origin becomes its name position; types 0x1f without a layer, 0xf with one
77 const SOURCE_ORIGIN& origin = static_cast<const SOURCE_ORIGIN&>( *NameOrigin );
78 DerivedNamePosition = std::make_unique<SOURCE_VALUE_POSITION>();
79 DerivedNamePosition->Position = origin.Position;
80 DerivedNamePosition->Layer = origin.Layer;
81 DerivedNamePosition->TextStyle = origin.TextStyle;
82 DerivedNamePosition->Types = origin.Layer ? 0xf : 0x1f;
83
84 DerivedValuePositions = std::make_unique<SOURCE_DESIGN_LIST>();
85 DerivedValuePositions->Items.push_back( DerivedNamePosition.get() );
87 }
88 else if( v >= 12003 )
89 {
90 bool tail = true;
91
92 co_await aAr.Object(); // origins
93
94 if( v < 14001 )
95 {
96 co_await SkipMember( aAr, "CScreenGrid" );
97 co_await SkipMember( aAr, "CUnits" );
98 co_await SkipMember( aAr, "COldWorkingGrid" );
99 tail = v > 12006;
100 }
101 else
102 {
103 co_await SkipMember( aAr, "CGrid" );
104 co_await SkipMember( aAr, "CUnits" );
105 }
106
107 if( tail )
108 {
109 aAr.InBool();
110 aAr.Skip( 16 ); // system and relative origins
111
112 if( v > 12999 )
113 co_await aAr.Object();
114
115 if( v > 15001 )
116 {
117 Library = aAr.ReadString();
118 aAr.Skip( 1 );
119 }
120 }
121 }
122
123 if( v > 28000 )
124 co_await aAr.Object();
125}
126
127
129{
130 co_await SOURCE_DESIGN_ITEM::Load( aAr );
131 co_await LoadRemainder( aAr );
132
133 if( ItemFormat( aAr ) > 2103 )
134 Visible = aAr.InBool();
135}
136
137
139{
140 co_await SOURCE_DESIGN_ITEM::Load( aAr );
141
142 Definition = co_await aAr.Object();
143
144 if( ItemFormat( aAr ) > 2103 )
145 Visible = aAr.InBool();
146}
147
148
150{
151 co_await SOURCE_DESIGN_ITEM::Load( aAr );
152
153 Symbol = aAr.ReadString();
154
155 for( int32_t i = aAr.I32(); i > 0; --i )
156 PinNames.push_back( aAr.ReadString() );
157
158 if( ItemFormat( aAr ) > 2003 )
159 Library = aAr.ReadString();
160}
161
162
163const std::vector<OBJECT*>& ListItems( const OBJECT* aList )
164{
165 static const std::vector<OBJECT*> empty;
166
167 if( const SOURCE_DESIGN_LIST* list = dynamic_cast<const SOURCE_DESIGN_LIST*>( aList ) )
168 return list->Items;
169
170 if( const SOURCE_DESIGN_ARRAY* array = dynamic_cast<const SOURCE_DESIGN_ARRAY*>( aList ) )
171 return array->Items;
172
173 return empty;
174}
175
176
178{
179 Parent = co_await aAr.Object();
180
181 for( uint32_t i = aAr.Count(); i > 0; --i )
182 Items.push_back( co_await aAr.Object() );
183}
184
185
187{
188 co_await SOURCE_DESIGN_ITEM::Load( aAr );
189
190 if( ItemFormat( aAr ) > 8999 )
191 {
192 Pins = co_await aAr.Object();
193 co_return;
194 }
195
196 for( int32_t i = aAr.I32(); i > 0; --i )
197 PcbSymbolPins.push_back( aAr.I32() );
198}
199
200
202{
203 co_await SOURCE_DESIGN_ITEM::Load( aAr );
204
205 if( ItemFormat( aAr ) < 12005 )
206 PcbSymbolPin = wxString::Format( wxS( "%d" ), aAr.I32() );
207 else
208 PcbSymbolPin = aAr.ReadString();
209
210 PinNumber = aAr.ReadString();
211 NetName = aAr.ReadString();
212
213 if( ItemFormat( aAr ) > 22999 )
214 PinType = aAr.U32();
215}
216
217
219{
220 serializeFormat( aAr, *this );
221 co_await SOURCE_DESIGN_ITEM::Load( aAr );
222 LoadOldFormat( aAr, Format );
223
224 const int f = Format;
225 const int32_t product = aAr.Product();
226
227 // The DesignSpark products store the package first
228 if( product == PRODUCT_DESIGNSPARK || product == PRODUCT_DESIGNSPARK_CREATOR || product == PRODUCT_DESIGNSPARK_PRO )
229 {
230 Package = aAr.ReadString();
231 Name = aAr.ReadString();
232 }
233 else
234 {
235 Name = aAr.ReadString();
236 Package = aAr.ReadString();
237 }
238
239 Gates = co_await aAr.Object();
241 Description = aAr.ReadString();
242
243 if( f > 4999 )
244 aAr.Skip( 4 ); // show flags
245
246 if( f > 15001 )
247 {
248 Library = aAr.ReadString();
249 aAr.Skip( 1 );
250 }
251
252 if( f > 16999 )
253 SuppressionFlags = aAr.U32();
254
255 if( f > 21999 )
256 aAr.Skip( 1 );
257
258 // Reset once loaded, so later objects chaining to this one gate on 30001
260}
261
262
264{
265 serializeFormat( aAr, *this );
266 co_await SOURCE_DESIGN_ITEM::Load( aAr );
267 LoadOldFormat( aAr, Format );
268
269 Package = aAr.ReadString();
270 Symbol = aAr.ReadString();
271 GateMaps = co_await aAr.Object();
272 aAr.SkipString(); // package description
273 aAr.Skip( 4 ); // version
274
275 if( Format > 2003 )
276 Library = aAr.ReadString();
277
278 // A null tag in every known file
279 if( Format > 21999 )
280 co_await aAr.Object();
281
283}
284
285
287{
288 co_await SOURCE_DESIGN_ITEM::Load( aAr );
289
290 Board = co_await aAr.ObjectAs<SOURCE_PCB_COMPONENT>();
291 Schematic = co_await aAr.ObjectAs<SOURCE_SCM_COMPONENT>();
292}
293
294
295bool IsPadList( const wxString& aPcbSymbolPin )
296{
297 if( aPcbSymbolPin.Contains( wxS( "," ) ) || aPcbSymbolPin.Contains( wxS( "+" ) )
298 || aPcbSymbolPin.Contains( wxS( "=" ) ) )
299 {
300 return true;
301 }
302
303 // "-1" is the unmapped marker, any other '-' is a range
304 return aPcbSymbolPin.Find( '-' ) > 0;
305}
306
307
308std::vector<wxString> ExpandPinNumberList( const wxString& aList, wxString* aDisplay )
309{
310 // A range wider than any part is file damage and stays one literal item
311 constexpr uint64_t MAX_PIN_RANGE = 100000;
312
313 std::vector<wxString> out;
314 wxString list = aList;
315 int eq = list.Find( '=' );
316
317 if( eq != wxNOT_FOUND )
318 {
319 if( aDisplay )
320 *aDisplay = list.Left( eq );
321
322 list = list.Mid( eq + 1 );
323 }
324
325 wxString item;
326
327 auto flush = [&]()
328 {
329 long first = 0;
330 long last = 0;
331 int dash = item.Find( '-' );
332
333 if( dash > 0 && item.Left( dash ).ToLong( &first ) && item.Mid( dash + 1 ).ToLong( &last ) && first <= last
334 && uint64_t( last ) - uint64_t( first ) < MAX_PIN_RANGE )
335 {
336 // Stopping before the increment keeps a range ending at LONG_MAX from overflowing
337 for( long n = first;; ++n )
338 {
339 out.push_back( wxString::Format( wxS( "%ld" ), n ) );
340
341 if( n == last )
342 break;
343 }
344 }
345 else if( !item.IsEmpty() )
346 {
347 out.push_back( item );
348 }
349
350 item.Clear();
351 };
352
353 for( wxUniChar ch : list )
354 {
355 if( ch == ',' || ch == '+' )
356 flush();
357 else
358 item += ch;
359 }
360
361 flush();
362 return out;
363}
364
365
367{
368 Register<SOURCE_SYMBOL>( aReg, { "CSymbol" } );
369 Register<SOURCE_SCM_COMPONENT>( aReg, { "CScmComponent" } );
370 Register<SOURCE_PCB_COMPONENT>( aReg, { "CPcbComponent" } );
371 Register<SOURCE_COMPONENT>( aReg, { "CComponent" } );
372 Register<SOURCE_GATE>( aReg, { "CGate" } );
373 Register<SOURCE_GATE_MAP>( aReg, { "CGateMap" } );
374 Register<SOURCE_GATE_PIN>( aReg, { "CGatePin" } );
375 Register<SOURCE_DESIGN_ARRAY>( aReg, { "CDesignArray", "CGateArray", "CGateMapArray", "CGatePinArray" } );
376 Register<SOURCE_DESIGN_LIST>( aReg, { "CSymbolArray", "CComponentArray", "CScmComponentArray" } );
377 Register<SOURCE_PIN_NAME>( aReg, { "CPinName", "CPinNumber" } );
378 Register<SOURCE_PIN_NAME_INSTANCE>( aReg, { "CPinNameInstance", "CPinNumberInstance" } );
379
380 // These carry the plain text position and origin fields
381 Register<SOURCE_TEXT_POSITION>( aReg, { "CSymbolName" } );
382 Register<SOURCE_ORIGIN>( aReg, { "CSymbolNameOrigin" } );
383}
384
385} // 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.