Break out ref-des-centric functions to own header

This breaks the following functions out to a general-purposed refdes utils
header:

* MODULE::GetReferencePrefix()
* kicad_string.h RefDesStringCompare()

This acheives:

* Slimming of MODULE interface
* Placement of refdes code in common rather than pcbnew
** Testing of this code in qa_common
* Tighter and smaller includes for code that only needed refdes functions

Note: there are failing tests commited (as expected failures). These
are the cause of lp:1813669 and will be fixed as a follow-up commit.
This commit is contained in:
John Beard 2019-01-29 10:50:50 +00:00 committed by Seth Hillbrand
parent dc20521cb9
commit 88f9f6f072
16 changed files with 288 additions and 118 deletions

View File

@ -338,6 +338,7 @@ set( COMMON_SRCS
project.cpp
properties.cpp
ptree.cpp
refdes_utils.cpp
reporter.cpp
richio.cpp
search_stack.cpp

94
common/refdes_utils.cpp Normal file
View File

@ -0,0 +1,94 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <refdes_utils.h>
#include <kicad_string.h>
namespace UTIL
{
wxString GetReferencePrefix( const wxString& aRefDes )
{
wxString prefix = aRefDes;
int strIndex = prefix.length() - 1;
while( strIndex >= 0 )
{
const wxUniChar chr = prefix.GetChar( strIndex );
// numeric suffix
if( chr >= '0' && chr <= '9' )
break;
strIndex--;
}
prefix = prefix.Mid( 0, strIndex );
return prefix;
}
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.CmpNoCase( 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.CmpNoCase( strSWordEnd );
}
}
} // namespace UTIL

View File

