Browse Source

Speed up symbol loading

Loading symbols, we need pin counts but we don't need to generate a
bunch of strings to do that.  Provides a fast path for counting number
of pins represented by the stacked pin notation
master
Seth Hillbrand 2 days ago
parent
commit
677676f457
  1. 85
      common/string_utils.cpp
  2. 19
      eeschema/lib_symbol.cpp
  3. 8
      eeschema/sch_pin.cpp
  4. 13
      eeschema/sch_pin.h
  5. 12
      include/string_utils.h
  6. 52
      qa/tests/eeschema/test_stacked_pin_conversion.cpp

85
common/string_utils.cpp

@ -1629,6 +1629,91 @@ std::vector<wxString> ExpandStackedPinNotation( const wxString& aPinName, bool*
}
int CountStackedPinNotation( const wxString& aPinName, bool* aValid )
{
if( aValid )
*aValid = true;
// Fast path: if no brackets, it's a single pin
const bool hasOpenBracket = aPinName.Contains( wxT( "[" ) );
const bool hasCloseBracket = aPinName.Contains( wxT( "]" ) );
if( hasOpenBracket || hasCloseBracket )
{
if( !aPinName.StartsWith( wxT( "[" ) ) || !aPinName.EndsWith( wxT( "]" ) ) )
{
if( aValid )
*aValid = false;
return 1;
}
}
if( !aPinName.StartsWith( wxT( "[" ) ) || !aPinName.EndsWith( wxT( "]" ) ) )
return 1;
const wxString inner = aPinName.Mid( 1, aPinName.Length() - 2 );
int count = 0;
size_t start = 0;
while( start < inner.length() )
{
size_t comma = inner.find( ',', start );
wxString part = ( comma == wxString::npos ) ? inner.Mid( start ) : inner.Mid( start, comma - start );
part.Trim( true ).Trim( false );
if( part.empty() )
{
start = ( comma == wxString::npos ) ? inner.length() : comma + 1;
continue;
}
int dashPos = part.Find( '-' );
if( dashPos != wxNOT_FOUND )
{
wxString startTxt = part.Left( dashPos );
wxString endTxt = part.Mid( dashPos + 1 );
startTxt.Trim( true ).Trim( false );
endTxt.Trim( true ).Trim( false );
auto [startPrefix, startVal] = ParseAlphaNumericPin( startTxt );
auto [endPrefix, endVal] = ParseAlphaNumericPin( endTxt );
if( startPrefix != endPrefix || startVal == -1 || endVal == -1 || startVal > endVal )
{
if( aValid )
*aValid = false;
return 1;
}
// Count pins in the range
count += static_cast<int>( endVal - startVal + 1 );
}
else
{
// Single pin
++count;
}
if( comma == wxString::npos )
break;
start = comma + 1;
}
if( count == 0 )
{
if( aValid )
*aValid = false;
return 1;
}
return count;
}
wxString GetDefaultVariantName()
{
return wxString( defaultVariantName );

19
eeschema/lib_symbol.cpp

@ -916,18 +916,13 @@ int LIB_SYMBOL::GetPinCount()
for( SCH_PIN* pin : GetGraphicalPins( 0 /* all units */, 1 /* single body style */ ) )
{
bool valid;
std::vector<wxString> numbers = pin->GetStackedPinNumbers( &valid );
wxLogTrace( "CVPCB_PINCOUNT",
wxString::Format( "LIB_SYMBOL::GetPinCount lib='%s' pin base='%s' shown='%s' valid=%d +%zu",
GetLibId().Format().wx_str(), pin->GetName(),
pin->GetShownNumber(), valid, numbers.size() ) );
count += numbers.size();
}
wxLogTrace( "CVPCB_PINCOUNT",
wxString::Format( "LIB_SYMBOL::GetPinCount total for lib='%s' => %d",
GetLibId().Format().wx_str(), count ) );
int pinCount = pin->GetStackedPinCount();
count += pinCount;
}
wxLogTrace( "CVPCB_PINCOUNT", "LIB_SYMBOL::GetPinCount total for lib='%s' => %d", GetLibId().Format().wx_str(),
count );
return count;
}

8
eeschema/sch_pin.cpp

