KiCad PCB EDA Suite
string.cpp File Reference

Some useful functions to handle strings. More...

#include <clocale>
#include <cmath>
#include <macros.h>
#include <richio.h>
#include <kicad_string.h>

Go to the source code of this file.

Functions

wxString ConvertToNewOverbarNotation (const wxString &aOldStr)
 Convert the old ~...~ overbar notation to the new ~{...} one. More...
 
bool ConvertSmartQuotesAndDashes (wxString *aString)
 Convert curly quotes and em/en dashes to straight quotes and dashes. More...
 
wxString EscapeString (const wxString &aSource, ESCAPE_CONTEXT aContext)
 The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are: (a) not legal in filenames (b) used as control characters in LIB_IDs (c) used to delineate hierarchical paths. More...
 
wxString UnescapeString (const wxString &aSource)
 
wxString TitleCaps (const wxString &aString)
 Capitalize the first letter in each word. More...
 
int ReadDelimitedText (wxString *aDest, const char *aSource)
 Copy bytes from aSource delimited string segment to aDest wxString. More...
 
int ReadDelimitedText (char *aDest, const char *aSource, int aDestSize)
 Copy bytes from aSource delimited string segment to aDest buffer. More...
 
std::string EscapedUTF8 (const wxString &aString)
 Return an 8 bit UTF8 string given aString in Unicode form. More...
 
wxString EscapeHTML (const wxString &aString)
 Return a new wxString escaped for embedding in HTML. More...
 
bool NoPrintableChars (const wxString &aString)
 Return true if the string is empty or contains only whitespace. More...
 
char * StrPurge (char *text)
 Remove leading and training spaces, tabs and end of line chars in text. More...
 
char * GetLine (FILE *File, char *Line, int *LineNum, int SizeLine)
 Read one line line from aFile. More...
 
wxString DateAndTime ()
 
int StrNumCmp (const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
 Compare two strings with alphanumerical content. More...
 
bool WildCompareString (const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
 Compare a string against wild card (* and ?) pattern using the usual rules. More...
 
bool ApplyModifier (double &value, const wxString &aString)
 
int ValueStringCompare (wxString strFWord, wxString strSWord)
 Compare strings like the strcmp function but handle numbers and modifiers within the string text correctly for sorting. More...
 
int SplitString (const wxString &strToSplit, wxString *strBeginning, wxString *strDigits, wxString *strEnd)
 Break a string into three parts: he alphabetic preamble, the numeric part, and any alphabetic ending. More...
 
int GetTrailingInt (const wxString &aStr)
 Gets the trailing int, if any, from a string. More...
 
wxString GetIllegalFileNameWxChars ()
 
bool ReplaceIllegalFileNameChars (std::string *aName, int aReplaceChar)
 Checks aName for illegal file name characters. More...
 
bool ReplaceIllegalFileNameChars (wxString &aName, int aReplaceChar)
 
void wxStringSplit (const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
 Split aString to a string list separated at aSplitter. More...
 
void StripTrailingZeros (wxString &aStringValue, unsigned aTrailingZeroAllowed)
 Remove trailing zeros from a string containing a converted float number. More...
 
std::string Double2Str (double aValue)
 Print a float number without using scientific notation and no trailing 0 We want to avoid scientific notation in S-expr files (not easy to read) for floating numbers. More...
 
wxString AngleToStringDegrees (double aAngle)
 A helper to convert the double aAngle (in internal unit) to a string in degrees. More...
 

Variables

static const char illegalFileNameChars [] = "\\/:\"<>|"
 Illegal file name characters used to ensure file names will be valid on all supported platforms. More...
 

Detailed Description

Some useful functions to handle strings.

Definition in file string.cpp.

Function Documentation

◆ AngleToStringDegrees()

wxString AngleToStringDegrees ( double  aAngle)

A helper to convert the double aAngle (in internal unit) to a string in degrees.

Definition at line 970 of file string.cpp.

971 {
972  wxString text;
973 
974  text.Printf( wxT( "%.3f" ), aAngle / 10.0 );
975  StripTrailingZeros( text, 1 );
976 
977  return text;
978 }
void StripTrailingZeros(wxString &aStringValue, unsigned aTrailingZeroAllowed)
Remove trailing zeros from a string containing a converted float number.
Definition: string.cpp:918

References StripTrailingZeros(), and text.

Referenced by PANEL_EDIT_OPTIONS::TransferDataToWindow().

◆ ApplyModifier()

bool ApplyModifier ( double &  value,
const wxString &  aString 
)

Definition at line 647 of file string.cpp.

648 {
649  static const wxString modifiers( wxT( "pnumkKM" ) );
650 
651  if( !aString.length() )
652  return false;
653 
654  wxChar modifier;
655  wxString units;
656 
657  if( modifiers.Find( aString[ 0 ] ) >= 0 )
658  {
659  modifier = aString[ 0 ];
660  units = aString.Mid( 1 ).Trim();
661  }
662  else
663  {
664  modifier = ' ';
665  units = aString.Mid( 0 ).Trim();
666  }
667 
668  if( units.length()
669  && !units.CmpNoCase( wxT( "F" ) )
670  && !units.CmpNoCase( wxT( "hz" ) )
671  && !units.CmpNoCase( wxT( "W" ) )
672  && !units.CmpNoCase( wxT( "V" ) )
673  && !units.CmpNoCase( wxT( "H" ) ) )
674  return false;
675 
676  if( modifier == 'p' )
677  value *= 1.0e-12;
678  if( modifier == 'n' )
679  value *= 1.0e-9;
680  else if( modifier == 'u' )
681  value *= 1.0e-6;
682  else if( modifier == 'm' )
683  value *= 1.0e-3;
684  else if( modifier == 'k' || modifier == 'K' )
685  value *= 1.0e3;
686  else if( modifier == 'M' )
687  value *= 1.0e6;
688  else if( modifier == 'G' )
689  value *= 1.0e9;
690 
691  return true;
692 }

Referenced by ValueStringCompare().

◆ ConvertSmartQuotesAndDashes()

bool ConvertSmartQuotesAndDashes ( wxString *  aString)

Convert curly quotes and em/en dashes to straight quotes and dashes.

Returns
true if any characters required conversion.

Definition at line 114 of file string.cpp.

115 {
116  bool retVal = false;
117 
118  for( wxString::iterator ii = aString->begin(); ii != aString->end(); ++ii )
119  {
120  if( *ii == L'\u00B4' || *ii == L'\u2018' || *ii == L'\u2019' )
121  {
122  *ii = '\'';
123  retVal = true;
124  }
125  if( *ii == L'\u201C' || *ii == L'\u201D' )
126  {
127  *ii = '"';
128  retVal = true;
129  }
130  if( *ii == L'\u2013' || *ii == L'\u2014' )
131  {
132  *ii = '-';
133  retVal = true;
134  }
135  }
136 
137  return retVal;
138 }

Referenced by WX_HTML_REPORT_PANEL::onBtnSaveToFile(), SCINTILLA_TRICKS::onCharHook(), and PANEL_SETUP_RULES::TransferDataToWindow().

◆ ConvertToNewOverbarNotation()

wxString ConvertToNewOverbarNotation ( const wxString &  aOldStr)

Convert the old ~...~ overbar notation to the new ~{...} one.

Definition at line 44 of file string.cpp.

45 {
46  wxString newStr;
47  bool inOverbar = false;
48 
49  // Don't get tripped up by the legacy empty-string token.
50  if( aOldStr == "~" )
51  return aOldStr;
52 
53  for( wxString::const_iterator chIt = aOldStr.begin(); chIt != aOldStr.end(); ++chIt )
54  {
55  if( *chIt == '~' )
56  {
57  wxString::const_iterator lookahead = chIt + 1;
58 
59  if( lookahead != aOldStr.end() && *lookahead == '~' )
60  {
61  if( ++lookahead != aOldStr.end() && *lookahead == '{' )
62  {
63  // This way the subseqent opening curly brace will not start an
64  // overbar.
65  newStr << "~~{}";
66  continue;
67  }
68 
69  // Two subsequent tildes mean a tilde.
70  newStr << "~";
71  ++chIt;
72  continue;
73  }
74  else if( lookahead != aOldStr.end() && *lookahead == '{' )
75  {
76  // Could mean the user wants "{" with an overbar, but more likely this
77  // is a case of double notation conversion. Bail out.
78  return aOldStr;
79  }
80  else
81  {
82  if( inOverbar )
83  {
84  newStr << "}";
85  inOverbar = false;
86  }
87  else
88  {
89  newStr << "~{";
90  inOverbar = true;
91  }
92 
93  continue;
94  }
95  }
96  else if( ( *chIt == ' ' || *chIt == '}' || *chIt == ')' ) && inOverbar )
97  {
98  // Spaces were used to terminate overbar as well
99  newStr << "}";
100  inOverbar = false;
101  }
102 
103  newStr << *chIt;
104  }
105 
106  // Explicitly end the overbar even if there was no terminating '~' in the aOldStr.
107  if( inOverbar )
108  newStr << "}";
109 
110  return newStr;
111 }

Referenced by LEGACY_PLUGIN::loadMODULE_TEXT(), LEGACY_PLUGIN::loadNETCLASS(), LEGACY_PLUGIN::loadNETINFO_ITEM(), LEGACY_PLUGIN::loadPAD(), LEGACY_PLUGIN::loadPCB_TEXT(), NET_SETTINGS::migrateSchema0to1(), SCH_SEXPR_PARSER::parseBusAlias(), SCH_SEXPR_PARSER::parseEDA_TEXT(), PCB_PARSER::parseEDA_TEXT(), PCB_PARSER::parseNETCLASS(), PCB_PARSER::parseNETINFO_ITEM(), PCB_PARSER::parsePAD(), SCH_SEXPR_PARSER::parsePin(), and DRAWING_SHEET_READER_PARSER::parseText().

◆ DateAndTime()

wxString DateAndTime ( )
Returns
a string giving the current date and time.

Definition at line 498 of file string.cpp.

499 {
500  wxDateTime datetime = wxDateTime::Now();
501 
502  datetime.SetCountry( wxDateTime::Country_Default );
503  return datetime.Format( wxDefaultDateTimeFormat, wxDateTime::Local );
504 }

Referenced by GENDRILL_WRITER_BASE::GenDrillReportFile(), PLACE_FILE_EXPORTER::GenPositionData(), PLACE_FILE_EXPORTER::GenReportData(), NETLIST_EXPORTER_XML::makeDesignHeader(), RecreateCmpFile(), EXCELLON_WRITER::writeEXCELLONHeader(), PCB_CALCULATOR_DATAFILE::WriteHeader(), NETLIST_EXPORTER_ORCADPCB2::WriteNetlist(), NETLIST_EXPORTER_CADSTAR::WriteNetlist(), and DIALOG_ERC::writeReport().

◆ Double2Str()

std::string Double2Str ( double  aValue)

Print a float number without using scientific notation and no trailing 0 We want to avoid scientific notation in S-expr files (not easy to read) for floating numbers.

We cannot always just use the g or the f format to print a fp number this helper function uses the f format when needed, or g when f is not well working and then removes trailing 0

Definition at line 940 of file string.cpp.

941 {
942  char buf[50];
943  int len;
944 
945  if( aValue != 0.0 && std::fabs( aValue ) <= 0.0001 )
946  {
947  // For these small values, %f works fine,
948  // and %g gives an exponent
949  len = sprintf( buf, "%.16f", aValue );
950 
951  while( --len > 0 && buf[len] == '0' )
952  buf[len] = '\0';
953 
954  if( buf[len] == '.' )
955  buf[len] = '\0';
956  else
957  ++len;
958  }
959  else
960  {
961  // For these values, %g works fine, and sometimes %f
962  // gives a bad value (try aValue = 1.222222222222, with %.16f format!)
963  len = sprintf( buf, "%.10g", aValue );
964  }
965 
966  return std::string( buf, len );
967 }

Referenced by GBR_TO_PCB_EXPORTER::export_non_copper_item(), GBR_TO_PCB_EXPORTER::export_via(), PCB_IO::format(), BOARD_STACKUP::FormatBoardStackup(), PCB_IO::formatSetup(), formatStroke(), NUMERIC_EVALUATOR::parseSetResult(), SCH_SEXPR_PLUGIN::saveJunction(), GBR_TO_PCB_EXPORTER::writeCopperLineItem(), GBR_TO_PCB_EXPORTER::writePcbFilledCircle(), GBR_TO_PCB_EXPORTER::writePcbPolygon(), and GBR_TO_PCB_EXPORTER::writePcbZoneItem().

◆ EscapedUTF8()

std::string EscapedUTF8 ( const wxString &  aString)

Return an 8 bit UTF8 string given aString in Unicode form.

Any double quoted or back slashes are prefixed with a '\' byte and the form of this UTF8 byte string is compatible with function ReadDelimitedText().

Parameters
aStringis the input string to convert.
Returns
the escaped input text, without the wrapping double quotes.

Definition at line 392 of file string.cpp.

393 {
394  wxString str = aString;
395 
396  // No new-lines allowed in quoted strings
397  str.Replace( "\r\n", "\r" );
398  str.Replace( "\n", "\r" );
399 
400  std::string utf8 = TO_UTF8( aString );
401 
402  std::string ret;
403 
404  ret += '"';
405 
406  for( std::string::const_iterator it = utf8.begin(); it!=utf8.end(); ++it )
407  {
408  // this escaping strategy is designed to be compatible with ReadDelimitedText():
409  if( *it == '"' )
410  {
411  ret += '\\';
412  ret += '"';
413  }
414  else if( *it == '\\' )
415  {
416  ret += '\\'; // double it up
417  ret += '\\';
418  }
419  else
420  {
421  ret += *it;
422  }
423  }
424 
425  ret += '"';
426 
427  return ret;
428 }
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96

References TO_UTF8.

Referenced by SCH_LEGACY_PLUGIN::Format(), PLACE_FILE_EXPORTER::GenReportData(), SCH_LEGACY_PLUGIN::saveField(), SCH_LEGACY_PLUGIN_CACHE::saveField(), SCH_SEXPR_PLUGIN::saveSheet(), and SCH_LEGACY_PLUGIN::saveSheet().

◆ EscapeHTML()

wxString EscapeHTML ( const wxString &  aString)

Return a new wxString escaped for embedding in HTML.

Definition at line 431 of file string.cpp.

432 {
433  wxString converted;
434 
435  for( wxUniChar c: aString )
436  {
437  if( c == '\"' )
438  converted += "&quot;";
439  else if( c == '\'' )
440  converted += "&apos;";
441  else if( c == '&' )
442  converted += "&amp;";
443  else if( c == '<' )
444  converted += "&lt;";
445  else if( c == '>' )
446  converted += "&gt;";
447  else
448  converted += c;
449  }
450 
451  return converted;
452 }

Referenced by DRC_ENGINE::EvalRules(), FOOTPRINT_INFO_GENERATOR::GenerateHtml(), FOOTPRINT_INFO_GENERATOR::GetHtmlFieldRow(), BOARD_INSPECTION_TOOL::InspectClearance(), BOARD_INSPECTION_TOOL::InspectConstraints(), BOARD_INSPECTION_TOOL::InspectDRCError(), FOOTPRINT_INFO_GENERATOR::SetHtmlAliasOf(), FOOTPRINT_INFO_GENERATOR::SetHtmlDesc(), FOOTPRINT_INFO_GENERATOR::SetHtmlKeywords(), and FOOTPRINT_INFO_GENERATOR::SetHtmlName().

◆ EscapeString()

wxString EscapeString ( const wxString &  aSource,
ESCAPE_CONTEXT  aContext 
)

The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are: (a) not legal in filenames (b) used as control characters in LIB_IDs (c) used to delineate hierarchical paths.

Definition at line 141 of file string.cpp.

142 {
143  wxString converted;
144 
145  for( wxUniChar c: aSource )
146  {
147  if( aContext == CTX_NETNAME )
148  {
149  if( c == '/' )
150  converted += "{slash}";
151  else if( c == '\n' || c == '\r' )
152  converted += ""; // drop
153  else
154  converted += c;
155  }
156  else if( aContext == CTX_LIBID )
157  {
158  if( c == '{' )
159  converted += "{brace}";
160  else if( c == ':' )
161  converted += "{colon}";
162  else if( c == '\n' || c == '\r' )
163  converted += ""; // drop
164  else
165  converted += c;
166  }
167  else if( aContext == CTX_QUOTED_STR )
168  {
169  if( c == '\"' )
170  converted += "{dblquote}";
171  else
172  converted += c;
173  }
174  else if( aContext == CTX_LINE )
175  {
176  if( c == '\n' || c == '\r' )
177  converted += "{return}";
178  else
179  converted += c;
180  }
181  else if( aContext == CTX_FILENAME )
182  {
183  if( c == '{' )
184  converted += "{brace}";
185  else if( c == '/' )
186  converted += "{slash}";
187  else if( c == '\\' )
188  converted += "{backslash}";
189  else if( c == '\"' )
190  converted += "{dblquote}";
191  else if( c == '<' )
192  converted += "{lt}";
193  else if( c == '>' )
194  converted += "{gt}";
195  else if( c == '|' )
196  converted += "{bar}";
197  else if( c == ':' )
198  converted += "{colon}";
199  else if( c == '\t' )
200  converted += "{tab}";
201  else if( c == '\n' || c == '\r' )
202  converted += "{return}";
203  else
204  converted += c;
205  }
206  else
207  converted += c;
208  }
209 
210  return converted;
211 }

References CTX_FILENAME, CTX_LIBID, CTX_LINE, CTX_NETNAME, and CTX_QUOTED_STR.

Referenced by SCH_EDIT_TOOL::ChangeTextType(), CONNECTION_SUBGRAPH::driverName(), CONNECTION_GRAPH::ercCheckBusToNetConflicts(), CONNECTION_GRAPH::ercCheckLabels(), DIALOG_NET_INSPECTOR::onRenameNet(), NET_SETTINGS::ParseBusGroup(), DIALOG_SHEET_PIN_PROPERTIES::TransferDataFromWindow(), DIALOG_LABEL_EDITOR::TransferDataFromWindow(), DIALOG_TEXT_PROPERTIES::TransferDataFromWindow(), and FOOTPRINT_LIST_IMPL::WriteCacheToFile().

◆ GetIllegalFileNameWxChars()

wxString GetIllegalFileNameWxChars ( )
Returns
a wxString object containing the illegal file name characters for all platforms.

Definition at line 828 of file string.cpp.

829 {
831 }
static const char illegalFileNameChars[]
Illegal file name characters used to ensure file names will be valid on all supported platforms.
Definition: string.cpp:41
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110

References FROM_UTF8(), and illegalFileNameChars.

Referenced by ReplaceIllegalFileNameChars().

◆ GetLine()

char* GetLine ( FILE *  aFile,
char *  Line,
int *  LineNum = nullptr,
int  SizeLine = 255 
)

Read one line line from aFile.

Returns
a pointer the first useful line read by eliminating blank lines and comments.

Definition at line 482 of file string.cpp.

483 {
484  do {
485  if( fgets( Line, SizeLine, File ) == NULL )
486  return NULL;
487 
488  if( LineNum )
489  *LineNum += 1;
490 
491  } while( Line[0] == '#' || Line[0] == '\n' || Line[0] == '\r' || Line[0] == 0 );
492 
493  strtok( Line, "\n\r" );
494  return Line;
495 }
#define NULL

References NULL.

Referenced by CVPCB_MAINFRAME::buildEquivalenceList().

◆ GetTrailingInt()

int GetTrailingInt ( const wxString &  aStr)

Gets the trailing int, if any, from a string.

Parameters
aStrthe string to check.
Returns
the trailing int or 0 if none found.

Definition at line 804 of file string.cpp.

805 {
806  int number = 0;
807  int base = 1;
808 
809  // Trim and extract the trailing numeric part
810  int index = aStr.Len() - 1;
811 
812  while( index >= 0 )
813  {
814  const char chr = aStr.GetChar( index );
815 
816  if( chr < '0' || chr > '9' )
817  break;
818 
819  number += ( chr - '0' ) * base;
820  base *= 10;
821  index--;
822  }
823 
824  return number;
825 }

Referenced by BOOST_AUTO_TEST_CASE(), FOOTPRINT::GetNextPadName(), and FOOTPRINT::IncrementReference().

◆ NoPrintableChars()

bool NoPrintableChars ( const wxString &  aString)

Return true if the string is empty or contains only whitespace.

Definition at line 455 of file string.cpp.

456 {
457  wxString tmp = aString;
458 
459  return tmp.Trim( true ).Trim( false ).IsEmpty();
460 }

Referenced by SCH_DRAWING_TOOLS::createNewText(), SCH_DRAWING_TOOLS::createSheetPin(), DRAWING_TOOL::PlaceText(), and SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace().

◆ ReadDelimitedText() [1/2]

int ReadDelimitedText ( wxString *  aDest,
const char *  aSource 
)

Copy bytes from aSource delimited string segment to aDest wxString.

Parameters
aDestis the destination wxString.
aSourceis the source C string holding utf8 encoded bytes.
Returns
the number of bytes read from source, which may be more than the number copied, due to escaping of double quotes and the escape byte itself.

Definition at line 298 of file string.cpp.

299 {
300  std::string utf8; // utf8 but without escapes and quotes.
301  bool inside = false;
302  const char* start = aSource;
303  char cc;
304 
305  while( (cc = *aSource++) != 0 )
306  {
307  if( cc == '"' )
308  {
309  if( inside )
310  break; // 2nd double quote is end of delimited text
311 
312  inside = true; // first delimiter found, make note, do not copy
313  }
314 
315  else if( inside )
316  {
317  if( cc == '\\' )
318  {
319  cc = *aSource++;
320 
321  if( !cc )
322  break;
323 
324  // do no copy the escape byte if it is followed by \ or "
325  if( cc != '"' && cc != '\\' )
326  utf8 += '\\';
327 
328  utf8 += cc;
329  }
330  else
331  {
332  utf8 += cc;
333  }
334  }
335  }
336 
337  *aDest = FROM_UTF8( utf8.c_str() );
338 
339  return aSource - start;
340 }
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110

References FROM_UTF8().

Referenced by LEGACY_PLUGIN::load3D(), LEGACY_PLUGIN::loadDIMENSION(), LEGACY_PLUGIN::loadMODULE_TEXT(), LEGACY_PLUGIN::loadNETCLASS(), LEGACY_PLUGIN::loadNETINFO_ITEM(), LEGACY_PLUGIN::loadPAD(), LEGACY_PLUGIN::loadPCB_TEXT(), LEGACY_PLUGIN::loadSHEET(), and LEGACY_PLUGIN::loadZONE_CONTAINER().

◆ ReadDelimitedText() [2/2]

int ReadDelimitedText ( char *  aDest,
const char *  aSource,
int  aDestSize 
)

Copy bytes from aSource delimited string segment to aDest buffer.

The extracted string will be null terminated even if truncation is necessary because aDestSize was not large enough.

Parameters
aDestis the destination byte buffer.
aSourceis the source bytes as a C string.
aDestSizeis the size of the destination byte buffer.
Returns
the number of bytes read from source, which may be more than the number copied, due to escaping of double quotes and the escape byte itself.
Deprecated:
should use the one which fetches a wxString, below.

Definition at line 343 of file string.cpp.

344 {
345  if( aDestSize <= 0 )
346  return 0;
347 
348  bool inside = false;
349  const char* start = aSource;
350  char* limit = aDest + aDestSize - 1;
351  char cc;
352 
353  while( (cc = *aSource++) != 0 && aDest < limit )
354  {
355  if( cc == '"' )
356  {
357  if( inside )
358  break; // 2nd double quote is end of delimited text
359 
360  inside = true; // first delimiter found, make note, do not copy
361  }
362 
363  else if( inside )
364  {
365  if( cc == '\\' )
366  {
367  cc = *aSource++;
368 
369  if( !cc )
370  break;
371 
372  // do no copy the escape byte if it is followed by \ or "
373  if( cc != '"' && cc != '\\' )
374  *aDest++ = '\\';
375 
376  if( aDest < limit )
377  *aDest++ = cc;
378  }
379  else
380  {
381  *aDest++ = cc;
382  }
383  }
384  }
385 
386  *aDest = 0;
387 
388  return aSource - start;
389 }

◆ ReplaceIllegalFileNameChars() [1/2]

bool ReplaceIllegalFileNameChars ( std::string *  aName,
int  aReplaceChar = 0 
)

Checks aName for illegal file name characters.

The Windows (DOS) file system forbidden characters already include the forbidden file name characters for both Posix and OSX systems. The characters \/?*|"<> are illegal and are replaced with xx where xx the hexadecimal equivalent of the replaced character. This replacement may not be as elegant as using an underscore ('_') or hyphen ('-') but it guarantees that there will be no naming conflicts when fixing footprint library names. however, if aReplaceChar is given, it will replace the illegal chars

Parameters
aNameis a point to a std::string object containing the footprint name to verify.
aReplaceChar(if not 0) is the replacement char.
Returns
true if any characters have been replaced in aName.

Definition at line 834 of file string.cpp.

835 {
836  bool changed = false;
837  std::string result;
838  result.reserve( aName->length() );
839 
840  for( std::string::iterator it = aName->begin(); it != aName->end(); ++it )
841  {
842  if( strchr( illegalFileNameChars, *it ) )
843  {
844  if( aReplaceChar )
845  StrPrintf( &result, "%c", aReplaceChar );
846  else
847  StrPrintf( &result, "%%%02x", *it );
848 
849  changed = true;
850  }
851  else
852  {
853  result += *it;
854  }
855  }
856 
857  if( changed )
858  *aName = result;
859 
860  return changed;
861 }
static const char illegalFileNameChars[]
Illegal file name characters used to ensure file names will be valid on all supported platforms.
Definition: string.cpp:41
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
Definition: richio.cpp:78

References illegalFileNameChars, and StrPrintf().

Referenced by AltiumToKiCadLibID(), EDEVICE::EDEVICE(), EELEMENT::EELEMENT(), LEGACY_PLUGIN::loadAllSections(), FABMASTER::loadFootprints(), EAGLE_PLUGIN::loadLibrary(), LP_CACHE::LoadModules(), SCH_EAGLE_PLUGIN::loadSheet(), CADSTAR_SCH_ARCHIVE_LOADER::loadSheetAndChildSheets(), and CADSTAR_SCH_ARCHIVE_LOADER::loadSheets().

◆ ReplaceIllegalFileNameChars() [2/2]

bool ReplaceIllegalFileNameChars ( wxString &  aName,
int  aReplaceChar 
)

Definition at line 864 of file string.cpp.

865 {
866  bool changed = false;
867  wxString result;
868  result.reserve( aName.Length() );
869  wxString illWChars = GetIllegalFileNameWxChars();
870 
871  for( wxString::iterator it = aName.begin(); it != aName.end(); ++it )
872  {
873  if( illWChars.Find( *it ) != wxNOT_FOUND )
874  {
875  if( aReplaceChar )
876  result += aReplaceChar;
877  else
878  result += wxString::Format( "%%%02x", *it );
879 
880  changed = true;
881  }
882  else
883  {
884  result += *it;
885  }
886  }
887 
888  if( changed )
889  aName = result;
890 
891  return changed;
892 }
wxString GetIllegalFileNameWxChars()
Definition: string.cpp:828
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200

References Format(), and GetIllegalFileNameWxChars().

◆ SplitString()

int SplitString ( const wxString &  strToSplit,
wxString *  strBeginning,
wxString *  strDigits,
wxString *  strEnd 
)

Break a string into three parts: he alphabetic preamble, the numeric part, and any alphabetic ending.

For example C10A is split to C 10 A

Definition at line 743 of file string.cpp.

747 {
748  static const wxString separators( wxT( ".," ) );
749 
750  // Clear all the return strings
751  strBeginning->Empty();
752  strDigits->Empty();
753  strEnd->Empty();
754 
755  // There no need to do anything if the string is empty
756  if( strToSplit.length() == 0 )
757  return 0;
758 
759  // Starting at the end of the string look for the first digit
760  int ii;
761 
762  for( ii = (strToSplit.length() - 1); ii >= 0; ii-- )
763  {
764  if( wxIsdigit( strToSplit[ii] ) )
765  break;
766  }
767 
768  // If there were no digits then just set the single string
769  if( ii < 0 )
770  {
771  *strBeginning = strToSplit;
772  }
773  else
774  {
775  // Since there is at least one digit this is the trailing string
776  *strEnd = strToSplit.substr( ii + 1 );
777 
778  // Go to the end of the digits
779  int position = ii + 1;
780 
781  for( ; ii >= 0; ii-- )
782  {
783  if( !wxIsdigit( strToSplit[ii] ) && separators.Find( strToSplit[ii] ) < 0 )
784  break;
785  }
786 
787  // If all that was left was digits, then just set the digits string
788  if( ii < 0 )
789  *strDigits = strToSplit.substr( 0, position );
790 
791  /* We were only looking for the last set of digits everything else is
792  * part of the preamble */
793  else
794  {
795  *strDigits = strToSplit.substr( ii + 1, position - ii - 1 );
796  *strBeginning = strToSplit.substr( 0, ii + 1 );
797  }
798  }
799 
800  return 0;
801 }

Referenced by UTIL::RefDesStringCompare(), and ValueStringCompare().

◆ StripTrailingZeros()

void StripTrailingZeros ( wxString &  aStringValue,
unsigned  aTrailingZeroAllowed = 1 
)

Remove trailing zeros from a string containing a converted float number.

The trailing zeros are removed if the mantissa has more than aTrailingZeroAllowed digits and some trailing zeros.

Definition at line 918 of file string.cpp.

919 {
920  struct lconv* lc = localeconv();
921  char sep = lc->decimal_point[0];
922  unsigned sep_pos = aStringValue.Find( sep );
923 
924  if( sep_pos > 0 )
925  {
926  // We want to keep at least aTrailingZeroAllowed digits after the separator
927  unsigned min_len = sep_pos + aTrailingZeroAllowed + 1;
928 
929  while( aStringValue.Len() > min_len )
930  {
931  if( aStringValue.Last() == '0' )
932  aStringValue.RemoveLast();
933  else
934  break;
935  }
936  }
937 }

Referenced by AngleToStringDegrees().

◆ StrNumCmp()

int StrNumCmp ( const wxString &  aString1,
const wxString &  aString2,
bool  aIgnoreCase = false 
)

Compare two strings with alphanumerical content.

This function is equivalent to strncmp() or strncasecmp() if aIgnoreCase is true except that strings containing numbers are compared by their integer value not by their ASCII code. In other words U10 would be greater than U2.

Parameters
aString1A wxString reference to the reference string.
aString2A wxString reference to the comparison string.
aIgnoreCaseUse true to make the comparison case insensitive.
Returns
An integer value of -1 if aString1 is less than aString2, 0 if aString1 is equal to aString2, or 1 if aString1 is greater than aString2.

Definition at line 507 of file string.cpp.

508 {
509  int nb1 = 0, nb2 = 0;
510 
511  auto str1 = aString1.begin();
512  auto str2 = aString2.begin();
513 
514  while( str1 != aString1.end() && str2 != aString2.end() )
515  {
516  wxUniChar c1 = *str1;
517  wxUniChar c2 = *str2;
518 
519  if( wxIsdigit( c1 ) && wxIsdigit( c2 ) ) // Both characters are digits, do numeric compare.
520  {
521  nb1 = 0;
522  nb2 = 0;
523 
524  do
525  {
526  c1 = *str1;
527  nb1 = nb1 * 10 + (int) c1 - '0';
528  ++str1;
529  } while( str1 != aString1.end() && wxIsdigit( *str1 ) );
530 
531  do
532  {
533  c2 = *str2;
534  nb2 = nb2 * 10 + (int) c2 - '0';
535  ++str2;
536  } while( str2 != aString2.end() && wxIsdigit( *str2 ) );
537 
538  if( nb1 < nb2 )
539  return -1;
540 
541  if( nb1 > nb2 )
542  return 1;
543 
544  c1 = ( str1 != aString1.end() ) ? *str1 : wxUniChar( 0 );
545  c2 = ( str2 != aString2.end() ) ? *str2 : wxUniChar( 0 );
546  }
547 
548  // Any numerical comparisons to here are identical.
549  if( aIgnoreCase )
550  {
551  if( wxToupper( c1 ) < wxToupper( c2 ) )
552  return -1;
553 
554  if( wxToupper( c1 ) > wxToupper( c2 ) )
555  return 1;
556  }
557  else
558  {
559  if( c1 < c2 )
560  return -1;
561 
562  if( c1 > c2 )
563  return 1;
564  }
565 
566  if( str1 != aString1.end() )
567  ++str1;
568 
569  if( str2 != aString2.end() )
570  ++str2;
571  }
572 
573  if( str1 == aString1.end() && str2 != aString2.end() )
574  {
575  return -1; // Identical to here but aString1 is longer.
576  }
577  else if( str1 != aString1.end() && str2 == aString2.end() )
578  {
579  return 1; // Identical to here but aString2 is longer.
580  }
581 
582  return 0;
583 }

Referenced by LIB_TREE_NODE::AssignIntrinsicRanks(), BOOST_AUTO_TEST_CASE(), ChangeArrayCompare(), SCH_PIN_TABLE_DATA_MODEL::compare(), PIN_TABLE_DATA_MODEL::compare(), PLACE_FILE_EXPORTER::GenReportData(), FP_TREE_MODEL_ADAPTER::getFootprints(), NETLIST_EXPORTER_XML::makeListOfNets(), myCompareFunction(), FOOTPRINT::cmp_pads::operator()(), operator<(), sortFPlist(), and FP_TREE_SYNCHRONIZING_ADAPTER::updateLibrary().

◆ StrPurge()

char* StrPurge ( char *  text)

Remove leading and training spaces, tabs and end of line chars in text.

Returns
a pointer on the first n char in text

Definition at line 463 of file string.cpp.

464 {
465  static const char whitespace[] = " \t\n\r\f\v";
466 
467  if( text )
468  {
469  while( *text && strchr( whitespace, *text ) )
470  ++text;
471 
472  char* cp = text + strlen( text ) - 1;
473 
474  while( cp >= text && strchr( whitespace, *cp ) )
475  *cp-- = '\0';
476  }
477 
478  return text;
479 }

References text.

Referenced by detect_file_type(), LEGACY_PLUGIN::loadAllSections(), EXCELLON_IMAGE::LoadFile(), LEGACY_PLUGIN::loadFOOTPRINT(), GERBER_FILE_IMAGE::LoadGerberFile(), LP_CACHE::LoadModules(), LEGACY_NETLIST_READER::LoadNetlist(), and LEGACY_PLUGIN::loadPAD().

◆ TitleCaps()

wxString TitleCaps ( const wxString &  aString)

Capitalize the first letter in each word.

Definition at line 279 of file string.cpp.

280 {
281  wxArrayString words;
282  wxString result;
283 
284  wxStringSplit( aString, words, ' ' );
285 
286  for( const wxString& word : words )
287  {
288  if( !result.IsEmpty() )
289  result += wxT( " " );
290 
291  result += word.Capitalize();
292  }
293 
294  return result;
295 }
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
Definition: string.cpp:895

References wxStringSplit().

Referenced by SYMBOL_EDITOR_EDIT_TOOL::editFieldProperties(), and SCH_EDIT_TOOL::editFieldText().

◆ UnescapeString()

wxString UnescapeString ( const wxString &  aSource)

Definition at line 214 of file string.cpp.

215 {
216  wxString newbuf;
217  size_t sourceLen = aSource.length();
218 
219  for( size_t i = 0; i < sourceLen; ++i )
220  {
221  if( ( aSource[i] == '$' || aSource[i] == '^' || aSource[i] == '_' )
222  && i + 1 < sourceLen && aSource[i+1] == '{' )
223  {
224  for( ; i < sourceLen; ++i )
225  {
226  newbuf += aSource[i];
227 
228  if( aSource[i] == '}' )
229  break;
230  }
231  }
232  else if( aSource[i] == '{' )
233  {
234  wxString token;
235  int depth = 1;
236 
237  for( i = i + 1; i < sourceLen; ++i )
238  {
239  if( aSource[i] == '{' )
240  depth++;
241  else if( aSource[i] == '}' )
242  depth--;
243 
244  if( depth <= 0 )
245  break;
246  else
247  token.append( aSource[i] );
248  }
249 
250  if( token == wxS( "dblquote" ) ) newbuf.append( wxS( "\"" ) );
251  else if( token == wxS( "quote" ) ) newbuf.append( wxS( "'" ) );
252  else if( token == wxS( "lt" ) ) newbuf.append( wxS( "<" ) );
253  else if( token == wxS( "gt" ) ) newbuf.append( wxS( ">" ) );
254  else if( token == wxS( "backslash" ) ) newbuf.append( wxS( "\\" ) );
255  else if( token == wxS( "slash" ) ) newbuf.append( wxS( "/" ) );
256  else if( token == wxS( "bar" ) ) newbuf.append( wxS( "|" ) );
257  else if( token == wxS( "colon" ) ) newbuf.append( wxS( ":" ) );
258  else if( token == wxS( "space" ) ) newbuf.append( wxS( " " ) );
259  else if( token == wxS( "dollar" ) ) newbuf.append( wxS( "$" ) );
260  else if( token == wxS( "tab" ) ) newbuf.append( wxS( "\t" ) );
261  else if( token == wxS( "return" ) ) newbuf.append( wxS( "\n" ) );
262  else if( token == wxS( "brace" ) ) newbuf.append( wxS( "{" ) );
263  else if( token.IsEmpty() ) newbuf.append( wxS( "{" ) );
264  else
265  {
266  newbuf.append( "{" + UnescapeString( token ) + "}" );
267  }
268  }
269  else
270  {
271  newbuf.append( aSource[i] );
272  }
273  }
274 
275  return newbuf;
276 }
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:214

References UnescapeString().

Referenced by NET_SELECTOR_COMBOPOPUP::Accept(), SCH_CONNECTION::AppendInfoToMsgPanel(), EDA_TEXT::cacheShownText(), SCH_EDIT_TOOL::ChangeTextType(), NETLIST_EXPORTER_PSPICE_SIM::ComponentToVector(), SCH_CONNECTION::ConfigureFromLabel(), BOARD_NETLIST_UPDATER::deleteSinglePadNets(), GRID_CELL_ESCAPED_TEXT_RENDERER::Draw(), KIGFX::PCB_PAINTER::draw(), CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts(), CONNECTION_GRAPH::ercCheckHierSheets(), SCH_EDIT_FRAME::ExecuteRemoteCommand(), NETLIST_EXPORTER_PSPICE::Format(), DIALOG_NET_INSPECTOR::formatNetName(), GRID_CELL_ESCAPED_TEXT_RENDERER::GetBestSize(), PCB_TEXT::GetMsgPanelInfo(), ZONE::GetMsgPanelInfo(), NETINFO_ITEM::GetMsgPanelInfo(), FP_TEXT::GetMsgPanelInfo(), GERBER_DRAW_ITEM::GetMsgPanelInfo(), SCH_TEXT::GetMsgPanelInfo(), PAD::GetMsgPanelInfo(), PCB_TRACK::GetMsgPanelInfoBase_Common(), BOARD_CONNECTED_ITEM::GetNetnameMsg(), GERBVIEW_CONTROL::HighlightControl(), SCH_CONNECTION::IsBusLabel(), DIALOG_NET_INSPECTOR::LIST_ITEM::LIST_ITEM(), SCH_CONNECTION::MightBeBusLabel(), DIALOG_NET_INSPECTOR::netFilterMatches(), DIALOG_NET_INSPECTOR::onRenameNet(), FOOTPRINT_LIST_IMPL::ReadCacheFromFile(), NET_SELECTOR_COMBOPOPUP::rebuildList(), UTIL::RefDesStringCompare(), NET_SETTINGS::ResolveNetClassAssignments(), NET_SELECTOR::SetSelectedNet(), NET_SELECTOR::SetSelectedNetcode(), BOARD::SortedNetnamesList(), DIALOG_SIGNAL_LIST::TransferDataToWindow(), DIALOG_SHEET_PIN_PROPERTIES::TransferDataToWindow(), DIALOG_LABEL_EDITOR::TransferDataToWindow(), UnescapeString(), HIGHLIGHT_MENU::update(), BOARD_NETLIST_UPDATER::updateComponentPadConnections(), BOARD_NETLIST_UPDATER::updateCopperZoneNets(), SCH_EDIT_FRAME::UpdateNetHighlightStatus(), GERBVIEW_FRAME::updateNetnameListSelectBox(), and ValueStringCompare().

◆ ValueStringCompare()

int ValueStringCompare ( wxString  strFWord,
wxString  strSWord 
)

Compare strings like the strcmp function but handle numbers and modifiers within the string text correctly for sorting.

eg. 1mF > 55uF

Returns
-1 if first string is less than the second, 0 if the strings are equal, or 1 if the first string is greater than the second.

Definition at line 695 of file string.cpp.

696 {
697  // Compare unescaped text
698  strFWord = UnescapeString( strFWord );
699  strSWord = UnescapeString( strSWord );
700 
701  // The different sections of the two strings
702  wxString strFWordBeg, strFWordMid, strFWordEnd;
703  wxString strSWordBeg, strSWordMid, strSWordEnd;
704 
705  // Split the two strings into separate parts
706  SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd );
707  SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd );
708 
709  // Compare the Beginning section of the strings
710  int isEqual = strFWordBeg.CmpNoCase( strSWordBeg );
711 
712  if( isEqual > 0 )
713  return 1;
714  else if( isEqual < 0 )
715  return -1;
716  else
717  {
718  // If the first sections are equal compare their digits
719  double lFirstNumber = 0;
720  double lSecondNumber = 0;
721  bool endingIsModifier = false;
722 
723  strFWordMid.ToDouble( &lFirstNumber );
724  strSWordMid.ToDouble( &lSecondNumber );
725 
726  endingIsModifier |= ApplyModifier( lFirstNumber, strFWordEnd );
727  endingIsModifier |= ApplyModifier( lSecondNumber, strSWordEnd );
728 
729  if( lFirstNumber > lSecondNumber )
730  return 1;
731  else if( lFirstNumber < lSecondNumber )
732  return -1;
733  // If the first two sections are equal and the endings are modifiers then compare them
734  else if( !endingIsModifier )
735  return strFWordEnd.CmpNoCase( strSWordEnd );
736  // Ran out of things to compare; they must match
737  else
738  return 0;
739  }
740 }
int SplitString(const wxString &strToSplit, wxString *strBeginning, wxString *strDigits, wxString *strEnd)
Break a string into three parts: he alphabetic preamble, the numeric part, and any alphabetic ending.
Definition: string.cpp:743
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:214
bool ApplyModifier(double &value, const wxString &aString)
Definition: string.cpp:647

References ApplyModifier(), SplitString(), and UnescapeString().

Referenced by FIELDS_EDITOR_GRID_DATA_MODEL::cmp().

◆ WildCompareString()

bool WildCompareString ( const wxString &  pattern,
const wxString &  string_to_tst,
bool  case_sensitive = true 
)

Compare a string against wild card (* and ?) pattern using the usual rules.

Returns
true if pattern matched otherwise false.

Definition at line 586 of file string.cpp.

588 {
589  const wxChar* cp = NULL, * mp = NULL;
590  const wxChar* wild, * str;
591  wxString _pattern, _string_to_tst;
592 
593  if( case_sensitive )
594  {
595  wild = pattern.GetData();
596  str = string_to_tst.GetData();
597  }
598  else
599  {
600  _pattern = pattern;
601  _pattern.MakeUpper();
602  _string_to_tst = string_to_tst;
603  _string_to_tst.MakeUpper();
604  wild = _pattern.GetData();
605  str = _string_to_tst.GetData();
606  }
607 
608  while( ( *str ) && ( *wild != '*' ) )
609  {
610  if( ( *wild != *str ) && ( *wild != '?' ) )
611  return false;
612 
613  wild++;
614  str++;
615  }
616 
617  while( *str )
618  {
619  if( *wild == '*' )
620  {
621  if( !*++wild )
622  return 1;
623  mp = wild;
624  cp = str + 1;
625  }
626  else if( ( *wild == *str ) || ( *wild == '?' ) )
627  {
628  wild++;
629  str++;
630  }
631  else
632  {
633  wild = mp;
634  str = cp++;
635  }
636  }
637 
638  while( *wild == '*' )
639  {
640  wild++;
641  }
642 
643  return !*wild;
644 }
#define NULL

References NULL.

Referenced by FROM_TO_CACHE::cacheFromToPaths(), LIBEVAL::VALUE::EqualTo(), DIALOG_EXCHANGE_FOOTPRINTS::isMatch(), DIALOG_CHANGE_SYMBOLS::isMatch(), and DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem().

◆ wxStringSplit()

void wxStringSplit ( const wxString &  aText,
wxArrayString &  aStrings,
wxChar  aSplitter 
)

Split aString to a string list separated at aSplitter.

Parameters
aTextis the text to split.
aStringswill contain the split lines.
aSplitteris the 'split' character.

Definition at line 895 of file string.cpp.

896 {
897  wxString tmp;
898 
899  for( unsigned ii = 0; ii < aText.Length(); ii++ )
900  {
901  if( aText[ii] == aSplitter )
902  {
903  aStrings.Add( tmp );
904  tmp.Clear();
905  }
906 
907  else
908  tmp << aText[ii];
909  }
910 
911  if( !tmp.IsEmpty() )
912  {
913  aStrings.Add( tmp );
914  }
915 }

Referenced by EDA_TEXT::GetTextBox(), HTML_MESSAGE_BOX::ListSet(), CADSTAR_SCH_ARCHIVE_LOADER::loadSymDefIntoLibrary(), PANEL_SETUP_RULES::OnErrorLinkClicked(), pcbnewGetWizardsBackTrace(), SCH_TEXT::Plot(), BRDITEMS_PLOTTER::PlotPcbText(), EDA_TEXT::Print(), TitleCaps(), and EDA_TEXT::TransformToSegmentList().

Variable Documentation

◆ illegalFileNameChars

const char illegalFileNameChars[] = "\\/:\"<>|"
static

Illegal file name characters used to ensure file names will be valid on all supported platforms.

This is the list of illegal file name characters for Windows which includes the illegal file name characters for Linux and OSX.

Definition at line 41 of file string.cpp.

Referenced by GetIllegalFileNameWxChars(), and ReplaceIllegalFileNameChars().