35    std::unique_lock<std::mutex> lock;
 
   38        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
 
   79    std::unique_lock<std::mutex> lock;
 
   82        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
 
   89                                           const std::map<
int, std::vector<SCH_REFERENCE>>& aRefNumberMap,
 
   90                                           const std::vector<int>& aRequiredUnits,
 
   93    std::unique_lock<std::mutex> lock;
 
   96        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
   99    std::vector<int> validUnits;
 
  100    std::copy_if( aRequiredUnits.begin(), aRequiredUnits.end(),
 
  101                  std::back_inserter( validUnits ),
 
  102                  []( 
int unit ) { return unit >= 0; } );
 
  104    int candidate = aMinValue;
 
  109        auto mapIt = aRefNumberMap.find( candidate );
 
  111        if( mapIt == aRefNumberMap.end() )
 
  114            std::string candidateRefDes = aRef.
GetRef().ToStdString() + std::to_string( candidate );
 
  133            if( validUnits.empty() )
 
 
  171                                        const std::vector<SCH_REFERENCE>& aRefVector,
 
  172                                        const std::vector<int>& aRequiredUnits )
 const 
  174    for( 
const int& unit : aRequiredUnits )
 
  181            if( ref.CompareLibName( aRef ) != 0
 
  182                || ref.CompareValue( aRef ) != 0
 
  183                || ref.GetUnit() == unit )
 
 
  196    if( aRefDes.empty() )
 
  200    std::regex pattern( R
"(^([A-Za-z]+)(\d+)?$)" ); 
  203    if( std::regex_match( aRefDes, match, pattern ) )
 
  205        std::string prefix = match[1].str();
 
  206        if( match[2].matched )
 
  208            int number = std::stoi( match[2].str() );
 
  209            return { prefix, number };
 
  213            return { prefix, 0 };  
 
  218    return { aRefDes, 0 };
 
 
  232        if( used == candidate )
 
  236        else if( used > candidate )
 
 
  267        int cachedNext = cacheIt->second;
 
  269        if( aInsertedNumber == cachedNext )
 
  272            int candidate = cachedNext + 1;
 
  277            cacheIt->second = candidate;
 
 
  285        return cacheIt->second;
 
  298        candidate = aMinValue;
 
 
  312    std::unique_lock<std::mutex> lock;
 
  314        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
  316    std::ostringstream 
result;
 
  328        std::vector<int> numbers;
 
  329        bool hasPrefix = 
false;
 
  331        for( 
int num : data.m_usedNumbers )
 
  334                numbers.push_back( num );
 
  339        if( numbers.empty() && !hasPrefix )
 
  343        std::vector<std::pair<int, int>> ranges;
 
  345        if( !numbers.empty() )
 
  347            int start = numbers[0];
 
  348            int end = numbers[0];
 
  350            for( 
size_t i = 1; i < numbers.size(); ++i )
 
  352                if( numbers[i] == 
end + 1 )
 
  358                    ranges.push_back( { start, 
end } );
 
  359                    start = 
end = numbers[i];
 
  362            ranges.push_back( { start, 
end } );
 
  365        bool firstRange = 
true;
 
  366        for( 
const auto& [start, 
end] : ranges )
 
 
  397    std::unique_lock<std::mutex> lock;
 
  400        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
  409    for( 
const std::string& part : parts )
 
  414        std::regex rangePattern( R
"(^([A-Za-z]+)(\d+)(?:-(\d+))?$)" ); 
  415        std::regex prefixOnlyPattern( R"(^([A-Za-z]+)$)" ); 
  418        if( std::regex_match( unescaped, match, rangePattern ) )
 
  420            std::string prefix = match[1].str();
 
  421            int start = std::stoi( match[2].str() );
 
  422            int end = match[3].matched ? std::stoi( match[3].str() ) : start;
 
  424            for( 
int i = start; i <= 
end; ++i )
 
  426                if( !
insertImpl( prefix + std::to_string( i ) ) )
 
  433        else if( std::regex_match( unescaped, match, prefixOnlyPattern ) )
 
  435            std::string prefix = match[1].str();
 
 
  455    std::unique_lock<std::mutex> lock;
 
  458        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
 
  472    std::unique_lock<std::mutex> lock;
 
  475        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
 
  483    result.reserve( aStr.length() * 2 ); 
 
  487        if( c == 
'\\' || c == 
',' || c == 
'-' )
 
 
  497    result.reserve( aStr.length() );
 
  499    bool escaped = 