@ -539,47 +539,6 @@ int ValueStringCompare( wxString strFWord, wxString strSWord )
}
int RefDesStringCompare( wxString strFWord, wxString strSWord )
{
// Compare unescaped text
strFWord = UnescapeString( strFWord );
strSWord = UnescapeString( strSWord );
// 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.CmpNoCase( 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.CmpNoCase( strSWordEnd );
}
}
int SplitString( wxString strToSplit,
wxString* strBeginning,
wxString* strDigits,

View File

@ -28,6 +28,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <sch_reference_list.h>
#include <wx/regex.h>
#include <algorithm>
@ -35,12 +36,12 @@
#include <unordered_set>
#include <fctsys.h>
#include <kicad_string.h>
#include <sch_edit_frame.h>
#include <sch_reference_list.h>
#include <sch_component.h>
#include <refdes_utils.h>
#include <reporter.h>
#include <sch_component.h>
#include <sch_edit_frame.h>
//#define USE_OLD_ALGO
@ -113,7 +114,7 @@ bool SCH_REFERENCE_LIST::sortByReferenceOnly( const SCH_REFERENCE& item1,
{
int ii;
ii = RefDesStringCompare( item1.GetRef(), item2.GetRef() );
ii = UTIL::RefDesStringCompare( item1.GetRef(), item2.GetRef() );
if( ii == 0 )
{

View File

@ -31,6 +31,7 @@
#include <bitmaps.h>
#include <grid_tricks.h>
#include <kicad_string.h>
#include <refdes_utils.h>
#include <build_version.h>
#include <general.h>
#include <sch_view.h>
@ -289,7 +290,7 @@ public:
{
wxString l_ref( l.GetRef() << l.GetRefNumber() );
wxString r_ref( r.GetRef() << r.GetRefNumber() );
return RefDesStringCompare( l_ref, r_ref ) < 0;
return UTIL::RefDesStringCompare( l_ref, r_ref ) < 0;
} );
auto logicalEnd = std::unique( references.begin(), references.end(),
@ -357,7 +358,7 @@ public:
{
wxString lhRef = lhGroup.m_Refs[ 0 ].GetRef() + lhGroup.m_Refs[ 0 ].GetRefNumber();
wxString rhRef = rhGroup.m_Refs[ 0 ].GetRef() + rhGroup.m_Refs[ 0 ].GetRefNumber();
retVal = RefDesStringCompare( lhRef, rhRef ) < 0;
retVal = UTIL::RefDesStringCompare( lhRef, rhRef ) < 0;
}
else
retVal = ValueStringCompare( lhs, rhs ) < 0;

View File

@ -23,23 +23,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file netlist_exporter.cpp
*/
#include <fctsys.h>
#include <confirm.h>
#include <kicad_string.h>
#include <gestfich.h>
#include <pgm_base.h>
#include <sch_reference_list.h>
#include <class_library.h>
#include <netlist.h>
#include <netlist_exporter.h>
#include <confirm.h>
#include <fctsys.h>
#include <gestfich.h>
#include <pgm_base.h>
#include <refdes_utils.h>
#include <class_library.h>
#include <netlist.h>
#include <sch_reference_list.h>
wxString NETLIST_EXPORTER::MakeCommandLine( const wxString& aFormatString,
@ -157,7 +151,7 @@ SCH_COMPONENT* NETLIST_EXPORTER::findNextComponent( EDA_ITEM* aItem, SCH_SHEET_P
static bool sortPinsByNum( NETLIST_OBJECT* aPin1, NETLIST_OBJECT* aPin2 )
{
// return "lhs < rhs"
return RefDesStringCompare( aPin1->GetPinNumText(), aPin2->GetPinNumText() ) < 0;
return UTIL::RefDesStringCompare( aPin1->GetPinNumText(), aPin2->GetPinNumText() ) < 0;
}

View File

@ -23,14 +23,15 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <build_version.h>
#include <sch_base_frame.h>
#include <class_library.h>
#include "netlist_exporter_generic.h"
#include <sch_edit_frame.h>
#include <build_version.h>
#include <refdes_utils.h>
#include <class_library.h>
#include <sch_base_frame.h>
#include <symbol_lib_table.h>
#include "netlist_exporter_generic.h"
static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 );
@ -556,5 +557,5 @@ XNODE* NETLIST_EXPORTER_GENERIC::node( const wxString& aName, const wxString& aT
static bool sortPinsByNumber( LIB_PIN* aPin1, LIB_PIN* aPin2 )
{
// return "lhs < rhs"
return RefDesStringCompare( aPin1->GetNumber(), aPin2->GetNumber() ) < 0;
return UTIL::RefDesStringCompare( aPin1->GetNumber(), aPin2->GetNumber() ) < 0;
}

View File

@ -26,11 +26,13 @@
#ifndef NETLIST_EXPORT_GENERIC_H
#define NETLIST_EXPORT_GENERIC_H
#include <project.h>
#include <netlist_exporter.h>
#include <project.h>
#include <xnode.h> // also nests: <wx/xml/xml.h>
#include <sch_edit_frame.h>
class SYMBOL_LIB_TABLE;
#define GENERIC_INTERMEDIATE_NETLIST_EXT wxT( "xml" )

View File

@ -148,16 +148,6 @@ bool WildCompareString( const wxString& pattern,
*/
int ValueStringCompare( wxString strFWord, wxString strSWord );
/**
* Function RefDesStringCompare
* 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( wxString lhs, wxString rhs );
/**
* Function SplitString
* breaks a string into three parts.

57
include/refdes_utils.h Normal file
View File

@ -0,0 +1,57 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file
* Collection of utility functions for component reference designators (refdes)
*/
#ifndef REFDES_UTILS__H
#define REFDES_UTILS__H
#include <wx/string.h>
namespace UTIL
{
/**
* Get the (non-numeric) prefix from a refdes - e.g.
* R1 -> R
* IC34 -> IC
* @param aRefDes full refdes
* @return the prefix, or empty string if nothing found
*/
wxString GetReferencePrefix( 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
#endif // REFDES_UTILS__H

View File

@ -29,7 +29,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <kicad_string.h>
#include <refdes_utils.h>
#include <vector>
// Helper class to store parameters for a regulator
class REGULATOR_DATA
@ -78,7 +80,7 @@ public:
unsigned ii = 0;
for( ; ii < m_List.size(); ii++ )
{
if( RefDesStringCompare( aItem->m_Name, m_List[ii]->m_Name ) < 0 )
if( UTIL::RefDesStringCompare( aItem->m_Name, m_List[ii]->m_Name ) < 0 )
break;
}
m_List.insert( m_List.begin() + ii, aItem );

View File

@ -37,6 +37,7 @@
#include <confirm.h>
#include <kicad_string.h>
#include <pcbnew.h>
#include <refdes_utils.h>
#include <richio.h>
#include <filter_reader.h>
#include <macros.h>
@ -1319,32 +1320,11 @@ wxString MODULE::GetNextPadName( bool aFillSequenceGaps ) const
}
wxString MODULE::GetReferencePrefix() const
{
wxString prefix = GetReference();
int strIndex = prefix.length() - 1;
while( strIndex >= 0 )
{
const wxUniChar chr = prefix.GetChar( strIndex );
// numeric suffix
if( chr >= '0' && chr <= '9' )
break;
strIndex--;
}
prefix = prefix.Mid( 0, strIndex );
return prefix;
}
void MODULE::IncrementReference( int aDelta )
{
SetReference( wxString::Format(
wxT( "%s%i" ), GetReferencePrefix(), GetTrailingInt( GetReference() ) + aDelta ) );
const auto& refdes = GetReference();
SetReference( wxString::Format( wxT( "%s%i" ), UTIL::GetReferencePrefix( refdes ),
GetTrailingInt( refdes ) + aDelta ) );
}

View File

@ -474,15 +474,6 @@ public:
m_Reference->SetText( aReference );
}
/**
* Function GetReferencePrefix
* Gets the alphabetic prefix of the module reference - e.g.
* R1 -> R
* IC34 -> IC
* @return the reference prefix (may be empty)
*/
wxString GetReferencePrefix() const;
/**
* Function IncrementReference
* Bumps the current reference by aDelta.

View File

@ -28,7 +28,7 @@
#include <macros.h>
#include <kicad_string.h>
#include <refdes_utils.h>
#include <reporter.h>
#include <pcb_netlist.h>
@ -197,7 +197,7 @@ void NETLIST::SortByFPID()
*/
bool operator < ( const COMPONENT& item1, const COMPONENT& item2 )
{
return RefDesStringCompare(item1.GetReference(), item2.GetReference() ) < 0;
return UTIL::RefDesStringCompare( item1.GetReference(), item2.GetReference() ) < 0;
}

View File

@ -42,6 +42,7 @@ set( common_srcs
test_format_units.cpp
test_hotkey_store.cpp
test_kicad_string.cpp
test_refdes_utils.cpp
test_title_block.cpp
test_utf8.cpp
test_wildcards_and_files_ext.cpp

View File

@ -0,0 +1,96 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file
* Test suite for refdes functions
*/
#include <unit_test_utils/unit_test_utils.h>
// Code under test
#include <refdes_utils.h>
/**
* Declare the test suite
*/
BOOST_AUTO_TEST_SUITE( RefdesUtils )
#ifdef HAVE_EXPECTED_FAILURES
/**
* Test the #UTIL::GetReferencePrefix function
*/
BOOST_AUTO_TEST_CASE( GetPrefix, *boost::unit_test::expected_failures( 2 ) )
{
using CASE = std::pair<std::string, std::string>;
const std::vector<CASE> cases = {
{ "", "" }, // empty
{ "U", "U" }, // no number
{ "U1", "U" }, // single digit
{ "U10", "U" }, // double digit // fails!
{ "U1000", "U" }, //multi digit // fails!
};
for( const auto& c : cases )
{
BOOST_CHECK_EQUAL( UTIL::GetReferencePrefix( c.first ), c.second );
}
}
#endif
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()