Remove broken RefDesStringCompare

This function attempted a poor-man's natural compare but it assumed
specific structure of the string.  This broke for strings with
numberings that looked like decimals.

Instead, we use our natural string comparison function and remove the
references to this older function and its similar elements.

Fixes https://gitlab.com/kicad/code/kicad/issues/9067
This commit is contained in:
Seth Hillbrand 2021-09-01 11:45:10 -07:00
parent bc0302fafe
commit 8a305eec32
10 changed files with 26 additions and 103 deletions

View File

@ -70,46 +70,4 @@ int GetRefDesNumber( const wxString& aRefDes )
return retval; return retval;
} }
} // namespace UTIL
int RefDesStringCompare( const wxString& aFirst, const wxString& aSecond )
{
// Compare unescaped text
wxString strFWord = UnescapeString( aFirst );
wxString strSWord = UnescapeString( aSecond );
// The different sections of the two strings
wxString strFWordBeg, strFWordMid, strFWordEnd;
wxString strSWordBeg, strSWordMid, strSWordEnd;
// Split the two strings into separate parts
SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd );
SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd );
// Compare the Beginning section of the strings
int isEqual = strFWordBeg.Cmp( strSWordBeg );
if( isEqual > 0 )
return 1;
else if( isEqual < 0 )
return -1;
else
{
// If the first sections are equal compare their digits
long lFirstDigit = 0;
long lSecondDigit = 0;
strFWordMid.ToLong( &lFirstDigit );
strSWordMid.ToLong( &lSecondDigit );
if( lFirstDigit > lSecondDigit )
return 1;
else if( lFirstDigit < lSecondDigit )
return -1;
// If the first two sections are equal compare the endings
else
return strFWordEnd.Cmp( strSWordEnd );
}
}
} // namespace UTIL

View File

