KiCad PCB EDA Suite
NUMERIC_EVALUATOR Class Reference

#include <numeric_evaluator.h>

Classes

struct  Token
 
struct  TokenStat
 

Public Member Functions

 NUMERIC_EVALUATOR (EDA_UNITS_T aUnits, bool aUseMils=false)
 
 ~NUMERIC_EVALUATOR ()
 
void Clear ()
 
void parseError (const char *s)
 
void parseOk ()
 
void parseSetResult (double)
 
bool IsValid () const
 
wxString Result () const
 
bool Process (const wxString &aString)
 
wxString OriginalText () const
 
void SetVar (const wxString &aString, double aValue)
 
double GetVar (const wxString &aString)
 
void RemoveVar (const wxString &aString)
 
void ClearVar ()
 

Protected Member Functions

void newString (const wxString &aString)
 
Token getToken ()
 
void parse (int token, numEval::TokenType value)
 

Private Types

enum  Unit { Unit::Invalid, Unit::Metric, Unit::Inch, Unit::Mil }
 

Private Attributes

void * m_parser
 
struct NUMERIC_EVALUATOR::TokenStat m_token
 
char m_localeDecimalSeparator
 
bool m_parseError
 
bool m_parseFinished
 
Unit m_defaultUnits
 
wxString m_originalText
 
std::map< wxString, double > m_varMap
 

Detailed Description

Definition at line 95 of file numeric_evaluator.h.

Member Enumeration Documentation

enum NUMERIC_EVALUATOR::Unit
strongprivate
Enumerator
Invalid 
Metric 
Inch 
Mil 

Definition at line 97 of file numeric_evaluator.h.

97 { Invalid, Metric, Inch, Mil };

Constructor & Destructor Documentation

NUMERIC_EVALUATOR::NUMERIC_EVALUATOR ( EDA_UNITS_T  aUnits,
bool  aUseMils = false 
)

Definition at line 59 of file numeric_evaluator.cpp.

60 {
61  struct lconv* lc = localeconv();
62  m_localeDecimalSeparator = *lc->decimal_point;
63 
64  m_parseError = false;
65  m_parseFinished = false;
66 
67  m_parser = numEval::ParseAlloc( malloc );
68 
69  switch( aUnits )
70  {
71  case INCHES:
72  if( aUseMils )
74  else
76  break;
78  break;
79  default:m_defaultUnits = Unit::Metric;
80  break;
81  }
82 }
Definition: common.h:160
void * ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE))
NUMERIC_EVALUATOR::~NUMERIC_EVALUATOR ( )

Definition at line 85 of file numeric_evaluator.cpp.

86 {
88 
89  // Allow explicit call to destructor
90  m_parser = nullptr;
91 
92  Clear();
93 }
void ParseFree(void *p, void(*freeProc)(void *))

Member Function Documentation

void NUMERIC_EVALUATOR::Clear ( )

Definition at line 96 of file numeric_evaluator.cpp.

Referenced by UNIT_BINDER::ChangeValue(), TEXT_CTRL_EVAL::SetValue(), and UNIT_BINDER::SetValue().

97 {
98  free( m_token.token );
99  m_token.token = nullptr;
100  m_token.input = nullptr;
101  m_parseError = true;
102  m_originalText = wxEmptyString;
103 }
struct NUMERIC_EVALUATOR::TokenStat m_token
void NUMERIC_EVALUATOR::ClearVar ( )
inline

Definition at line 138 of file numeric_evaluator.h.

138 { m_varMap.clear(); }
std::map< wxString, double > m_varMap
NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken ( )
protected

Definition at line 178 of file numeric_evaluator.cpp.