@ -609,6 +609,14 @@ std::vector<wxString> SCH_PIN::GetStackedPinNumbers( bool* aValid ) const
return numbers;
}
int SCH_PIN::GetStackedPinCount( bool* aValid ) const
{
wxString shown = GetShownNumber();
return CountStackedPinNotation( shown, aValid );
}
std::optional<wxString> SCH_PIN::GetSmallestLogicalNumber() const
{
bool valid = false;

13
eeschema/sch_pin.h

@ -124,6 +124,19 @@ public:
const wxString& GetNumber() const { return m_number; }
wxString GetShownNumber() const;
std::vector<wxString> GetStackedPinNumbers( bool* aValid = nullptr ) const;
/**
* Return the count of logical pins represented by this pin's stacked notation.
*
* This is a fast alternative to GetStackedPinNumbers().size() that avoids
* allocating and populating a vector of strings.
*
* @param aValid Optional pointer to bool that will be set to indicate if the
* stacked notation is valid (true) or malformed (false).
* @return The number of logical pins represented (always >= 1).
*/
int GetStackedPinCount( bool* aValid = nullptr ) const;
/**
* Return the smallest logical pin number if this pin uses stacked
* notation and it is valid. Otherwise returns std::nullopt.

12
include/string_utils.h

@ -494,6 +494,18 @@ KICOMMON_API wxString NormalizeFileUri( const wxString& aFileUri );
KICOMMON_API std::vector<wxString> ExpandStackedPinNotation( const wxString& aPinName,
bool* aValid = nullptr );
/**
* Count the number of pins represented by stacked pin notation without allocating strings.
*
* This is a fast alternative to ExpandStackedPinNotation().size() for cases where only
* the count is needed.
*
* @param aPinName is the pin name to count (may or may not use stacked notation)
* @param aValid is optionally set to indicate whether the notation was valid
* @return count of individual pins represented (always >= 1)
*/
KICOMMON_API int CountStackedPinNotation( const wxString& aPinName, bool* aValid = nullptr );
KICOMMON_API wxString GetDefaultVariantName();

52
qa/tests/eeschema/test_stacked_pin_conversion.cpp

@ -772,4 +772,56 @@ BOOST_AUTO_TEST_CASE( TestDuplicatePinDetectionWithStackedNotation )
BOOST_CHECK( messages.empty() );
}
/**
* Test that GetStackedPinCount returns the same count as GetStackedPinNumbers().size()
* but more efficiently
*/
BOOST_AUTO_TEST_CASE( TestStackedPinCountEfficiency )
{
// Test cases with different pin notations
struct TestCase
{
wxString notation;
int expectedCount;
bool expectedValid;
};
std::vector<TestCase> testCases = {
{ wxT( "1" ), 1, true }, // Simple pin
{ wxT( "[1,2,3]" ), 3, true }, // List notation
{ wxT( "[5-7]" ), 3, true }, // Range notation
{ wxT( "[1,3,5-7]" ), 5, true }, // Mixed notation
{ wxT( "[A1-A5]" ), 5, true }, // Alphanumeric range
{ wxT( "[1-10]" ), 10, true }, // Larger range
{ wxT( "[PA1,PA2,PB5-PB8]" ), 6, true }, // Complex mixed
{ wxT( "[1-3,10,20-22]" ), 7, true }, // Multiple ranges
{ wxT( "[10" ), 1, false }, // Invalid (missing bracket)
{ wxT( "10]" ), 1, false }, // Invalid (missing bracket)
{ wxT( "[5-3]" ), 1, false }, // Invalid (reverse range)
};
for( const auto& testCase : testCases )
{
SCH_PIN* pin = new SCH_PIN( m_symbol.get() );
pin->SetNumber( testCase.notation );
bool validExpand = false;
bool validCount = false;
std::vector<wxString> expanded = pin->GetStackedPinNumbers( &validExpand );
int count = pin->GetStackedPinCount( &validCount );
// Both methods should agree on validity
BOOST_CHECK_EQUAL( validExpand, validCount );
BOOST_CHECK_EQUAL( validExpand, testCase.expectedValid );
// Both methods should return the same count
BOOST_CHECK_EQUAL( static_cast<int>( expanded.size() ), count );
BOOST_CHECK_EQUAL( count, testCase.expectedCount );
delete pin;
}
}
BOOST_AUTO_TEST_SUITE_END()
Loading…
Cancel
Save