@ -33,7 +33,6 @@
#include <grid_tricks.h> #include <grid_tricks.h>
#include <string_utils.h> #include <string_utils.h>
#include <kiface_i.h> #include <kiface_i.h>
#include <refdes_utils.h>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <sch_reference_list.h> #include <sch_reference_list.h>
#include <schematic.h> #include <schematic.h>
@ -302,9 +301,9 @@ public:
std::sort( references.begin(), references.end(), std::sort( references.begin(), references.end(),
[]( const SCH_REFERENCE& l, const SCH_REFERENCE& r ) -> bool []( const SCH_REFERENCE& l, const SCH_REFERENCE& r ) -> bool
{ {
wxString l_ref( l.GetRef() << l.GetRefNumber() ); wxString l_ref( l.GetFullRef() );
wxString r_ref( r.GetRef() << r.GetRefNumber() ); wxString r_ref( r.GetFullRef() );
return UTIL::RefDesStringCompare( l_ref, r_ref ) < 0; return StrNumCmp( l_ref, r_ref, true ) < 0;
} ); } );
auto logicalEnd = std::unique( references.begin(), references.end(), auto logicalEnd = std::unique( references.begin(), references.end(),
@ -372,9 +371,9 @@ public:
if( lhs == rhs || sortCol == REFERENCE_FIELD ) if( lhs == rhs || sortCol == REFERENCE_FIELD )
{ {
wxString lhRef = lhGroup.m_Refs[ 0 ].GetRef() + lhGroup.m_Refs[ 0 ].GetRefNumber(); wxString lhRef = lhGroup.m_Refs[ 0 ].GetFullRef();
wxString rhRef = rhGroup.m_Refs[ 0 ].GetRef() + rhGroup.m_Refs[ 0 ].GetRefNumber(); wxString rhRef = rhGroup.m_Refs[ 0 ].GetFullRef();
return local_cmp( UTIL::RefDesStringCompare( lhRef, rhRef ), 0 ); return local_cmp( StrNumCmp( lhRef, rhRef, true ), 0 );
} }
else else
{ {

View File

@ -25,7 +25,7 @@
#include <netlist_exporter_base.h> #include <netlist_exporter_base.h>
#include <refdes_utils.h> #include <string_utils.h>
#include <symbol_library.h> #include <symbol_library.h>
#include <connection_graph.h> #include <connection_graph.h>
@ -117,7 +117,7 @@ SCH_SYMBOL* NETLIST_EXPORTER_BASE::findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PA
static bool sortPinsByNum( PIN_INFO& aPin1, PIN_INFO& aPin2 ) static bool sortPinsByNum( PIN_INFO& aPin1, PIN_INFO& aPin2 )
{ {
// return "lhs < rhs" // return "lhs < rhs"
return UTIL::RefDesStringCompare( aPin1.num, aPin2.num ) < 0; return StrNumCmp( aPin1.num, aPin2.num, true ) < 0;
} }

View File

@ -31,7 +31,7 @@
#include <symbol_library.h> #include <symbol_library.h>
#include <string_utils.h> #include <string_utils.h>
#include <connection_graph.h> #include <connection_graph.h>
#include <refdes_utils.h> #include <string_utils.h>
#include <wx/wfstream.h> #include <wx/wfstream.h>
#include <xnode.h> // also nests: <wx/xml/xml.h> #include <xnode.h> // also nests: <wx/xml/xml.h>
@ -237,8 +237,8 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
auto cmp = [sheet]( SCH_SYMBOL* a, SCH_SYMBOL* b ) auto cmp = [sheet]( SCH_SYMBOL* a, SCH_SYMBOL* b )
{ {
return ( UTIL::RefDesStringCompare( a->GetRef( &sheet ), return ( StrNumCmp( a->GetRef( &sheet, false ),
b->GetRef( &sheet ) ) < 0 ); b->GetRef( &sheet, false ), true ) < 0 );
}; };
std::set<SCH_SYMBOL*, decltype( cmp )> ordered_symbols( cmp ); std::set<SCH_SYMBOL*, decltype( cmp )> ordered_symbols( cmp );
@ -779,5 +779,5 @@ XNODE* NETLIST_EXPORTER_XML::node( const wxString& aName,
static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 ) static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 )
{ {
// return "lhs < rhs" // return "lhs < rhs"
return UTIL::RefDesStringCompare( aPin1->GetShownNumber(), aPin2->GetShownNumber() ) < 0; return StrNumCmp( aPin1->GetShownNumber(), aPin2->GetShownNumber(), true ) < 0;
} }

View File

@ -104,7 +104,7 @@ public:
const char* GetRefStr() const { return m_ref.c_str(); } const char* GetRefStr() const { return m_ref.c_str(); }
///< Return reference name with unit altogether ///< Return reference name with unit altogether
wxString GetFullRef() wxString GetFullRef() const
{ {
if( GetSymbol()->GetUnitCount() > 1 ) if( GetSymbol()->GetUnitCount() > 1 )
return GetRef() + LIB_SYMBOL::SubReference( GetUnit() ); return GetRef() + LIB_SYMBOL::SubReference( GetUnit() );

View File

@ -64,15 +64,6 @@ wxString GetRefDesUnannotated( const wxString& aRefDes );
*/ */
int GetRefDesNumber( const wxString& aRefDes ); int GetRefDesNumber( const wxString& aRefDes );
/**
* Acts just like the strcmp function but treats numbers within the string text
* correctly for sorting. eg. A10 > A2
* return -1 if first string is less than the second
* return 0 if the strings are equal
* return 1 if the first string is greater than the second
*/
int RefDesStringCompare( const wxString& lhs, const wxString& rhs );
} // namespace UTIL } // namespace UTIL
#endif // REFDES_UTILS__H #endif // REFDES_UTILS__H

View File

@ -24,7 +24,7 @@
*/ */
#include <refdes_utils.h> #include <string_utils.h>
#include "pcb_netlist.h" #include "pcb_netlist.h"
#include <footprint.h> #include <footprint.h>
@ -211,7 +211,7 @@ void NETLIST::SortByFPID()
*/ */
bool operator < ( const COMPONENT& item1, const COMPONENT& item2 ) bool operator < ( const COMPONENT& item1, const COMPONENT& item2 )
{ {
return UTIL::RefDesStringCompare( item1.GetReference(), item2.GetReference() ) < 0; return StrNumCmp( item1.GetReference(), item2.GetReference(), true ) < 0;
} }

View File

@ -24,6 +24,7 @@
*/ */
#include <refdes_utils.h> #include <refdes_utils.h>
#include <string_utils.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <wx/filedlg.h> #include <wx/filedlg.h>
#include <tools/board_reannotate_tool.h> #include <tools/board_reannotate_tool.h>
@ -86,7 +87,7 @@ int BOARD_REANNOTATE_TOOL::ReannotateDuplicatesInSelection()
std::sort( fpInSelection.begin(), fpInSelection.end(), std::sort( fpInSelection.begin(), fpInSelection.end(),
[]( const FOOTPRINT* aA, const FOOTPRINT* aB ) -> bool []( const FOOTPRINT* aA, const FOOTPRINT* aB ) -> bool
{ {
int ii = UTIL::RefDesStringCompare( aA->GetReference(), aB->GetReference() ); int ii = StrNumCmp( aA->GetReference(), aB->GetReference(), true );
if( ii == 0 ) if( ii == 0 )
ii = aA->m_Uuid < aB->m_Uuid; // ensure a deterministic sort ii = aA->m_Uuid < aB->m_Uuid; // ensure a deterministic sort

View File

@ -93,7 +93,13 @@ BOOST_AUTO_TEST_CASE( NaturalNumberCompare )
{ { "u10", "u10" }, { 0, 0 } }, { { "u10", "u10" }, { 0, 0 } },
{ { "U10", "U10" }, { 0, 0 } }, { { "U10", "U10" }, { 0, 0 } },
{ { "u10", "U10" }, { 1, 0 } }, { { "u10", "U10" }, { 1, 0 } },
{ { "U10", "u10" }, { -1, 0 } } { { "U10", "u10" }, { -1, 0 } },
{ { "U10.1", "U10.10" }, { -1, -1 } },
{ { "U10-1", "U10-10" }, { -1, -1 } },
{ { "U10,1", "U10,10" }, { -1, -1 } },
{ { "U10.A", "U10.a" }, { -1, 0 } },
{ { "U10-A", "U10-a" }, { -1, 0 } },
{ { "U10,A", "U10,a" }, { -1, 0 } },
}; };
for( const auto& c : cases ) for( const auto& c : cases )

View File

@ -66,36 +66,4 @@ BOOST_AUTO_TEST_CASE( GetPrefix )
} }
struct REF_DES_COMP_CASE
{
std::string m_refdes_a;
std::string m_refdes_b;
int m_exp_res;
};
/**
* Test the #UTIL::RefDesStringCompare function
*/
BOOST_AUTO_TEST_CASE( RefDesComp )
{
const int SAME = 0;
const int LESS = -1;
const int MORE = 1;
const std::vector<REF_DES_COMP_CASE> cases = {
{ "", "", SAME },
{ "U", "U", SAME },
{ "U1", "U1", SAME },
{ "U1", "U2", LESS },
{ "U2", "U1", MORE },
{ "U1000", "U2000", LESS },
};
for( const auto& c : cases )
{
BOOST_CHECK_EQUAL( UTIL::RefDesStringCompare( c.m_refdes_a, c.m_refdes_b ), c.m_exp_res );
}
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()