179 {
180  Token retval;
181  size_t idx;
182 
183  retval.token = ENDS;
184  retval.value.dValue = 0;
185 
186  if( m_token.token == nullptr )
187  return retval;
188 
189  if( m_token.input == nullptr )
190  return retval;
191 
192  if( m_token.pos >= m_token.inputLen )
193  return retval;
194 
195  auto isDecimalSeparator = [ & ]( char ch ) -> bool {
196  return ( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' );
197  };
198 
199  // Lambda: get value as string, store into clToken.token and update current index.
200  auto extractNumber = [ & ]() {
201  bool haveSeparator = false;
202  idx = 0;
203  auto ch = m_token.input[ m_token.pos ];
204 
205  do
206  {
207  if( isDecimalSeparator( ch ) && haveSeparator )
208  break;
209 
210  m_token.token[ idx++ ] = ch;
211 
212  if( isDecimalSeparator( ch ))
213  haveSeparator = true;
214 
215  ch = m_token.input[ ++m_token.pos ];
216  } while( isdigit( ch ) || isDecimalSeparator( ch ));
217 
218  m_token.token[ idx ] = 0;
219 
220  // Ensure that the systems decimal separator is used
221  for( int i = strlen( m_token.token ); i; i-- )
222  if( isDecimalSeparator( m_token.token[ i - 1 ] ))
224  };
225 
226  // Lamda: Get unit for current token.
227  // Valid units are ", in, mm, mil and thou. Returns Unit::Invalid otherwise.
228  auto checkUnit = [ this ]() -> Unit {
229  char ch = m_token.input[ m_token.pos ];
230 
231  if( ch == '"' )
232  {
233  m_token.pos++;
234  return Unit::Inch;
235  }
236 
237  // Do not use strcasecmp() as it is not available on all platforms
238  const char* cptr = &m_token.input[ m_token.pos ];
239  const auto sizeLeft = m_token.inputLen - m_token.pos;
240 
241  if( sizeLeft >= 2 && ch == 'm' && cptr[ 1 ] == 'm' && !isalnum( cptr[ 2 ] ))
242  {
243  m_token.pos += 2;
244  return Unit::Metric;
245  }
246 
247  if( sizeLeft >= 2 && ch == 'i' && cptr[ 1 ] == 'n' && !isalnum( cptr[ 2 ] ))
248  {
249  m_token.pos += 2;
250  return Unit::Inch;
251  }
252 
253  if( sizeLeft >= 3 && ch == 'm' && cptr[ 1 ] == 'i' && cptr[ 2 ] == 'l' && !isalnum( cptr[ 3 ] ))
254  {
255  m_token.pos += 3;
256  return Unit::Mil;
257  }
258 
259  if( sizeLeft >= 4 && ch == 't' && cptr[ 1 ] == 'h' && cptr[ 2 ] == 'o' && cptr[ 3 ] == 'u' && !isalnum( cptr[ 4 ] ))
260  {
261  m_token.pos += 4;
262  return Unit::Mil;
263  }
264 
265  return Unit::Invalid;
266  };
267 
268  char ch;
269 
270  // Start processing of first/next token: Remove whitespace
271  for( ;; )
272  {
273  ch = m_token.input[ m_token.pos ];
274 
275  if( ch == ' ' )
276  m_token.pos++;
277  else
278  break;
279  }
280 
281  Unit convertFrom;
282 
283  if( ch == 0 )
284  {
285  /* End of input */
286  }
287  else if( isdigit( ch ) || isDecimalSeparator( ch ))
288  {
289  // VALUE
290  extractNumber();
291  retval.token = VALUE;
292  retval.value.dValue = atof( m_token.token );
293  }
294  else if(( convertFrom = checkUnit()) != Unit::Invalid )
295  {
296  // UNIT
297  // Units are appended to a VALUE.
298  // Determine factor to default unit if unit for value is given.
299  // Example: Default is mm, unit is inch: factor is 25.4
300  // The factor is assigned to the terminal UNIT. The actual
301  // conversion is done within a parser action.
302  retval.token = UNIT;
304  {
305  switch( convertFrom )
306  {
307  case Unit::Inch :retval.value.dValue = 25.4; break;
308  case Unit::Mil :retval.value.dValue = 25.4 / 1000.0; break;
309  case Unit::Metric :retval.value.dValue = 1.0; break;
310  case Unit::Invalid :break;
311  }
312  }
313  else if( m_defaultUnits == Unit::Inch )
314  {
315  switch( convertFrom )
316  {
317  case Unit::Inch :retval.value.dValue = 1.0; break;
318  case Unit::Mil :retval.value.dValue = 1.0 / 1000.0; break;
319  case Unit::Metric :retval.value.dValue = 1.0 / 25.4; break;
320  case Unit::Invalid :break;
321  }
322  }
323  else if( m_defaultUnits == Unit::Mil )
324  {
325  switch( convertFrom )
326  {
327  case Unit::Inch :retval.value.dValue = 1.0 * 1000.0; break;
328  case Unit::Mil :retval.value.dValue = 1.0; break;
329  case Unit::Metric :retval.value.dValue = 1000.0 / 25.4; break;
330  case Unit::Invalid :break;
331  }
332  }
333  }
334  else if( isalpha( ch ))
335  {
336  // VAR
337  const char* cptr = &m_token.input[ m_token.pos ];
338  cptr++;
339 
340  while( isalnum( *cptr ))
341  cptr++;
342 
343  retval.token = VAR;
344  size_t bytesToCopy = cptr - &m_token.input[ m_token.pos ];
345 
346  if( bytesToCopy >= sizeof( retval.value.text ))
347  bytesToCopy = sizeof( retval.value.text ) - 1;
348 
349  strncpy( retval.value.text, &m_token.input[ m_token.pos ], bytesToCopy );
350  retval.value.text[ bytesToCopy ] = 0;
351  m_token.pos += cptr - &m_token.input[ m_token.pos ];
352  }
353  else
354  {
355  // Single char tokens
356  switch( ch )
357  {
358  case '+' :retval.token = PLUS; break;
359  case '-' :retval.token = MINUS; break;
360  case '*' :retval.token = MULT; break;
361  case '/' :retval.token = DIVIDE; break;
362  case '(' :retval.token = PARENL; break;
363  case ')' :retval.token = PARENR; break;
364  case '=' :retval.token = ASSIGN; break;
365  case ';' :retval.token = SEMCOL; break;
366  default :m_parseError = true; break; /* invalid character */
367  }
368  m_token.pos++;
369  }
370 
371  return retval;
372 }
#define ASSIGN
#define PARENR
struct NUMERIC_EVALUATOR::TokenStat m_token
#define MINUS
#define SEMCOL
#define ENDS
#define PARENL
#define MULT
#define DIVIDE
#define UNIT
#define PLUS
size_t i
Definition: json11.cpp:597
#define VAR
#define VALUE
double NUMERIC_EVALUATOR::GetVar ( const wxString &  aString)

Definition at line 379 of file numeric_evaluator.cpp.

380 {
381  if( m_varMap[ aString ] )
382  return m_varMap[ aString ];
383  else
384  return 0.0;
385 }
std::map< wxString, double > m_varMap
bool NUMERIC_EVALUATOR::IsValid ( ) const
inline

Definition at line 114 of file numeric_evaluator.h.

114 { return !m_parseError; }
void NUMERIC_EVALUATOR::newString ( const wxString &  aString)
protected

Definition at line 162 of file numeric_evaluator.cpp.

163 {
164  Clear();
165 
166  m_originalText = aString;
167 
168  m_token.token = reinterpret_cast<decltype( m_token.token )>( malloc( TokenStat::OutLen + 1 ) );
169  strcpy( m_token.token, "0" );
170  m_token.inputLen = aString.length();
171  m_token.pos = 0;
172  m_token.input = aString.mb_str();
173 
174  m_parseFinished = false;
175 }
struct NUMERIC_EVALUATOR::TokenStat m_token
wxString NUMERIC_EVALUATOR::OriginalText ( ) const

Definition at line 124 of file numeric_evaluator.cpp.

Referenced by UNIT_BINDER::onSetFocus(), and TEXT_CTRL_EVAL::onTextFocusGet().

125 {
126  return m_originalText;
127 }
void NUMERIC_EVALUATOR::parse ( int  token,
numEval::TokenType  value 
)
protected
void NUMERIC_EVALUATOR::parseError ( const char *  s)

Definition at line 106 of file numeric_evaluator.cpp.

107 {
108  m_parseError = true;
109 }
void NUMERIC_EVALUATOR::parseOk ( )

Definition at line 112 of file numeric_evaluator.cpp.

113 {
114  m_parseFinished = true;
115 }
void NUMERIC_EVALUATOR::parseSetResult ( double  val)

Definition at line 118 of file numeric_evaluator.cpp.

119 {
120  snprintf( m_token.token, m_token.OutLen, "%.10g", val );
121 }
struct NUMERIC_EVALUATOR::TokenStat m_token
bool NUMERIC_EVALUATOR::Process ( const wxString &  aString)

Definition at line 130 of file numeric_evaluator.cpp.

Referenced by TEXT_CTRL_EVAL::evaluate(), UNIT_BINDER::GetValue(), and UNIT_BINDER::onKillFocus().

131 {
132  // Feed parser token after token until end of input.
133 
134  newString( aString );
135  m_parseError = false;
136  m_parseFinished = false;
137  Token tok;
138 
139  if( aString.IsEmpty() )
140  {
141  m_parseFinished = true;
142  return true;
143  }
144 
145  do
146  {
147  tok = getToken();
148  numEval::Parse( m_parser, tok.token, tok.value, this );
149 
150  if( m_parseFinished || tok.token == ENDS )
151  {
152  // Reset parser by passing zero as token ID, value is ignored.
153  numEval::Parse( m_parser, 0, tok.value, this );
154  break;
155  }
156  } while( tok.token );
157 
158  return !m_parseError;
159 }
void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminorParseARG_PDECL)
#define ENDS
void newString(const wxString &aString)
void NUMERIC_EVALUATOR::RemoveVar ( const wxString &  aString)
inline

