KiCad PCB EDA Suite
am_param.cpp File Reference
#include <am_param.h>
#include <am_primitive.h>
#include <macros.h>
#include <wx/debug.h>

Go to the source code of this file.

Functions

int ReadInt (char *&text, bool aSkipSeparator=true)
 Read an integer from an ASCII character buffer. More...
 
double ReadDouble (char *&text, bool aSkipSeparator=true)
 Read a double precision floating point number from an ASCII character buffer. More...
 
double Evaluate (AM_PARAM_EVAL_STACK &aExp)
 Evaluate an basic arithmetic expression (infix notation) with precedence The expression is a sequence of numbers (double) and arith operators: operators are + - x / ( and ) the expression is stored in a std::vector each item is a AM_PARAM_EVAL (each item is an operator or a double) More...
 

Function Documentation

◆ Evaluate()

double Evaluate ( AM_PARAM_EVAL_STACK aExp)

Evaluate an basic arithmetic expression (infix notation) with precedence The expression is a sequence of numbers (double) and arith operators: operators are + - x / ( and ) the expression is stored in a std::vector each item is a AM_PARAM_EVAL (each item is an operator or a double)

Parameters
aExp= the arithmetic expression to evaluate
Returns
the value

Definition at line 102 of file evaluate.cpp.

103 {
104  class OP_CODE // A small class to store a operator and its priority
105  {
106  public:
107  parm_item_type m_Optype;
108  int m_Priority;
109 
110  OP_CODE( AM_PARAM_EVAL& aAmPrmEval )
111  : m_Optype( aAmPrmEval.GetOperator() ),
112  m_Priority( aAmPrmEval.GetPriority() )
113  {}
114 
115  OP_CODE( parm_item_type aOptype )
116  : m_Optype( aOptype ), m_Priority( 0 )
117  {}
118  };
119 
120  double result = 0.0;
121 
122  std::vector<double> values; // the current list of values
123  std::vector<OP_CODE> optype; // the list of arith operators
124 
125  double curr_value = 0.0;
126  int extra_priority = 0;
127 
128  for( unsigned ii = 0; ii < aExp.size(); ii++ )
129  {
130  AM_PARAM_EVAL& prm = aExp[ii];
131 
132  if( prm.IsOperator() )
133  {
134  if( prm.GetOperator() == OPEN_PAR )
135  {
136  extra_priority += AM_PARAM_EVAL::GetPriority( OPEN_PAR );
137  }
138  else if( prm.GetOperator() == CLOSE_PAR )
139  {
140  extra_priority -= AM_PARAM_EVAL::GetPriority( CLOSE_PAR );
141  }
142  else
143  {
144  optype.emplace_back( prm );
145  optype.back().m_Priority += extra_priority;
146  }
147  }
148  else // we have a value:
149  {
150  values.push_back( prm.GetValue() );
151 
152  if( optype.size() < 2 )
153  continue;
154 
155  OP_CODE& previous_optype = optype[optype.size() - 2];
156 
157  if( optype.back().m_Priority > previous_optype.m_Priority )
158  {
159  double op1 = 0.0;
160 
161  double op2 = values.back();
162  values.pop_back();
163 
164  if( values.size() )
165  {
166  op1 = values.back();
167  values.pop_back();
168  }
169 
170  switch( optype.back().m_Optype )
171  {
172  case ADD:
173  values.push_back( op1+op2 );
174  break;
175 
176  case SUB:
177  values.push_back( op1-op2 );
178  break;
179 
180  case MUL:
181  values.push_back( op1*op2 );
182  break;
183 
184  case DIV:
185  values.push_back( op1/op2 );
186  break;
187 
188  default:
189  break;
190  }
191 
192  optype.pop_back();
193  }
194  }
195  }
196 
197  // Now all operators have the same priority, or those having the higher priority
198  // are before others, calculate the final result by combining initial values and/or
199  // replaced values.
200  if( values.size() > optype.size() )
201  // If there are n values, the number of operator is n-1 or n if the first
202  // item of the expression to evaluate is + or - (like -$1/2)
203  // If the number of operator is n-1 the first value is just copied to result
204  optype.insert( optype.begin(), OP_CODE( POPVALUE ) );
205 
206  wxASSERT( values.size() == optype.size() );
207 
208  for( unsigned idx = 0; idx < values.size(); idx++ )
209  {
210  curr_value = values[idx];
211 
212  switch( optype[idx].m_Optype )
213  {
214  case POPVALUE:
215  result = curr_value;
216  break;
217 
218  case ADD:
219  result += curr_value;
220  break;
221 
222  case SUB:
223  result -= curr_value;
224  break;
225 
226  case MUL:
227  result *= curr_value;
228  break;
229 
230  case DIV:
231  result /= curr_value;
232  break;
233 
234  default:
235  break;
236  }
237  }
238 
239  return result;
240 }
Definition: am_param.h:150
parm_item_type GetOperator() const
Definition: am_param.h:178
int GetPriority() const
Definition: am_param.h:179
parm_item_type
Definition: am_param.h:148
Definition: am_param.h:150
Definition: am_param.h:150
bool IsOperator() const
Definition: am_param.h:176
This helper class hold a value or an arithmetic operator to calculate the final value of a aperture m...
Definition: am_param.h:160
Definition: am_param.h:150
double GetValue() const
Definition: am_param.h:177