false;
 
 
  521    std::vector<std::string> 
result;
 
  523    bool escaped = 
false;
 
  537        else if( c == aDelimiter )
 
  539            result.push_back( current );
 
  548    if( !current.empty() )
 
  549        result.push_back( current );
 
 
  557    std::unique_lock<std::mutex> lock;
 
  560        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
 
  568    std::unique_lock<std::mutex> lock;
 
  571        lock = std::unique_lock<std::mutex>( 
m_mutex );
 
 
void updateBaseNext(PREFIX_DATA &aData) const
 
std::string escapeForSerialization(const std::string &aStr) const
Escape special characters for serialization.
 
bool insertNumber(const std::string &aPrefix, int aNumber)
Insert a number for a specific prefix, updating internal structures.
 
void ClearUnitsChecker()
Clear the external units checker, reverting to default behavior.
 
bool Deserialize(const std::string &aData)
Deserialize tracker data from string representation.
 
std::vector< std::string > splitString(const std::string &aStr, char aDelimiter) const
Split string by delimiter, handling escaped characters.
 
bool m_reuseRefDes
If true, allows reusing existing reference designators.
 
std::mutex m_mutex
Mutex for thread safety.
 
int GetNextRefDesForUnits(const SCH_REFERENCE &aRef, const std::map< int, std::vector< SCH_REFERENCE > > &aRefNumberMap, const std::vector< int > &aRequiredUnits, int aMinValue)
Get the next available reference designator number for multi-unit symbols.
 
std::unordered_set< std::string > m_allRefDes
 
bool Insert(const std::string &aRefDes)
Insert a reference designator into the tracker.
 
void clearImpl()
Clear all internal data structures without locking.
 
size_t Size() const
Get the total count of stored reference designators.
 
std::string unescapeFromSerialization(const std::string &aStr) const
Unescape special characters from serialization.
 
bool insertImpl(const std::string &aRefDes)
Internal implementation of Insert without locking.
 
int findNextAvailable(const PREFIX_DATA &aData, int aMinValue) const
Find next available number for a prefix starting from a minimum value.
 
REFDES_TRACKER(bool aThreadSafe=false)
Constructor.
 
bool areUnitsAvailable(const SCH_REFERENCE &aRef, const std::vector< SCH_REFERENCE > &aRefVector, const std::vector< int > &aRequiredUnits) const
Check if all required units are available for a given reference number.
 
void SetUnitsChecker(const UNITS_CHECKER_FUNC< SCH_REFERENCE > &aChecker)
Set an external units checker function for SCH_REFERENCE objects.
 
void updateCacheOnInsert(PREFIX_DATA &aData, int aInsertedNumber) const
Update cached next available values when a number is inserted.
 
std::string Serialize() const
Serialize the tracker data to a compact string representation.
 
std::unordered_map< std::string, PREFIX_DATA > m_prefixData
Map from prefix to its tracking data.
 
bool m_threadSafe
True if thread safety is enabled.
 
bool Contains(const std::string &aRefDes) const
Check if a reference designator exists in the tracker.
 
std::pair< std::string, int > parseRefDes(const std::string &aRefDes) const
Parse a reference designator into prefix and numerical suffix.
 
bool containsImpl(const std::string &aRefDes) const
Check if a reference designator exists in the tracker without locking.
 
UNITS_CHECKER_FUNC< SCH_REFERENCE > m_externalUnitsChecker
External units checker function (optional)
 
void Clear()
Clear all stored reference designators.
 
A helper to define a symbol's reference designator in a schematic.
 
const char * GetRefStr() const
 
std::function< bool(const T &aTestRef, const std::vector< T > &aExistingRefs, const std::vector< int > &aRequiredUnits)> UNITS_CHECKER_FUNC
Function type for external units availability checking.
 
Data structure for tracking used numbers and caching next available values.
 
std::set< int > m_usedNumbers
Sorted set of used numbers for this prefix.
 
bool m_cacheValid
True if m_baseNext cache is valid.
 
int m_baseNext
Next available from 1 (cached)
 
std::map< int, int > m_nextCache
Cache of next available number for given min values.
 
wxString result
Test unit parsing edge cases and error handling.