Cppcheck
mathlib.cpp
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2023 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 
20 #include "mathlib.h"
21 #include "errortypes.h"
22 #include "utils.h"
23 
24 #include <cctype>
25 #include <cmath>
26 #include <cstdint>
27 #include <cstdlib>
28 #include <exception>
29 #include <limits>
30 #include <locale>
31 #include <sstream>
32 #include <stdexcept>
33 #include <numeric>
34 
35 #include <simplecpp.h>
36 
37 
38 const int MathLib::bigint_bits = 64;
39 
40 MathLib::value::value(const std::string &s)
41 {
42  if (MathLib::isFloat(s)) {
45  return;
46  }
47 
48  if (!MathLib::isInt(s))
49  throw InternalError(nullptr, "Invalid value: " + s);
50 
53 
54  if (isIntHex(s) && mIntValue < 0)
55  mIsUnsigned = true;
56 
57  // read suffix
58  if (s.size() >= 2U) {
59  for (std::size_t i = s.size() - 1U; i > 0U; --i) {
60  const char c = s[i];
61  if (c == 'u' || c == 'U')
62  mIsUnsigned = true;
63  else if (c == 'l' || c == 'L') {
68  } else if (i > 2U && c == '4' && s[i-1] == '6' && s[i-2] == 'i')
70  }
71  }
72 }
73 
74 std::string MathLib::value::str() const
75 {
76  std::ostringstream ostr;
77  if (mType == MathLib::value::Type::FLOAT) {
78  if (std::isnan(mDoubleValue))
79  return "nan.0";
80  if (std::isinf(mDoubleValue))
81  return (mDoubleValue > 0) ? "inf.0" : "-inf.0";
82 
83  ostr.precision(9);
84  ostr << std::fixed << mDoubleValue;
85 
86  // remove trailing zeros
87  std::string ret(ostr.str());
88  std::string::size_type pos = ret.size() - 1U;
89  while (ret[pos] == '0')
90  pos--;
91  if (ret[pos] == '.')
92  ++pos;
93 
94  return ret.substr(0, pos+1);
95  }
96 
97  if (mIsUnsigned)
98  ostr << static_cast<biguint>(mIntValue) << "U";
99  else
100  ostr << mIntValue;
101  if (mType == MathLib::value::Type::LONG)
102  ostr << "L";
103  else if (mType == MathLib::value::Type::LONGLONG)
104  ostr << "LL";
105  return ostr.str();
106 }
107 
109 {
110  if (isInt() && v.isInt()) {
111  if (mType < v.mType) {
112  mType = v.mType;
113  mIsUnsigned = v.mIsUnsigned;
114  } else if (mType == v.mType) {
115  mIsUnsigned |= v.mIsUnsigned;
116  }
117  } else if (!isFloat()) {
118  mIsUnsigned = false;
119  mDoubleValue = mIntValue;
121  }
122 }
123 
124 
126 {
127  value temp(v1);
128  temp.promote(v2);
129  if (temp.isFloat()) {
130  switch (op) {
131  case '+':
132  temp.mDoubleValue += v2.getDoubleValue();
133  break;
134  case '-':
135  temp.mDoubleValue -= v2.getDoubleValue();
136  break;
137  case '*':
138  temp.mDoubleValue *= v2.getDoubleValue();
139  break;
140  case '/':
141  temp.mDoubleValue /= v2.getDoubleValue();
142  break;
143  case '%':
144  case '&':
145  case '|':
146  case '^':
147  throw InternalError(nullptr, "Invalid calculation");
148  default:
149  throw InternalError(nullptr, "Unhandled calculation");
150  }
151  } else if (temp.mIsUnsigned) {
152  switch (op) {
153  case '+':
154  temp.mIntValue += (unsigned long long)v2.mIntValue;
155  break;
156  case '-':
157  temp.mIntValue -= (unsigned long long)v2.mIntValue;
158  break;
159  case '*':
160  temp.mIntValue *= (unsigned long long)v2.mIntValue;
161  break;
162  case '/':
163  if (v2.mIntValue == 0)
164  throw InternalError(nullptr, "Internal Error: Division by zero");
165  if (v1.mIntValue == std::numeric_limits<bigint>::min() && std::abs(v2.mIntValue)<=1)
166  throw InternalError(nullptr, "Internal Error: Division overflow");
167  temp.mIntValue /= (unsigned long long)v2.mIntValue;
168  break;
169  case '%':
170  if (v2.mIntValue == 0)
171  throw InternalError(nullptr, "Internal Error: Division by zero");
172  temp.mIntValue %= (unsigned long long)v2.mIntValue;
173  break;
174  case '&':
175  temp.mIntValue &= (unsigned long long)v2.mIntValue;
176  break;
177  case '|':
178  temp.mIntValue |= (unsigned long long)v2.mIntValue;
179  break;
180  case '^':
181  temp.mIntValue ^= (unsigned long long)v2.mIntValue;
182  break;
183  default:
184  throw InternalError(nullptr, "Unhandled calculation");
185  }
186  } else {
187  switch (op) {
188  case '+':
189  temp.mIntValue += v2.mIntValue;
190  break;
191  case '-':
192  temp.mIntValue -= v2.mIntValue;
193  break;
194  case '*':
195  temp.mIntValue *= v2.mIntValue;
196  break;
197  case '/':
198  if (v2.mIntValue == 0)
199  throw InternalError(nullptr, "Internal Error: Division by zero");
200  if (v1.mIntValue == std::numeric_limits<bigint>::min() && std::abs(v2.mIntValue)<=1)
201  throw InternalError(nullptr, "Internal Error: Division overflow");
202  temp.mIntValue /= v2.mIntValue;
203  break;
204  case '%':
205  if (v2.mIntValue == 0)
206  throw InternalError(nullptr, "Internal Error: Division by zero");
207  temp.mIntValue %= v2.mIntValue;
208  break;
209  case '&':
210  temp.mIntValue &= v2.mIntValue;
211  break;
212  case '|':
213  temp.mIntValue |= v2.mIntValue;
214  break;
215  case '^':
216  temp.mIntValue ^= v2.mIntValue;
217  break;
218  default:
219  throw InternalError(nullptr, "Unhandled calculation");
220  }
221  }
222  return temp;
223 }
224 
225 
227 {
228  value temp(*this);
229  temp.promote(v);
230 
231  if (temp.isFloat()) {
232  if (temp.mDoubleValue < v.getDoubleValue())
233  return -1;
234  if (temp.mDoubleValue > v.getDoubleValue())
235  return 1;
236  return 0;
237  }
238 
239  if (temp.mIsUnsigned) {
240  if ((unsigned long long)mIntValue < (unsigned long long)v.mIntValue)
241  return -1;
242  if ((unsigned long long)mIntValue > (unsigned long long)v.mIntValue)
243  return 1;
244  return 0;
245  }
246 
247  if (mIntValue < v.mIntValue)
248  return -1;
249  if (mIntValue > v.mIntValue)
250  return 1;
251  return 0;
252 }
253 
255 {
256  MathLib::value temp(*this);
257  if (temp.isInt())
258  temp.mIntValue += v;
259  else
260  temp.mDoubleValue += v;
261  return temp;
262 }
263 
265 {
266  if (!isInt() || !v.isInt())
267  throw InternalError(nullptr, "Shift operand is not integer");
268  MathLib::value ret(*this);
269  if (v.mIntValue >= MathLib::bigint_bits) {
270  return ret;
271  }
272  ret.mIntValue <<= v.mIntValue;
273  return ret;
274 }
275 
277 {
278  if (!isInt() || !v.isInt())
279  throw InternalError(nullptr, "Shift operand is not integer");
280  MathLib::value ret(*this);
281  if (v.mIntValue >= MathLib::bigint_bits) {
282  return ret;
283  }
284  ret.mIntValue >>= v.mIntValue;
285  return ret;
286 }
287 
288 // TODO: remove handling of non-literal stuff
289 MathLib::biguint MathLib::toBigUNumber(const std::string & str)
290 {
291  // hexadecimal numbers:
292  if (isIntHex(str)) {
293  try {
294  const biguint ret = std::stoull(str, nullptr, 16);
295  return ret;
296  } catch (const std::out_of_range& /*e*/) {
297  throw InternalError(nullptr, "Internal Error. MathLib::toBigUNumber: out_of_range: " + str);
298  } catch (const std::invalid_argument& /*e*/) {
299  throw InternalError(nullptr, "Internal Error. MathLib::toBigUNumber: invalid_argument: " + str);
300  }
301  }
302 
303  // octal numbers:
304  if (isOct(str)) {
305  try {
306  const biguint ret = std::stoull(str, nullptr, 8);
307  return ret;
308  } catch (const std::out_of_range& /*e*/) {
309  throw InternalError(nullptr, "Internal Error. MathLib::toBigUNumber: out_of_range: " + str);
310  } catch (const std::invalid_argument& /*e*/) {
311  throw InternalError(nullptr, "Internal Error. MathLib::toBigUNumber: invalid_argument: " + str);
312  }
313  }
314 
315  // binary numbers:
316  if (isBin(str)) {
317  biguint ret = 0;
318  for (std::string::size_type i = str[0] == '0'?2:3; i < str.length(); i++) {
319  if (str[i] != '1' && str[i] != '0')
320  break;
321  ret <<= 1;
322  if (str[i] == '1')
323  ret |= 1;
324  }
325  if (str[0] == '-')
326  ret = -ret;
327  return ret;
328  }
329 
330  if (isFloat(str)) {
331  // Things are going to be less precise now: the value can't be represented in the biguint type.
332  // Use min/max values as an approximation. See #5843
333  // TODO: bail out when we are out of range?
334  const double doubleval = toDoubleNumber(str);
335  if (doubleval > (double)std::numeric_limits<biguint>::max())
336  return std::numeric_limits<biguint>::max();
337  // cast to bigint to avoid UBSAN warning about negative double being out-of-range
338  return static_cast<biguint>(static_cast<bigint>(doubleval));
339  }
340 
341  if (isCharLiteral(str))
342  return simplecpp::characterLiteralToLL(str);
343 
344  try {
345  std::size_t idx = 0;
346  const biguint ret = std::stoull(str, &idx, 10);
347  if (idx != str.size()) {
348  const std::string s = str.substr(idx);
349  if (!isValidIntegerSuffix(s, true))
350  throw InternalError(nullptr, "Internal Error. MathLib::toBigUNumber: input was not completely consumed: " + str);
351  }
352  return ret;
353  } catch (const std::out_of_range& /*e*/) {
354  throw InternalError(nullptr, "Internal Error. MathLib::toBigUNumber: out_of_range: " + str);
355  } catch (const std::invalid_argument& /*e*/) {
356  throw InternalError(nullptr, "Internal Error. MathLib::toBigUNumber: invalid_argument: " + str);
357  }
358 }
359 
360 unsigned int MathLib::encodeMultiChar(const std::string& str)
361 {
362  return std::accumulate(str.cbegin(), str.cend(), uint32_t(), [](uint32_t v, char c) {
363  return (v << 8) | c;
364  });
365 }
366 
367 // TODO: remove handling of non-literal stuff
368 MathLib::bigint MathLib::toBigNumber(const std::string & str)
369 {
370  // hexadecimal numbers:
371  if (isIntHex(str)) {
372  try {
373  const biguint ret = std::stoull(str, nullptr, 16);
374  return (bigint)ret;
375  } catch (const std::out_of_range& /*e*/) {
376  throw InternalError(nullptr, "Internal Error. MathLib::toBigNumber: out_of_range: " + str);
377  } catch (const std::invalid_argument& /*e*/) {
378  throw InternalError(nullptr, "Internal Error. MathLib::toBigNumber: invalid_argument: " + str);
379  }
380  }
381 
382  // octal numbers:
383  if (isOct(str)) {
384  try {
385  const biguint ret = std::stoull(str, nullptr, 8);
386  return ret;
387  } catch (const std::out_of_range& /*e*/) {
388  throw InternalError(nullptr, "Internal Error. MathLib::toBigNumber: out_of_range: " + str);
389  } catch (const std::invalid_argument& /*e*/) {
390  throw InternalError(nullptr, "Internal Error. MathLib::toBigNumber: invalid_argument: " + str);
391  }
392  }
393 
394  // binary numbers:
395  if (isBin(str)) {
396  bigint ret = 0;
397  for (std::string::size_type i = str[0] == '0'?2:3; i < str.length(); i++) {
398  if (str[i] != '1' && str[i] != '0')
399  break;
400  ret <<= 1;
401  if (str[i] == '1')
402  ret |= 1;
403  }
404  if (str[0] == '-')
405  ret = -ret;
406  return ret;
407  }
408 
409  if (isFloat(str)) {
410  // Things are going to be less precise now: the value can't be represented in the bigint type.
411  // Use min/max values as an approximation. See #5843
412  // TODO: bail out when we are out of range?
413  const double doubleval = toDoubleNumber(str);
414  if (doubleval > (double)std::numeric_limits<bigint>::max())
415  return std::numeric_limits<bigint>::max();
416  if (doubleval < (double)std::numeric_limits<bigint>::min())
417  return std::numeric_limits<bigint>::min();
418  return static_cast<bigint>(doubleval);
419  }
420 
421  if (isCharLiteral(str))
422  return simplecpp::characterLiteralToLL(str);
423 
424  try {
425  std::size_t idx = 0;
426  const biguint ret = std::stoull(str, &idx, 10);
427  if (idx != str.size()) {
428  const std::string s = str.substr(idx);
429  if (!isValidIntegerSuffix(s, true))
430  throw InternalError(nullptr, "Internal Error. MathLib::toBigNumber: input was not completely consumed: " + str);
431  }
432  return ret;
433  } catch (const std::out_of_range& /*e*/) {
434  throw InternalError(nullptr, "Internal Error. MathLib::toBigNumber: out_of_range: " + str);
435  } catch (const std::invalid_argument& /*e*/) {
436  throw InternalError(nullptr, "Internal Error. MathLib::toBigNumber: invalid_argument: " + str);
437  }
438 }
439 
440 // in-place conversion of (sub)string to double. Requires no heap.
441 static double myStod(const std::string& str, std::string::const_iterator from, std::string::const_iterator to, int base)
442 {
443  double result = 0.;
444  bool positivesign = true;
445  std::string::const_iterator it;
446  if ('+' == *from) {
447  it = from + 1;
448  } else if ('-' == *from) {
449  it = from + 1;
450  positivesign = false;
451  } else
452  it = from;
453  const std::size_t decimalsep = str.find('.', it-str.begin());
454  int distance;
455  if (std::string::npos == decimalsep) {
456  distance = to - it;
457  } else if (decimalsep > (to - str.begin()))
458  return 0.; // error handling??
459  else
460  distance = int(decimalsep)-(from - str.begin());
461  auto digitval = [&](char c) {
462  if ((10 < base) && (c > '9'))
463  return 10 + std::tolower(c) - 'a';
464  return c - '0';
465  };
466  for (; it!=to; ++it) {
467  if ('.' == *it)
468  continue;
469  --distance;
470  result += digitval(*it)* std::pow(base, distance);
471  }
472  return positivesign ? result : -result;
473 }
474 
475 // Assuming a limited support of built-in hexadecimal floats (see C99, C++17) that is a fall-back implementation.
476 // Performance has been optimized WRT to heap activity, however the calculation part is not optimized.
477 static double floatHexToDoubleNumber(const std::string& str)
478 {
479  const std::size_t p = str.find_first_of("pP",3);
480  const double factor1 = myStod(str, str.cbegin() + 2, str.cbegin()+p, 16);
481  const bool suffix = (str.back() == 'f') || (str.back() == 'F') || (str.back() == 'l') || (str.back() == 'L');
482  const double exponent = myStod(str, str.cbegin() + p + 1, suffix ? str.cend()-1:str.cend(), 10);
483  const double factor2 = std::pow(2, exponent);
484  return factor1 * factor2;
485 }
486 
487 double MathLib::toDoubleNumber(const std::string &str)
488 {
489  if (isCharLiteral(str)) {
490  try {
491  return simplecpp::characterLiteralToLL(str);
492  } catch (const std::exception& e) {
493  throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: characterLiteralToLL(" + str + ") => " + e.what());
494  }
495  }
496  if (isIntHex(str))
497  return static_cast<double>(toBigNumber(str));
498 #ifdef _LIBCPP_VERSION
499  if (isFloat(str)) // Workaround libc++ bug at https://github.com/llvm/llvm-project/issues/18156
500  // TODO: handle locale
501  // TODO: make sure all characters are being consumed
502  return std::strtod(str.c_str(), nullptr);
503 #endif
504  if (isFloatHex(str))
505  return floatHexToDoubleNumber(str);
506  // otherwise, convert to double
507  std::istringstream istr(str);
508  istr.imbue(std::locale::classic());
509  double ret;
510  if (!(istr >> ret))
511  throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: conversion failed: " + str);
512  std::string s;
513  if (istr >> s) {
514  if (isDecimalFloat(str))
515  return ret;
516  if (!isValidIntegerSuffix(s, true))
517  throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: " + str);
518  }
519  return ret;
520 }
521 
522 template<> std::string MathLib::toString<double>(double value)
523 {
524  std::ostringstream result;
525  result.precision(12);
526  result << value;
527  std::string s = result.str();
528  if (s == "-0")
529  return "0.0";
530  if (s.find_first_of(".e") == std::string::npos)
531  return s + ".0";
532  return s;
533 }
534 
535 bool MathLib::isFloat(const std::string &str)
536 {
537  return isDecimalFloat(str) || isFloatHex(str);
538 }
539 
540 bool MathLib::isDecimalFloat(const std::string &str)
541 {
542  if (str.empty())
543  return false;
544  enum class State {
545  START, BASE_DIGITS1, LEADING_DECIMAL, TRAILING_DECIMAL, BASE_DIGITS2, E, MANTISSA_PLUSMINUS, MANTISSA_DIGITS, SUFFIX_F, SUFFIX_L, SUFFIX_LITERAL_LEADER, SUFFIX_LITERAL
546  } state = State::START;
547  std::string::const_iterator it = str.cbegin();
548  if ('+' == *it || '-' == *it)
549  ++it;
550  for (; it != str.cend(); ++it) {
551  switch (state) {
552  case State::START:
553  if (*it=='.')
554  state = State::LEADING_DECIMAL;
555  else if (std::isdigit(static_cast<unsigned char>(*it)))
556  state = State::BASE_DIGITS1;
557  else
558  return false;
559  break;
560  case State::LEADING_DECIMAL:
561  if (std::isdigit(static_cast<unsigned char>(*it)))
562  state = State::BASE_DIGITS2;
563  else
564  return false;
565  break;
566  case State::BASE_DIGITS1:
567  if (*it=='e' || *it=='E')
568  state = State::E;
569  else if (*it=='.')
570  state = State::TRAILING_DECIMAL;
571  else if (!std::isdigit(static_cast<unsigned char>(*it)))
572  return false;
573  break;
574  case State::TRAILING_DECIMAL:
575  if (*it=='e' || *it=='E')
576  state = State::E;
577  else if (*it=='f' || *it=='F')
578  state = State::SUFFIX_F;
579  else if (*it=='l' || *it=='L')
580  state = State::SUFFIX_L;
581  else if (*it == '_')
582  state = State::SUFFIX_LITERAL_LEADER;
583  else if (std::isdigit(static_cast<unsigned char>(*it)))
584  state = State::BASE_DIGITS2;
585  else
586  return false;
587  break;
588  case State::BASE_DIGITS2:
589  if (*it=='e' || *it=='E')
590  state = State::E;
591  else if (*it=='f' || *it=='F')
592  state = State::SUFFIX_F;
593  else if (*it=='l' || *it=='L')
594  state = State::SUFFIX_L;
595  else if (*it == '_')
596  state = State::SUFFIX_LITERAL_LEADER;
597  else if (!std::isdigit(static_cast<unsigned char>(*it)))
598  return false;
599  break;
600  case State::E:
601  if (*it=='+' || *it=='-')
602  state = State::MANTISSA_PLUSMINUS;
603  else if (std::isdigit(static_cast<unsigned char>(*it)))
604  state = State::MANTISSA_DIGITS;
605  else
606  return false;
607  break;
608  case State::MANTISSA_PLUSMINUS:
609  if (!std::isdigit(static_cast<unsigned char>(*it)))
610  return false;
611  else
612  state = State::MANTISSA_DIGITS;
613  break;
614  case State::MANTISSA_DIGITS:
615  if (*it=='f' || *it=='F')
616  state = State::SUFFIX_F;
617  else if (*it=='l' || *it=='L')
618  state = State::SUFFIX_L;
619  else if (!std::isdigit(static_cast<unsigned char>(*it)))
620  return false;
621  break;
622  // Ensure at least one post _ char for user defined literals
623  case State::SUFFIX_LITERAL:
624  case State::SUFFIX_LITERAL_LEADER:
625  state = State::SUFFIX_LITERAL;
626  break;
627  case State::SUFFIX_F:
628  return false;
629  case State::SUFFIX_L:
630  return false;
631  }
632  }
633  return (state==State::BASE_DIGITS2 || state==State::MANTISSA_DIGITS || state==State::TRAILING_DECIMAL || state==State::SUFFIX_F || state==State::SUFFIX_L || (state==State::SUFFIX_LITERAL));
634 }
635 
636 bool MathLib::isNegative(const std::string &str)
637 {
638  if (str.empty())
639  return false;
640  return (str[0] == '-');
641 }
642 
643 bool MathLib::isPositive(const std::string &str)
644 {
645  if (str.empty())
646  return false;
647  return !MathLib::isNegative(str);
648 }
649 
650 static bool isValidIntegerSuffixIt(std::string::const_iterator it, std::string::const_iterator end, bool supportMicrosoftExtensions=true)
651 {
652  enum class Status { START, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_UZ, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU, SUFFIX_I, SUFFIX_I6, SUFFIX_I64, SUFFIX_UI, SUFFIX_UI6, SUFFIX_UI64, SUFFIX_Z, SUFFIX_LITERAL_LEADER, SUFFIX_LITERAL } state = Status::START;
653  for (; it != end; ++it) {
654  switch (state) {
655  case Status::START:
656  if (*it == 'u' || *it == 'U')
657  state = Status::SUFFIX_U;
658  else if (*it == 'l' || *it == 'L')
659  state = Status::SUFFIX_L;
660  else if (*it == 'z' || *it == 'Z')
661  state = Status::SUFFIX_Z;
662  else if (supportMicrosoftExtensions && (*it == 'i' || *it == 'I'))
663  state = Status::SUFFIX_I;
664  else if (*it == '_')
665  state = Status::SUFFIX_LITERAL_LEADER;
666  else
667  return false;
668  break;
669  case Status::SUFFIX_U:
670  if (*it == 'l' || *it == 'L')
671  state = Status::SUFFIX_UL; // UL
672  else if (*it == 'z' || *it == 'Z')
673  state = Status::SUFFIX_UZ; // UZ
674  else if (supportMicrosoftExtensions && (*it == 'i' || *it == 'I'))
675  state = Status::SUFFIX_UI;
676  else
677  return false;
678  break;
679  case Status::SUFFIX_UL:
680  if (*it == 'l' || *it == 'L')
681  state = Status::SUFFIX_ULL; // ULL
682  else
683  return false;
684  break;
685  case Status::SUFFIX_L:
686  if (*it == 'u' || *it == 'U')
687  state = Status::SUFFIX_LU; // LU
688  else if (*it == 'l' || *it == 'L')
689  state = Status::SUFFIX_LL; // LL
690  else
691  return false;
692  break;
693  case Status::SUFFIX_LU:
694  return false;
695  case Status::SUFFIX_LL:
696  if (*it == 'u' || *it == 'U')
697  state = Status::SUFFIX_LLU; // LLU
698  else
699  return false;
700  break;
701  case Status::SUFFIX_I:
702  if (*it == '6')
703  state = Status::SUFFIX_I6;
704  else
705  return false;
706  break;
707  case Status::SUFFIX_I6:
708  if (*it == '4')
709  state = Status::SUFFIX_I64;
710  else
711  return false;
712  break;
713  case Status::SUFFIX_UI:
714  if (*it == '6')
715  state = Status::SUFFIX_UI6;
716  else
717  return false;
718  break;
719  case Status::SUFFIX_UI6:
720  if (*it == '4')
721  state = Status::SUFFIX_UI64;
722  else
723  return false;
724  break;
725  case Status::SUFFIX_Z:
726  if (*it == 'u' || *it == 'U')
727  state = Status::SUFFIX_UZ;
728  else
729  return false;
730  break;
731  // Ensure at least one post _ char for user defined literals
732  case Status::SUFFIX_LITERAL:
733  case Status::SUFFIX_LITERAL_LEADER:
734  state = Status::SUFFIX_LITERAL;
735  break;
736  default:
737  return false;
738  }
739  }
740  return ((state == Status::SUFFIX_U) ||
741  (state == Status::SUFFIX_L) ||
742  (state == Status::SUFFIX_Z) ||
743  (state == Status::SUFFIX_UL) ||
744  (state == Status::SUFFIX_UZ) ||
745  (state == Status::SUFFIX_LU) ||
746  (state == Status::SUFFIX_LL) ||
747  (state == Status::SUFFIX_ULL) ||
748  (state == Status::SUFFIX_LLU) ||
749  (state == Status::SUFFIX_I64) ||
750  (state == Status::SUFFIX_UI64) ||
751  (state == Status::SUFFIX_LITERAL));
752 }
753 
754 // cppcheck-suppress unusedFunction
755 bool MathLib::isValidIntegerSuffix(const std::string& str, bool supportMicrosoftExtensions)
756 {
757  return isValidIntegerSuffixIt(str.cbegin(), str.cend(), supportMicrosoftExtensions);
758 }
759 
760 
761 
762 /*! \brief Does the string represent an octal number?
763  * In case leading or trailing white space is provided, the function
764  * returns false.
765  * Additional information can be found here:
766  * http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html
767  *
768  * \param str The string to check. In case the string is empty, the function returns false.
769  * \return Return true in case a octal number is provided and false otherwise.
770  **/
771 bool MathLib::isOct(const std::string& str)
772 {
773  enum class Status {
774  START, OCTAL_PREFIX, DIGITS
775  } state = Status::START;
776  if (str.empty())
777  return false;
778  std::string::const_iterator it = str.cbegin();
779  if ('+' == *it || '-' == *it)
780  ++it;
781  for (; it != str.cend(); ++it) {
782  switch (state) {
783  case Status::START:
784  if (*it == '0')
785  state = Status::OCTAL_PREFIX;
786  else
787  return false;
788  break;
789  case Status::OCTAL_PREFIX:
790  if (isOctalDigit(static_cast<unsigned char>(*it)))
791  state = Status::DIGITS;
792  else
793  return false;
794  break;
795  case Status::DIGITS:
796  if (isOctalDigit(static_cast<unsigned char>(*it)))
797  state = Status::DIGITS;
798  else
799  return isValidIntegerSuffixIt(it,str.end());
800  break;
801  }
802  }
803  return state == Status::DIGITS;
804 }
805 
806 bool MathLib::isIntHex(const std::string& str)
807 {
808  enum class Status {
809  START, HEX_0, HEX_X, DIGIT
810  } state = Status::START;
811  if (str.empty())
812  return false;
813  std::string::const_iterator it = str.cbegin();
814  if ('+' == *it || '-' == *it)
815  ++it;
816  for (; it != str.cend(); ++it) {
817  switch (state) {
818  case Status::START:
819  if (*it == '0')
820  state = Status::HEX_0;
821  else
822  return false;
823  break;
824  case Status::HEX_0:
825  if (*it == 'x' || *it == 'X')
826  state = Status::HEX_X;
827  else
828  return false;
829  break;
830  case Status::HEX_X:
831  if (isxdigit(static_cast<unsigned char>(*it)))
832  state = Status::DIGIT;
833  else
834  return false;
835  break;
836  case Status::DIGIT:
837  if (isxdigit(static_cast<unsigned char>(*it)))
838  ; // state = Status::DIGIT;
839  else
840  return isValidIntegerSuffixIt(it,str.end());
841  break;
842  }
843  }
844  return Status::DIGIT == state;
845 }
846 
847 bool MathLib::isFloatHex(const std::string& str)
848 {
849  enum class Status {
850  START, HEX_0, HEX_X, WHOLE_NUMBER_DIGIT, POINT, FRACTION, EXPONENT_P, EXPONENT_SIGN, EXPONENT_DIGITS, EXPONENT_SUFFIX
851  } state = Status::START;
852  if (str.empty())
853  return false;
854  std::string::const_iterator it = str.cbegin();
855  if ('+' == *it || '-' == *it)
856  ++it;
857  for (; it != str.cend(); ++it) {
858  switch (state) {
859  case Status::START:
860  if (*it == '0')
861  state = Status::HEX_0;
862  else
863  return false;
864  break;
865  case Status::HEX_0:
866  if (*it == 'x' || *it == 'X')
867  state = Status::HEX_X;
868  else
869  return false;
870  break;
871  case Status::HEX_X:
872  if (isxdigit(static_cast<unsigned char>(*it)))
873  state = Status::WHOLE_NUMBER_DIGIT;
874  else if (*it == '.')
875  state = Status::POINT;
876  else
877  return false;
878  break;
879  case Status::WHOLE_NUMBER_DIGIT:
880  if (isxdigit(static_cast<unsigned char>(*it)))
881  ; // state = Status::WHOLE_NUMBER_DIGITS;
882  else if (*it=='.')
883  state = Status::FRACTION;
884  else if (*it=='p' || *it=='P')
885  state = Status::EXPONENT_P;
886  else
887  return false;
888  break;
889  case Status::POINT:
890  case Status::FRACTION:
891  if (isxdigit(static_cast<unsigned char>(*it)))
892  state = Status::FRACTION;
893  else if (*it == 'p' || *it == 'P')
894  state = Status::EXPONENT_P;
895  else
896  return false;
897  break;
898  case Status::EXPONENT_P:
899  if (isdigit(static_cast<unsigned char>(*it)))
900  state = Status::EXPONENT_DIGITS;
901  else if (*it == '+' || *it == '-')
902  state = Status::EXPONENT_SIGN;
903  else
904  return false;
905  break;
906  case Status::EXPONENT_SIGN:
907  if (isdigit(static_cast<unsigned char>(*it)))
908  state = Status::EXPONENT_DIGITS;
909  else
910  return false;
911  break;
912  case Status::EXPONENT_DIGITS:
913  if (isdigit(static_cast<unsigned char>(*it)))
914  ; // state = Status::EXPONENT_DIGITS;
915  else if (*it == 'f' || *it == 'F' || *it == 'l' || *it == 'L')
916  state = Status::EXPONENT_SUFFIX;
917  else
918  return false;
919  break;
920  case Status::EXPONENT_SUFFIX:
921  return false;
922  }
923  }
924  return (Status::EXPONENT_DIGITS == state) || (Status::EXPONENT_SUFFIX == state);
925 }
926 
927 
928 /*! \brief Does the string represent a binary number?
929  * In case leading or trailing white space is provided, the function
930  * returns false.
931  * Additional information can be found here:
932  * http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html
933  *
934  * \param str The string to check. In case the string is empty, the function returns false.
935  * \return Return true in case a binary number is provided and false otherwise.
936  **/
937 bool MathLib::isBin(const std::string& str)
938 {
939  enum class Status {
940  START, GNU_BIN_PREFIX_0, GNU_BIN_PREFIX_B, DIGIT
941  } state = Status::START;
942  if (str.empty())
943  return false;
944  std::string::const_iterator it = str.cbegin();
945  if ('+' == *it || '-' == *it)
946  ++it;
947  for (; it != str.cend(); ++it) {
948  switch (state) {
949  case Status::START:
950  if (*it == '0')
951  state = Status::GNU_BIN_PREFIX_0;
952  else
953  return false;
954  break;
955  case Status::GNU_BIN_PREFIX_0:
956  if (*it == 'b' || *it == 'B')
957  state = Status::GNU_BIN_PREFIX_B;
958  else
959  return false;
960  break;
961  case Status::GNU_BIN_PREFIX_B:
962  if (*it == '0' || *it == '1')
963  state = Status::DIGIT;
964  else
965  return false;
966  break;
967  case Status::DIGIT:
968  if (*it == '0' || *it == '1')
969  ; // state = Status::DIGIT;
970  else
971  return isValidIntegerSuffixIt(it,str.end());
972  break;
973  }
974  }
975  return state == Status::DIGIT;
976 }
977 
978 bool MathLib::isDec(const std::string & str)
979 {
980  enum class Status {
981  START, DIGIT
982  } state = Status::START;
983  if (str.empty())
984  return false;
985  std::string::const_iterator it = str.cbegin();
986  if ('+' == *it || '-' == *it)
987  ++it;
988  for (; it != str.cend(); ++it) {
989  switch (state) {
990  case Status::START:
991  if (isdigit(static_cast<unsigned char>(*it)))
992  state = Status::DIGIT;
993  else
994  return false;
995  break;
996  case Status::DIGIT:
997  if (isdigit(static_cast<unsigned char>(*it)))
998  state = Status::DIGIT;
999  else
1000  return isValidIntegerSuffixIt(it,str.end());
1001  break;
1002  }
1003  }
1004  return state == Status::DIGIT;
1005 }
1006 
1007 bool MathLib::isInt(const std::string & str)
1008 {
1009  return isDec(str) || isIntHex(str) || isOct(str) || isBin(str);
1010 }
1011 
1012 std::string MathLib::getSuffix(const std::string& value)
1013 {
1014  if (value.size() > 3 && value[value.size() - 3] == 'i' && value[value.size() - 2] == '6' && value[value.size() - 1] == '4') {
1015  if (value[value.size() - 4] == 'u')
1016  return "ULL";
1017  return "LL";
1018  }
1019  bool isUnsigned = false;
1020  unsigned int longState = 0;
1021  for (std::size_t i = 1U; i < value.size(); ++i) {
1022  const char c = value[value.size() - i];
1023  if (c == 'u' || c == 'U')
1024  isUnsigned = true;
1025  else if (c == 'L' || c == 'l')
1026  longState++;
1027  else break;
1028  }
1029  if (longState == 0)
1030  return isUnsigned ? "U" : "";
1031  if (longState == 1)
1032  return isUnsigned ? "UL" : "L";
1033  if (longState == 2)
1034  return isUnsigned ? "ULL" : "LL";
1035  return "";
1036 }
1037 
1038 static std::string intsuffix(const std::string & first, const std::string & second)
1039 {
1040  const std::string suffix1 = MathLib::getSuffix(first);
1041  const std::string suffix2 = MathLib::getSuffix(second);
1042  if (suffix1 == "ULL" || suffix2 == "ULL")
1043  return "ULL";
1044  if (suffix1 == "LL" || suffix2 == "LL")
1045  return "LL";
1046  if (suffix1 == "UL" || suffix2 == "UL")
1047  return "UL";
1048  if (suffix1 == "L" || suffix2 == "L")
1049  return "L";
1050  if (suffix1 == "U" || suffix2 == "U")
1051  return "U";
1052 
1053  return suffix1.empty() ? suffix2 : suffix1;
1054 }
1055 
1056 std::string MathLib::add(const std::string & first, const std::string & second)
1057 {
1058 #ifdef TEST_MATHLIB_VALUE
1059  return (value(first) + value(second)).str();
1060 #else
1061  if (MathLib::isInt(first) && MathLib::isInt(second)) {
1062  return std::to_string(toBigNumber(first) + toBigNumber(second)) + intsuffix(first, second);
1063  }
1064 
1065  double d1 = toDoubleNumber(first);
1066  double d2 = toDoubleNumber(second);
1067 
1068  int count = 0;
1069  while (d1 > 100000.0 * d2 && toString(d1+d2)==first && ++count<5)
1070  d2 *= 10.0;
1071  while (d2 > 100000.0 * d1 && toString(d1+d2)==second && ++count<5)
1072  d1 *= 10.0;
1073 
1074  return toString(d1 + d2);
1075 #endif
1076 }
1077 
1078 std::string MathLib::subtract(const std::string &first, const std::string &second)
1079 {
1080 #ifdef TEST_MATHLIB_VALUE
1081  return (value(first) - value(second)).str();
1082 #else
1083  if (MathLib::isInt(first) && MathLib::isInt(second)) {
1084  return std::to_string(toBigNumber(first) - toBigNumber(second)) + intsuffix(first, second);
1085  }
1086 
1087  if (first == second)
1088  return "0.0";
1089 
1090  double d1 = toDoubleNumber(first);
1091  double d2 = toDoubleNumber(second);
1092 
1093  int count = 0;
1094  while (d1 > 100000.0 * d2 && toString(d1-d2)==first && ++count<5)
1095  d2 *= 10.0;
1096  while (d2 > 100000.0 * d1 && toString(d1-d2)==second && ++count<5)
1097  d1 *= 10.0;
1098 
1099  return toString(d1 - d2);
1100 #endif
1101 }
1102 
1103 std::string MathLib::divide(const std::string &first, const std::string &second)
1104 {
1105 #ifdef TEST_MATHLIB_VALUE
1106  return (value(first) / value(second)).str();
1107 #else
1108  if (MathLib::isInt(first) && MathLib::isInt(second)) {
1109  const bigint a = toBigNumber(first);
1110  const bigint b = toBigNumber(second);
1111  if (b == 0)
1112  throw InternalError(nullptr, "Internal Error: Division by zero");
1113  if (a == std::numeric_limits<bigint>::min() && std::abs(b)<=1)
1114  throw InternalError(nullptr, "Internal Error: Division overflow");
1115  return std::to_string(toBigNumber(first) / b) + intsuffix(first, second);
1116  }
1117  if (isNullValue(second)) {
1118  if (isNullValue(first))
1119  return "nan.0";
1120  return isPositive(first) == isPositive(second) ? "inf.0" : "-inf.0";
1121  }
1122  return toString(toDoubleNumber(first) / toDoubleNumber(second));
1123 #endif
1124 }
1125 
1126 std::string MathLib::multiply(const std::string &first, const std::string &second)
1127 {
1128 #ifdef TEST_MATHLIB_VALUE
1129  return (value(first) * value(second)).str();
1130 #else
1131  if (MathLib::isInt(first) && MathLib::isInt(second)) {
1132  return std::to_string(toBigNumber(first) * toBigNumber(second)) + intsuffix(first, second);
1133  }
1134  return toString(toDoubleNumber(first) * toDoubleNumber(second));
1135 #endif
1136 }
1137 
1138 std::string MathLib::mod(const std::string &first, const std::string &second)
1139 {
1140 #ifdef TEST_MATHLIB_VALUE
1141  return (value(first) % value(second)).str();
1142 #else
1143  if (MathLib::isInt(first) && MathLib::isInt(second)) {
1144  const bigint b = toBigNumber(second);
1145  if (b == 0)
1146  throw InternalError(nullptr, "Internal Error: Division by zero");
1147  return std::to_string(toBigNumber(first) % b) + intsuffix(first, second);
1148  }
1149  return toString(std::fmod(toDoubleNumber(first),toDoubleNumber(second)));
1150 #endif
1151 }
1152 
1153 std::string MathLib::calculate(const std::string &first, const std::string &second, char action)
1154 {
1155  switch (action) {
1156  case '+':
1157  return MathLib::add(first, second);
1158 
1159  case '-':
1160  return MathLib::subtract(first, second);
1161 
1162  case '*':
1163  return MathLib::multiply(first, second);
1164 
1165  case '/':
1166  return MathLib::divide(first, second);
1167 
1168  case '%':
1169  return MathLib::mod(first, second);
1170 
1171  case '&':
1172  return std::to_string(MathLib::toBigNumber(first) & MathLib::toBigNumber(second)) + intsuffix(first, second);
1173 
1174  case '|':
1175  return std::to_string(MathLib::toBigNumber(first) | MathLib::toBigNumber(second)) + intsuffix(first, second);
1176 
1177  case '^':
1178  return std::to_string(MathLib::toBigNumber(first) ^ MathLib::toBigNumber(second)) + intsuffix(first, second);
1179 
1180  default:
1181  throw InternalError(nullptr, std::string("Unexpected action '") + action + "' in MathLib::calculate(). Please report this to Cppcheck developers.");
1182  }
1183 }
1184 
1185 std::string MathLib::sin(const std::string &tok)
1186 {
1187  return toString(std::sin(toDoubleNumber(tok)));
1188 }
1189 
1190 
1191 std::string MathLib::cos(const std::string &tok)
1192 {
1193  return toString(std::cos(toDoubleNumber(tok)));
1194 }
1195 
1196 std::string MathLib::tan(const std::string &tok)
1197 {
1198  return toString(std::tan(toDoubleNumber(tok)));
1199 }
1200 
1201 
1202 std::string MathLib::abs(const std::string &tok)
1203 {
1204  if (isNegative(tok))
1205  return tok.substr(1, tok.length() - 1);
1206  return tok;
1207 }
1208 
1209 bool MathLib::isEqual(const std::string &first, const std::string &second)
1210 {
1211  // this conversion is needed for formatting
1212  // e.g. if first=0.1 and second=1.0E-1, the direct comparison of the strings would fail
1213  return toString(toDoubleNumber(first)) == toString(toDoubleNumber(second));
1214 }
1215 
1216 bool MathLib::isNotEqual(const std::string &first, const std::string &second)
1217 {
1218  return !isEqual(first, second);
1219 }
1220 
1221 // cppcheck-suppress unusedFunction
1222 bool MathLib::isGreater(const std::string &first, const std::string &second)
1223 {
1224  return toDoubleNumber(first) > toDoubleNumber(second);
1225 }
1226 
1227 // cppcheck-suppress unusedFunction
1228 bool MathLib::isGreaterEqual(const std::string &first, const std::string &second)
1229 {
1230  return toDoubleNumber(first) >= toDoubleNumber(second);
1231 }
1232 
1233 // cppcheck-suppress unusedFunction
1234 bool MathLib::isLess(const std::string &first, const std::string &second)
1235 {
1236  return toDoubleNumber(first) < toDoubleNumber(second);
1237 }
1238 
1239 bool MathLib::isLessEqual(const std::string &first, const std::string &second)
1240 {
1241  return toDoubleNumber(first) <= toDoubleNumber(second);
1242 }
1243 
1244 /*! \brief Does the string represent the numerical value of 0?
1245  * In case leading or trailing white space is provided, the function
1246  * returns false.
1247  * Requirement for this function:
1248  * - This code is allowed to be slow because of simplicity of the code.
1249  *
1250  * \param[in] str The string to check. In case the string is empty, the function returns false.
1251  * \return Return true in case the string represents a numerical null value.
1252  **/
1253 bool MathLib::isNullValue(const std::string &str)
1254 {
1255  if (str.empty() || (!std::isdigit(static_cast<unsigned char>(str[0])) && (str[0] != '.' && str[0] != '-' && str[0] != '+')))
1256  return false; // Has to be a number
1257 
1258  if (!isInt(str) && !isFloat(str))
1259  return false;
1260  const bool isHex = isIntHex(str) || isFloatHex(str);
1261  for (const char i : str) {
1262  if (std::isdigit(static_cast<unsigned char>(i)) && i != '0') // May not contain digits other than 0
1263  return false;
1264  if (i == 'p' || i == 'P' || (!isHex && (i == 'E' || i == 'e')))
1265  return true;
1266  if (isHex && isxdigit(i) && i != '0')
1267  return false;
1268  }
1269  return true;
1270 }
1271 
1273 {
1274  return (c >= '0' && c <= '7');
1275 }
1276 
1277 bool MathLib::isDigitSeparator(const std::string& iCode, std::string::size_type iPos)
1278 {
1279  if (iPos == 0 || iPos >= iCode.size() || iCode[iPos] != '\'')
1280  return false;
1281  std::string::size_type i = iPos - 1;
1282  while (std::isxdigit(iCode[i])) {
1283  if (i == 0)
1284  return true; // Only xdigits before '
1285  --i;
1286  }
1287  if (i == iPos - 1) // No xdigit before '
1288  return false;
1289 
1290  switch (iCode[i]) {
1291  case ' ':
1292  case '.':
1293  case ',':
1294  case 'x':
1295  case '(':
1296  case '{':
1297  case '+':
1298  case '-':
1299  case '*':
1300  case '%':
1301  case '/':
1302  case '&':
1303  case '|':
1304  case '^':
1305  case '~':
1306  case '=':
1307  return true;
1308  case '\'':
1309  return isDigitSeparator(iCode, i);
1310  default:
1311  return false;
1312  }
1313 }
1314 
1316 {
1317  return MathLib::value::calc('+',v1,v2);
1318 }
1319 
1321 {
1322  return MathLib::value::calc('-',v1,v2);
1323 }
1324 
1326 {
1327  return MathLib::value::calc('*',v1,v2);
1328 }
1329 
1331 {
1332  return MathLib::value::calc('/',v1,v2);
1333 }
1334 
1336 {
1337  return MathLib::value::calc('%',v1,v2);
1338 }
1339 
1341 {
1342  return MathLib::value::calc('&',v1,v2);
1343 }
1344 
1346 {
1347  return MathLib::value::calc('|',v1,v2);
1348 }
1349 
1351 {
1352  return MathLib::value::calc('^',v1,v2);
1353 }
1354 
1356 {
1357  return v1.shiftLeft(v2);
1358 }
1359 
1361 {
1362  return v1.shiftRight(v2);
1363 }
value class
Definition: mathlib.h:38
enum MathLib::value::Type mType
value shiftLeft(const value &v) const
Definition: mathlib.cpp:264
bool mIsUnsigned
Definition: mathlib.h:43
value shiftRight(const value &v) const
Definition: mathlib.cpp:276
bool isInt() const
Definition: mathlib.h:50
int compare(const value &v) const
Definition: mathlib.cpp:226
std::string str() const
Definition: mathlib.cpp:74
value(const std::string &s)
Definition: mathlib.cpp:40
void promote(const value &v)
Definition: mathlib.cpp:108
bool isFloat() const
Definition: mathlib.h:53
long long mIntValue
Definition: mathlib.h:40
value add(int v) const
Definition: mathlib.cpp:254
double getDoubleValue() const
Definition: mathlib.h:57
static value calc(char op, const value &v1, const value &v2)
Definition: mathlib.cpp:125
double mDoubleValue
Definition: mathlib.h:41
static bool isValidIntegerSuffix(const std::string &str, bool supportMicrosoftExtensions=true)
Only used in unit tests.
Definition: mathlib.cpp:755
static std::string toString(T value)=delete
static biguint toBigUNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
Definition: mathlib.cpp:289
static bool isLessEqual(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1239
static std::string divide(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1103
static bool isDigitSeparator(const std::string &iCode, std::string::size_type iPos)
Definition: mathlib.cpp:1277
static bool isOct(const std::string &str)
Does the string represent an octal number? In case leading or trailing white space is provided,...
Definition: mathlib.cpp:771
static bool isEqual(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1209
static std::string sin(const std::string &tok)
Definition: mathlib.cpp:1185
long long bigint
Definition: mathlib.h:68
static bool isGreaterEqual(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1228
static const int bigint_bits
Definition: mathlib.h:70
static bool isOctalDigit(char c)
Return true if given character is 0,1,2,3,4,5,6 or 7.
Definition: mathlib.cpp:1272
static bool isNotEqual(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1216
static std::string subtract(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1078
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
Definition: mathlib.cpp:368
static std::string calculate(const std::string &first, const std::string &second, char action)
Definition: mathlib.cpp:1153
static std::string cos(const std::string &tok)
Definition: mathlib.cpp:1191
static bool isDecimalFloat(const std::string &str)
Definition: mathlib.cpp:540
static bool isGreater(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1222
static bool isFloat(const std::string &str)
Definition: mathlib.cpp:535
static unsigned int encodeMultiChar(const std::string &str)
Definition: mathlib.cpp:360
static bool isDec(const std::string &str)
Definition: mathlib.cpp:978
static bool isBin(const std::string &str)
Does the string represent a binary number? In case leading or trailing white space is provided,...
Definition: mathlib.cpp:937
static std::string mod(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1138
static std::string add(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1056
static bool isIntHex(const std::string &str)
Definition: mathlib.cpp:806
static bool isNullValue(const std::string &str)
Does the string represent the numerical value of 0? In case leading or trailing white space is provid...
Definition: mathlib.cpp:1253
static std::string abs(const std::string &tok)
Definition: mathlib.cpp:1202
static bool isNegative(const std::string &str)
Definition: mathlib.cpp:636
static bool isFloatHex(const std::string &str)
Definition: mathlib.cpp:847
static bool isInt(const std::string &str)
Definition: mathlib.cpp:1007
static bool isLess(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1234
static std::string multiply(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1126
static double toDoubleNumber(const std::string &str)
for conversion of numeric literals
Definition: mathlib.cpp:487
unsigned long long biguint
Definition: mathlib.h:69
static std::string tan(const std::string &tok)
Definition: mathlib.cpp:1196
static bool isPositive(const std::string &str)
Definition: mathlib.cpp:643
static std::string getSuffix(const std::string &value)
Definition: mathlib.cpp:1012
MathLib::value operator&(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1340
MathLib::value operator%(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1335
MathLib::value operator-(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1320
MathLib::value operator|(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1345
MathLib::value operator<<(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1355
MathLib::value operator>>(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1360
MathLib::value operator*(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1325
MathLib::value operator/(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1330
MathLib::value operator^(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1350
MathLib::value operator+(const MathLib::value &v1, const MathLib::value &v2)
Definition: mathlib.cpp:1315
static double myStod(const std::string &str, std::string::const_iterator from, std::string::const_iterator to, int base)
Definition: mathlib.cpp:441
static std::string intsuffix(const std::string &first, const std::string &second)
Definition: mathlib.cpp:1038
static double floatHexToDoubleNumber(const std::string &str)
Definition: mathlib.cpp:477
static bool isValidIntegerSuffixIt(std::string::const_iterator it, std::string::const_iterator end, bool supportMicrosoftExtensions=true)
Definition: mathlib.cpp:650
Simple container to be thrown when internal error is detected.
Definition: errortypes.h:36
static bool isCharLiteral(const std::string &str)
Definition: utils.h:164