You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
5.0 KiB

3 years ago
3 years ago
3 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015 Simon Richter
  5. * Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.TXT for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include "pin_numbers.h"
  25. #include <wx/crt.h>
  26. #include <wx/translation.h>
  27. wxString PIN_NUMBERS::getNextSymbol( const wxString& str, wxString::size_type& cursor )
  28. {
  29. if( str.size() <= cursor )
  30. return wxEmptyString;
  31. wxString::size_type begin = cursor;
  32. wxChar c = str[cursor];
  33. // Need to check that there is a digit in the string before we parse it as a numeric
  34. if( ( wxIsdigit( c ) || ( ( c == '+' || c == '-' ) && ( cursor < str.size() - 1 ) && wxIsdigit( str[cursor + 1] ) ) ) )
  35. {
  36. // number, possibly with sign
  37. while( ++cursor < str.size() )
  38. {
  39. c = str[cursor];
  40. if( wxIsdigit( c ) || c == 'v' || c == 'V' || c == '.' )
  41. continue;
  42. else
  43. break;
  44. }
  45. }
  46. else
  47. {
  48. while( ++cursor < str.size() )
  49. {
  50. c = str[cursor];
  51. if( wxIsdigit( c ) )
  52. break;
  53. else
  54. continue;
  55. }
  56. }
  57. return str.substr( begin, cursor - begin );
  58. }
  59. wxString PIN_NUMBERS::GetSummary() const
  60. {
  61. wxString ret;
  62. const_iterator i = begin();
  63. if( i == end() )
  64. return ret;
  65. const_iterator begin_of_range = i;
  66. const_iterator last;
  67. for( ;; )
  68. {
  69. last = i;
  70. ++i;
  71. int rc = ( i != end() ) ? Compare( *last, *i ) : -2;
  72. assert( rc == -1 || rc == -2 );
  73. if( rc == -1 )
  74. // adjacent elements
  75. continue;
  76. ret += *begin_of_range;
  77. if( begin_of_range != last )
  78. {
  79. ret += '-';
  80. ret += *last;
  81. }
  82. if( i == end() )
  83. break;
  84. begin_of_range = i;
  85. ret += ',';
  86. }
  87. return ret;
  88. }
  89. wxString PIN_NUMBERS::GetDuplicates() const
  90. {
  91. wxString ret;
  92. for( const wxString& pinNumber : duplicate_pins )
  93. {
  94. ret += pinNumber;
  95. ret += ',';
  96. }
  97. // Remove the trailing comma
  98. ret.RemoveLast();
  99. if( ret.IsEmpty() )
  100. ret = _( "none" );
  101. return ret;
  102. }
  103. int PIN_NUMBERS::Compare( const wxString& lhs, const wxString& rhs )
  104. {
  105. wxString::size_type cursor1 = 0;
  106. wxString::size_type cursor2 = 0;
  107. wxString symbol1, symbol2;
  108. for( ; ; )
  109. {
  110. symbol1 = getNextSymbol( lhs, cursor1 );
  111. symbol2 = getNextSymbol( rhs, cursor2 );
  112. if( symbol1.empty() && symbol2.empty() )
  113. return 0;
  114. if( symbol1.empty() )
  115. return -2;
  116. if( symbol2.empty() )
  117. return 2;
  118. bool sym1_isnumeric = symbol1.find_first_of( wxS( "0123456789" ) ) != wxString::npos;
  119. bool sym2_isnumeric = symbol2.find_first_of( wxS( "0123456789" ) ) != wxString::npos;
  120. if( sym1_isnumeric )
  121. {
  122. if( sym2_isnumeric )
  123. {
  124. // numeric comparison
  125. wxString::size_type v1 = symbol1.find_first_of( wxS( "vV" ) );
  126. if( v1 != wxString::npos )
  127. symbol1[v1] = '.';
  128. wxString::size_type v2 = symbol2.find_first_of( wxS( "vV" ) );
  129. if( v2 != wxString::npos )
  130. symbol2[v2] = '.';
  131. double val1, val2;
  132. symbol1.ToCDouble( &val1 );
  133. symbol2.ToCDouble( &val2 );
  134. if( val1 < val2 )
  135. {
  136. if( val1 == val2 - 1 )
  137. return -1;
  138. else
  139. return -2;
  140. }
  141. if( val1 > val2 )
  142. {
  143. if( val1 == val2 + 1 )
  144. return 1;
  145. else
  146. return 2;
  147. }
  148. }
  149. else
  150. return -2;
  151. }
  152. else
  153. {
  154. if( sym2_isnumeric )
  155. return 2;
  156. int res = symbol1.Cmp( symbol2 );
  157. if( res != 0 )
  158. return res;
  159. }
  160. }
  161. }