References ADD, CLOSE_PAR, DIV, AM_PARAM_EVAL::GetOperator(), AM_PARAM_EVAL::GetPriority(), AM_PARAM_EVAL::GetValue(), AM_PARAM_EVAL::IsOperator(), MUL, OPEN_PAR, POPVALUE, and SUB.

Referenced by AM_PARAM::GetValue().

◆ ReadDouble()

double ReadDouble ( char *&  text,
bool  aSkipSeparator = true 
)

Read a double precision floating point number from an ASCII character buffer.

If there is a comma after the number, then skip over that.

Parameters
textis a reference to a character pointer from which the ASCII double is read from and the pointer advanced for each character read.
aSkipSeparatorset to true (default) to skip comma.
Returns
number read.

Definition at line 335 of file rs274_read_XY_and_IJ_coordinates.cpp.

336 {
337  double ret;
338 
339  // For strtod, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
340  // However, 'X' is a separator in Gerber strings with numbers.
341  // We need to detect that
342  if( strncasecmp( text, "0X", 2 ) == 0 )
343  {
344  text++;
345  ret = 0.0;
346  }
347  else
348  {
349  ret = strtod( text, &text );
350  }
351 
352  if( *text == ',' || isspace( *text ) )
353  {
354  if( aSkipSeparator )
355  ++text;
356  }
357 
358  return ret;
359 }

Referenced by AM_PARAM::ReadParam().

◆ ReadInt()

int ReadInt ( char *&  text,
bool  aSkipSeparator = true 
)

Read an integer from an ASCII character buffer.

If there is a comma after the integer, then skip over that.

Parameters
textis a reference to a character pointer from which bytes are read and the pointer is advanced for each byte read.
aSkipSeparatorset to true (default) to skip comma.
Returns
The integer read in.

Definition at line 298 of file rs274_read_XY_and_IJ_coordinates.cpp.

299 {
300  int ret;
301 
302  // For strtol, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
303  // However, 'X' is a separator in Gerber strings with numbers.
304  // We need to detect that
305  if( strncasecmp( text, "0X", 2 ) == 0 )
306  {
307  text++;
308  ret = 0;
309  }
310  else
311  {
312  ret = (int) strtol( text, &text, 10 );
313  }
314 
315  if( *text == ',' || isspace( *text ) )
316  {
317  if( aSkipSeparator )
318  ++text;
319  }
320 
321  return ret;
322 }

Referenced by AM_PARAM::ReadParam().