Definition at line 135 of file numeric_evaluator.h.

135 { m_varMap.erase( aString ); }
std::map< wxString, double > m_varMap
wxString NUMERIC_EVALUATOR::Result ( ) const
inline

Definition at line 117 of file numeric_evaluator.h.

Referenced by TEXT_CTRL_EVAL::evaluate(), UNIT_BINDER::GetValue(), and UNIT_BINDER::onKillFocus().

117 { return wxString::FromUTF8( m_token.token ); }
struct NUMERIC_EVALUATOR::TokenStat m_token
void NUMERIC_EVALUATOR::SetVar ( const wxString &  aString,
double  aValue 
)

Definition at line 374 of file numeric_evaluator.cpp.

References numEval::NUMERIC_EVALUATOR::m_varMap.

375 {
376  m_varMap[ aString ] = aValue;
377 }
std::map< wxString, double > m_varMap

Member Data Documentation

Unit NUMERIC_EVALUATOR::m_defaultUnits
private

Definition at line 178 of file numeric_evaluator.h.

char NUMERIC_EVALUATOR::m_localeDecimalSeparator
private

Definition at line 172 of file numeric_evaluator.h.

wxString NUMERIC_EVALUATOR::m_originalText
private

Definition at line 180 of file numeric_evaluator.h.

bool NUMERIC_EVALUATOR::m_parseError
private

Definition at line 175 of file numeric_evaluator.h.

bool NUMERIC_EVALUATOR::m_parseFinished
private

Definition at line 176 of file numeric_evaluator.h.

void* NUMERIC_EVALUATOR::m_parser
private

Definition at line 158 of file numeric_evaluator.h.

struct NUMERIC_EVALUATOR::TokenStat NUMERIC_EVALUATOR::m_token
private
std::map<wxString, double> NUMERIC_EVALUATOR::m_varMap
private

Definition at line 182 of file numeric_evaluator.h.


The documentation for this class was generated from the following files: