diff --git a/src/core/math/extern/exprtk.h b/src/core/math/extern/exprtk.h index 4c88bbdf6b501ccd95726cab45b0000597e49e49..afa862bf11b3a28de2c44bd6145cd09842137f50 100644 --- a/src/core/math/extern/exprtk.h +++ b/src/core/math/extern/exprtk.h @@ -2,7 +2,7 @@ ****************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Author: Arash Partow (1999-2019) * + * Author: Arash Partow (1999-2021) * * URL: http://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -35,6 +35,7 @@ #include <algorithm> +#include <cassert> #include <cctype> #include <cmath> #include <complex> @@ -83,12 +84,14 @@ namespace exprtk namespace details { - typedef unsigned char uchar_t; - typedef char char_t; - typedef uchar_t* uchar_ptr; - typedef char_t* char_ptr; - typedef uchar_t const* uchar_cptr; - typedef char_t const* char_cptr; + typedef unsigned char uchar_t; + typedef char char_t; + typedef uchar_t* uchar_ptr; + typedef char_t* char_ptr; + typedef uchar_t const* uchar_cptr; + typedef char_t const* char_cptr; + typedef unsigned long long int _uint64_t; + typedef long long int _int64_t; inline bool is_whitespace(const char_t c) { @@ -162,6 +165,12 @@ namespace exprtk ('\'' != c); } + inline bool is_valid_string_char(const char_t c) + { + return std::isprint(static_cast<unsigned char>(c)) || + is_whitespace(c); + } + #ifndef exprtk_disable_caseinsensitivity inline void case_normalise(std::string& s) { @@ -308,31 +317,30 @@ namespace exprtk } template <typename Iterator> - inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result) + inline bool parse_hex(Iterator& itr, Iterator end, + std::string::value_type& result) { if ( - (end != (itr )) && - (end != (itr + 1)) && - (end != (itr + 2)) && - (end != (itr + 3)) && - ('0' == *(itr )) && - ( - ('x' == *(itr + 1)) || - ('X' == *(itr + 1)) - ) && - (is_hex_digit(*(itr + 2))) && - (is_hex_digit(*(itr + 3))) + (end == (itr )) || + (end == (itr + 1)) || + (end == (itr + 2)) || + (end == (itr + 3)) || + ('0' != *(itr )) || + ('X' != std::toupper(*(itr + 1))) || + (!is_hex_digit(*(itr + 2))) || + (!is_hex_digit(*(itr + 3))) ) { - result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | - hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ; - itr += 3; + return false; } - else - result = '\0'; + + result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | + hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ; + + return true; } - inline void cleanup_escapes(std::string& s) + inline bool cleanup_escapes(std::string& s) { typedef std::string::iterator str_itr_t; @@ -346,36 +354,41 @@ namespace exprtk { if ('\\' == (*itr1)) { - ++removal_count; - if (end == ++itr1) - break; - else if ('\\' != (*itr1)) { - switch (*itr1) - { - case 'n' : (*itr1) = '\n'; break; - case 'r' : (*itr1) = '\r'; break; - case 't' : (*itr1) = '\t'; break; - case '0' : parse_hex(itr1, end, (*itr1)); - removal_count += 3; - break; - } - - continue; + return false; } + else if (parse_hex(itr1, end, *itr2)) + { + itr1+= 4; + itr2+= 1; + removal_count +=4; + } + else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } + else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } + else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } + else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } + else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } + else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } + else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } + else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } + else + { + (*itr2++) = (*itr1++); + ++removal_count; + } + continue; } - - if (itr1 != itr2) - { - (*itr2) = (*itr1); - } - - ++itr1; - ++itr2; + else + (*itr2++) = (*itr1++); } + if ((removal_count > s.size()) || (0 == removal_count)) + return false; + s.resize(s.size() - removal_count); + + return true; } class build_string @@ -643,23 +656,19 @@ namespace exprtk inline bool wc_match(const std::string& wild_card, const std::string& str) { - return match_impl<char_cptr,cs_match>(wild_card.data(), - wild_card.data() + wild_card.size(), - str.data(), - str.data() + str.size(), - '*', - '?'); + return match_impl<char_cptr,cs_match>( + wild_card.data(), wild_card.data() + wild_card.size(), + str.data(), str.data() + str.size(), + '*', '?'); } inline bool wc_imatch(const std::string& wild_card, const std::string& str) { - return match_impl<char_cptr,cis_match>(wild_card.data(), - wild_card.data() + wild_card.size(), - str.data(), - str.data() + str.size(), - '*', - '?'); + return match_impl<char_cptr,cis_match>( + wild_card.data(), wild_card.data() + wild_card.size(), + str.data(), str.data() + str.size(), + '*', '?'); } inline bool sequence_match(const std::string& pattern, @@ -773,15 +782,15 @@ namespace exprtk }; #define exprtk_register_real_type_tag(T) \ - template<> struct number_type<T> \ + template <> struct number_type<T> \ { typedef real_type_tag type; number_type() {} }; \ #define exprtk_register_complex_type_tag(T) \ - template<> struct number_type<std::complex<T> > \ + template <> struct number_type<std::complex<T> > \ { typedef complex_type_tag type; number_type() {} }; \ #define exprtk_register_int_type_tag(T) \ - template<> struct number_type<T> \ + template <> struct number_type<T> \ { typedef int_type_tag type; number_type() {} }; \ exprtk_register_real_type_tag(double ) @@ -792,12 +801,12 @@ namespace exprtk exprtk_register_complex_type_tag(long double) exprtk_register_complex_type_tag(float ) - exprtk_register_int_type_tag(short ) - exprtk_register_int_type_tag(int ) - exprtk_register_int_type_tag(long long int ) - exprtk_register_int_type_tag(unsigned short ) - exprtk_register_int_type_tag(unsigned int ) - exprtk_register_int_type_tag(unsigned long long int) + exprtk_register_int_type_tag(short ) + exprtk_register_int_type_tag(int ) + exprtk_register_int_type_tag(_int64_t ) + exprtk_register_int_type_tag(unsigned short) + exprtk_register_int_type_tag(unsigned int ) + exprtk_register_int_type_tag(_uint64_t ) #undef exprtk_register_real_type_tag #undef exprtk_register_int_type_tag @@ -827,7 +836,7 @@ namespace exprtk { static inline long double value() { - const long double epsilon = (long double)(0.000000000001); + const long double epsilon = static_cast<long double>(0.000000000001); return epsilon; } }; @@ -845,9 +854,9 @@ namespace exprtk } template <typename T> - inline long long int to_int64_impl(const T v, real_type_tag) + inline _int64_t to_int64_impl(const T v, real_type_tag) { - return static_cast<long long int>(v); + return static_cast<_int64_t>(v); } template <typename T> @@ -1028,7 +1037,7 @@ namespace exprtk template <typename T> inline T roundn_impl(const T v0, const T v1, real_type_tag) { - const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1))); + const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1)))); const T p10 = T(pow10[index]); if (v0 < T(0)) @@ -1372,10 +1381,10 @@ namespace exprtk template <typename Type> struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; - template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; }; - template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; }; - template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; }; - template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; }; + template <> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; }; + template <> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; }; + template <> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; }; + template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; }; template <typename T> inline int to_int32(const T v) @@ -1385,7 +1394,7 @@ namespace exprtk } template <typename T> - inline long long int to_int64(const T v) + inline _int64_t to_int64(const T v) { const typename details::number_type<T>::type num_type; return to_int64_impl(v, num_type); @@ -1827,6 +1836,13 @@ namespace exprtk return true; } + template <typename T> + inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) + { + return (std::numeric_limits<T>::min_exponent10 <= exponent) && + (exponent <= std::numeric_limits<T>::max_exponent10) ; + } + template <typename Iterator, typename T> inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) { @@ -1867,12 +1883,12 @@ namespace exprtk while ((end != itr) && (zero == (*itr))) ++itr; - unsigned int digit; - while (end != itr) { // Note: For 'physical' superscalar architectures it // is advised that the following loop be: 4xPD1 and 1xPD2 + unsigned int digit; + #ifdef exprtk_enable_superscalar parse_digit_1(d) parse_digit_1(d) @@ -1892,11 +1908,12 @@ namespace exprtk if ('.' == (*itr)) { const Iterator curr = ++itr; - unsigned int digit; T tmp_d = T(0); while (end != itr) { + unsigned int digit; + #ifdef exprtk_enable_superscalar parse_digit_1(tmp_d) parse_digit_1(tmp_d) @@ -1910,7 +1927,13 @@ namespace exprtk if (curr != itr) { instate = true; - d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr))); + + const int exponent = static_cast<int>(-std::distance(curr, itr)); + + if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) + return false; + + d += compute_pow10(tmp_d, exponent); } #undef parse_digit_1 @@ -1981,6 +2004,8 @@ namespace exprtk if ((end != itr) || (!instate)) return false; + else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) + return false; else if (exponent) d = compute_pow10(d,exponent); @@ -2019,6 +2044,50 @@ namespace exprtk } // namespace details + struct loop_runtime_check + { + enum loop_types + { + e_invalid = 0, + e_for_loop = 1, + e_while_loop = 2, + e_repeat_until_loop = 4, + e_all_loops = 7 + }; + + enum violation_type + { + e_unknown = 0, + e_iteration_count = 1, + e_timeout = 2 + }; + + loop_types loop_set; + + loop_runtime_check() + : loop_set(e_invalid), + max_loop_iterations(0) + {} + + details::_uint64_t max_loop_iterations; + + struct violation_context + { + loop_types loop; + violation_type violation; + details::_uint64_t iteration_count; + }; + + virtual void handle_runtime_violation(const violation_context&) + { + throw std::runtime_error("ExprTk Loop run-time violation."); + } + + virtual ~loop_runtime_check() {} + }; + + typedef loop_runtime_check* loop_runtime_check_ptr; + namespace lexer { struct token @@ -2199,7 +2268,7 @@ namespace exprtk typedef token token_t; typedef std::vector<token_t> token_list_t; - typedef std::vector<token_t>::iterator token_list_itr_t; + typedef token_list_t::iterator token_list_itr_t; typedef details::char_t char_t; generator() @@ -2334,9 +2403,9 @@ namespace exprtk if (finished()) return ""; else if (token_list_.begin() != token_itr_) - return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_); + return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); else - return std::string(base_itr_ + token_itr_->position,s_end_); + return std::string(base_itr_ + token_itr_->position, s_end_); } private: @@ -2346,9 +2415,9 @@ namespace exprtk return (s_end_ == itr); } + #ifndef exprtk_disable_comments inline bool is_comment_start(details::char_cptr itr) { - #ifndef exprtk_disable_comments const char_t c0 = *(itr + 0); const char_t c1 = *(itr + 1); @@ -2359,9 +2428,14 @@ namespace exprtk if (('/' == c0) && ('/' == c1)) return true; if (('/' == c0) && ('*' == c1)) return true; } - #endif return false; } + #else + inline bool is_comment_start(details::char_cptr) + { + return false; + } + #endif inline void skip_whitespace() { @@ -2637,6 +2711,7 @@ namespace exprtk { t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); + return; } @@ -2715,7 +2790,10 @@ namespace exprtk // $fdd(x,x,x) = at least 11 chars if (std::distance(s_itr_,s_end_) < 11) { - t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); + t.set_error( + token::e_err_sfunc, + initial_itr, std::min(initial_itr + 11, s_end_), + base_itr_); token_list_.push_back(t); return; @@ -2728,7 +2806,10 @@ namespace exprtk (details::is_digit(*(s_itr_ + 3)))) ) { - t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); + t.set_error( + token::e_err_sfunc, + initial_itr, std::min(initial_itr + 4, s_end_), + base_itr_); token_list_.push_back(t); return; @@ -2752,6 +2833,7 @@ namespace exprtk { t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); token_list_.push_back(t); + return; } @@ -2762,7 +2844,14 @@ namespace exprtk while (!is_end(s_itr_)) { - if (!escaped && ('\\' == *s_itr_)) + if (!details::is_valid_string_char(*s_itr_)) + { + t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + else if (!escaped && ('\\' == *s_itr_)) { escaped_found = true; escaped = true; @@ -2777,28 +2866,17 @@ namespace exprtk } else if (escaped) { - if (!is_end(s_itr_) && ('0' == *(s_itr_))) + if ( + !is_end(s_itr_) && ('0' == *(s_itr_)) && + ((s_itr_ + 4) <= s_end_) + ) { - /* - Note: The following 'awkward' conditional is - due to various broken msvc compilers. - */ - #if defined(_MSC_VER) && (_MSC_VER == 1600) - const bool within_range = !is_end(s_itr_ + 2) && - !is_end(s_itr_ + 3) ; - #else - const bool within_range = !is_end(s_itr_ + 1) && - !is_end(s_itr_ + 2) && - !is_end(s_itr_ + 3) ; - #endif + const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1))); - const bool x_seperator = ('x' == *(s_itr_ + 1)) || - ('X' == *(s_itr_ + 1)) ; + const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && + details::is_hex_digit(*(s_itr_ + 3)) ; - const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && - details::is_hex_digit(*(s_itr_ + 3)) ; - - if (!within_range || !x_seperator || !both_digits) + if (!(x_seperator && both_digits)) { t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); @@ -2829,7 +2907,13 @@ namespace exprtk { std::string parsed_string(initial_itr,s_itr_); - details::cleanup_escapes(parsed_string); + if (!details::cleanup_escapes(parsed_string)) + { + t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } t.set_string( parsed_string, @@ -2845,10 +2929,10 @@ namespace exprtk private: - token_list_t token_list_; - token_list_itr_t token_itr_; - token_list_itr_t store_token_itr_; - token_t eof_token_; + token_list_t token_list_; + token_list_itr_t token_itr_; + token_list_itr_t store_token_itr_; + token_t eof_token_; details::char_cptr base_itr_; details::char_cptr s_itr_; details::char_cptr s_end_; @@ -3018,6 +3102,10 @@ namespace exprtk std::size_t changes = 0; + typedef std::pair<std::size_t, token> insert_t; + std::vector<insert_t> insert_list; + insert_list.reserve(10000); + for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) { int insert_index = -1; @@ -3041,17 +3129,36 @@ namespace exprtk break; } - typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; - if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) { - g.token_list_.insert( - g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t); - + insert_list.push_back(insert_t(i, t)); changes++; } } + if (!insert_list.empty()) + { + generator::token_list_t token_list; + + std::size_t insert_index = 0; + + for (std::size_t i = 0; i < g.token_list_.size(); ++i) + { + token_list.push_back(g.token_list_[i]); + + if ( + (insert_index < insert_list.size()) && + (insert_list[insert_index].first == i) + ) + { + token_list.push_back(insert_list[insert_index].second); + insert_index++; + } + } + + std::swap(g.token_list_,token_list); + } + return changes; } @@ -3086,7 +3193,7 @@ namespace exprtk { public: - token_joiner(const std::size_t& stride) + explicit token_joiner(const std::size_t& stride) : stride_(stride) {} @@ -3110,59 +3217,82 @@ namespace exprtk inline std::size_t process_stride_2(generator& g) { - typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; - if (g.token_list_.size() < 2) return 0; std::size_t changes = 0; + generator::token_list_t token_list; + token_list.reserve(10000); + for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) { token t; - while (join(g[i], g[i + 1], t)) + for ( ; ; ) { - g.token_list_[i] = t; + if (!join(g[i], g[i + 1], t)) + { + token_list.push_back(g[i]); + break; + } - g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1)); + token_list.push_back(t); ++changes; - if (static_cast<std::size_t>(i + 1) >= g.token_list_.size()) + i+=2; + + if (static_cast<std::size_t>(i) >= g.token_list_.size()) break; } } + token_list.push_back(g.token_list_.back()); + + std::swap(token_list, g.token_list_); + return changes; } inline std::size_t process_stride_3(generator& g) { - typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; - if (g.token_list_.size() < 3) return 0; std::size_t changes = 0; + generator::token_list_t token_list; + token_list.reserve(10000); + for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) { token t; - while (join(g[i], g[i + 1], g[i + 2], t)) + for ( ; ; ) { - g.token_list_[i] = t; + if (!join(g[i], g[i + 1], g[i + 2], t)) + { + token_list.push_back(g[i]); + break; + } + + token_list.push_back(t); - g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1), - g.token_list_.begin() + static_cast<diff_t>(i + 3)); ++changes; - if (static_cast<std::size_t>(i + 2) >= g.token_list_.size()) + i+=3; + + if (static_cast<std::size_t>(i) >= g.token_list_.size()) break; } } + token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); + token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); + + std::swap(token_list, g.token_list_); + return changes; } @@ -3172,11 +3302,11 @@ namespace exprtk namespace helper { - inline void dump(lexer::generator& generator) + inline void dump(const lexer::generator& generator) { for (std::size_t i = 0; i < generator.size(); ++i) { - lexer::token t = generator[i]; + const lexer::token& t = generator[i]; printf("Token[%02d] @ %03d %6s --> '%s'\n", static_cast<int>(i), static_cast<int>(t.position), @@ -3251,7 +3381,7 @@ namespace exprtk { public: - operator_joiner(const std::size_t& stride) + explicit operator_joiner(const std::size_t& stride) : token_joiner(stride) {} @@ -3649,10 +3779,11 @@ namespace exprtk sequence_validator() : lexer::token_scanner(2) { - add_invalid(lexer::token::e_number ,lexer::token::e_number ); - add_invalid(lexer::token::e_string ,lexer::token::e_string ); - add_invalid(lexer::token::e_number ,lexer::token::e_string ); - add_invalid(lexer::token::e_string ,lexer::token::e_number ); + add_invalid(lexer::token::e_number, lexer::token::e_number); + add_invalid(lexer::token::e_string, lexer::token::e_string); + add_invalid(lexer::token::e_number, lexer::token::e_string); + add_invalid(lexer::token::e_string, lexer::token::e_number); + add_invalid_set1(lexer::token::e_assign ); add_invalid_set1(lexer::token::e_shr ); add_invalid_set1(lexer::token::e_shl ); @@ -3726,21 +3857,21 @@ namespace exprtk void add_invalid_set1(lexer::token::token_type t) { - add_invalid(t,lexer::token::e_assign); - add_invalid(t,lexer::token::e_shr ); - add_invalid(t,lexer::token::e_shl ); - add_invalid(t,lexer::token::e_lte ); - add_invalid(t,lexer::token::e_ne ); - add_invalid(t,lexer::token::e_gte ); - add_invalid(t,lexer::token::e_lt ); - add_invalid(t,lexer::token::e_gt ); - add_invalid(t,lexer::token::e_eq ); - add_invalid(t,lexer::token::e_comma ); - add_invalid(t,lexer::token::e_div ); - add_invalid(t,lexer::token::e_mul ); - add_invalid(t,lexer::token::e_mod ); - add_invalid(t,lexer::token::e_pow ); - add_invalid(t,lexer::token::e_colon ); + add_invalid(t, lexer::token::e_assign); + add_invalid(t, lexer::token::e_shr ); + add_invalid(t, lexer::token::e_shl ); + add_invalid(t, lexer::token::e_lte ); + add_invalid(t, lexer::token::e_ne ); + add_invalid(t, lexer::token::e_gte ); + add_invalid(t, lexer::token::e_lt ); + add_invalid(t, lexer::token::e_gt ); + add_invalid(t, lexer::token::e_eq ); + add_invalid(t, lexer::token::e_comma ); + add_invalid(t, lexer::token::e_div ); + add_invalid(t, lexer::token::e_mul ); + add_invalid(t, lexer::token::e_mod ); + add_invalid(t, lexer::token::e_pow ); + add_invalid(t, lexer::token::e_colon ); } bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t) @@ -3750,7 +3881,7 @@ namespace exprtk switch (t) { case lexer::token::e_assign : return (']' != base); - case lexer::token::e_string : return true; + case lexer::token::e_string : return (')' != base); default : return false; } } @@ -3821,23 +3952,23 @@ namespace exprtk sequence_validator_3tokens() : lexer::token_scanner(3) { - add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); - add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); - add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); + add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number); + add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string); + add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); - add_invalid(lexer::token::e_add ,lexer::token::e_add , lexer::token::e_add); - add_invalid(lexer::token::e_sub ,lexer::token::e_sub , lexer::token::e_sub); - add_invalid(lexer::token::e_div ,lexer::token::e_div , lexer::token::e_div); - add_invalid(lexer::token::e_mul ,lexer::token::e_mul , lexer::token::e_mul); - add_invalid(lexer::token::e_mod ,lexer::token::e_mod , lexer::token::e_mod); - add_invalid(lexer::token::e_pow ,lexer::token::e_pow , lexer::token::e_pow); + add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); + add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); + add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); + add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); + add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); + add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); - add_invalid(lexer::token::e_add ,lexer::token::e_sub , lexer::token::e_add); - add_invalid(lexer::token::e_sub ,lexer::token::e_add , lexer::token::e_sub); - add_invalid(lexer::token::e_div ,lexer::token::e_mul , lexer::token::e_div); - add_invalid(lexer::token::e_mul ,lexer::token::e_div , lexer::token::e_mul); - add_invalid(lexer::token::e_mod ,lexer::token::e_pow , lexer::token::e_mod); - add_invalid(lexer::token::e_pow ,lexer::token::e_mod , lexer::token::e_pow); + add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); + add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); + add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); + add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); + add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); + add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); } bool result() @@ -4231,14 +4362,14 @@ namespace exprtk inline vector_view<T> make_vector_view(T* data, const std::size_t size, const std::size_t offset = 0) { - return vector_view<T>(data + offset,size); + return vector_view<T>(data + offset, size); } template <typename T> inline vector_view<T> make_vector_view(std::vector<T>& v, const std::size_t size, const std::size_t offset = 0) { - return vector_view<T>(v.data() + offset,size); + return vector_view<T>(v.data() + offset, size); } template <typename T> class results_context; @@ -4273,7 +4404,7 @@ namespace exprtk { public: - parameter_list(std::vector<type_store>& pl) + explicit parameter_list(std::vector<type_store>& pl) : parameter_list_(pl) {} @@ -4330,12 +4461,12 @@ namespace exprtk typedef type_store<T> type_store_t; typedef ViewType value_t; - type_view(type_store_t& ts) + explicit type_view(type_store_t& ts) : ts_(ts), data_(reinterpret_cast<value_t*>(ts_.data)) {} - type_view(const type_store_t& ts) + explicit type_view(const type_store_t& ts) : ts_(const_cast<type_store_t&>(ts)), data_(reinterpret_cast<value_t*>(ts_.data)) {} @@ -4380,11 +4511,11 @@ namespace exprtk typedef type_store<T> type_store_t; typedef T value_t; - scalar_view(type_store_t& ts) + explicit scalar_view(type_store_t& ts) : v_(*reinterpret_cast<value_t*>(ts.data)) {} - scalar_view(const type_store_t& ts) + explicit scalar_view(const type_store_t& ts) : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) {} @@ -4572,27 +4703,33 @@ namespace exprtk { switch (opr) { - case e_add : return "+"; - case e_sub : return "-"; - case e_mul : return "*"; - case e_div : return "/"; - case e_mod : return "%"; - case e_pow : return "^"; - case e_assign : return ":="; - case e_addass : return "+="; - case e_subass : return "-="; - case e_mulass : return "*="; - case e_divass : return "/="; - case e_modass : return "%="; - case e_lt : return "<"; - case e_lte : return "<="; - case e_eq : return "=="; - case e_equal : return "="; - case e_ne : return "!="; - case e_nequal : return "<>"; - case e_gte : return ">="; - case e_gt : return ">"; - default : return"N/A"; + case e_add : return "+" ; + case e_sub : return "-" ; + case e_mul : return "*" ; + case e_div : return "/" ; + case e_mod : return "%" ; + case e_pow : return "^" ; + case e_assign : return ":=" ; + case e_addass : return "+=" ; + case e_subass : return "-=" ; + case e_mulass : return "*=" ; + case e_divass : return "/=" ; + case e_modass : return "%=" ; + case e_lt : return "<" ; + case e_lte : return "<=" ; + case e_eq : return "==" ; + case e_equal : return "=" ; + case e_ne : return "!=" ; + case e_nequal : return "<>" ; + case e_gte : return ">=" ; + case e_gt : return ">" ; + case e_and : return "and" ; + case e_or : return "or" ; + case e_xor : return "xor" ; + case e_nand : return "nand"; + case e_nor : return "nor" ; + case e_xnor : return "xnor"; + default : return "N/A" ; } } @@ -4617,8 +4754,8 @@ namespace exprtk struct details { - details(const std::size_t& vsize, - const unsigned int loop_batch_size = global_loop_batch_size) + explicit details(const std::size_t& vsize, + const unsigned int loop_batch_size = global_loop_batch_size) : batch_size(loop_batch_size ), remainder (vsize % batch_size), upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) @@ -4665,7 +4802,7 @@ namespace exprtk destruct (true) {} - control_block(const std::size_t& dsize) + explicit control_block(const std::size_t& dsize) : ref_count(1 ), size (dsize), data (0 ), @@ -4732,7 +4869,7 @@ namespace exprtk { destruct = true; data = new T[size]; - std::fill_n(data,size,T(0)); + std::fill_n(data, size, T(0)); dump_ptr("control_block::create_data() - data",data,size); } }; @@ -4743,8 +4880,8 @@ namespace exprtk : control_block_(control_block::create(0)) {} - vec_data_store(const std::size_t& size) - : control_block_(control_block::create(size,(data_t)(0),true)) + explicit vec_data_store(const std::size_t& size) + : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) {} vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) @@ -4829,7 +4966,7 @@ namespace exprtk static inline void match_sizes(type& vds0, type& vds1) { - std::size_t size = min_size(vds0.control_block_,vds1.control_block_); + const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); vds0.control_block_->size = size; vds1.control_block_->size = size; } @@ -4993,58 +5130,77 @@ namespace exprtk template <typename T> inline T process(const operator_type operation, const T arg0, const T arg1) { - return exprtk::details::numeric::details::process_impl(operation,arg0,arg1); + return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); } } + template <typename Node> + struct node_collector_interface + { + typedef Node* node_ptr_t; + typedef Node** node_pp_t; + typedef std::vector<node_pp_t> noderef_list_t; + + virtual ~node_collector_interface() {} + + virtual void collect_nodes(noderef_list_t&) {} + }; + + template <typename Node> + struct node_depth_base; + template <typename T> - class expression_node + class expression_node : public node_collector_interface<expression_node<T> >, + public node_depth_base<expression_node<T> > { public: enum node_type { - e_none , e_null , e_constant , e_unary , - e_binary , e_binary_ext , e_trinary , e_quaternary , - e_vararg , e_conditional , e_while , e_repeat , - e_for , e_switch , e_mswitch , e_return , - e_retenv , e_variable , e_stringvar , e_stringconst , - e_stringvarrng , e_cstringvarrng, e_strgenrange , e_strconcat , - e_stringvarsize, e_strswap , e_stringsize , e_stringvararg , - e_function , e_vafunction , e_genfunction , e_strfunction , - e_strcondition , e_strccondition, e_add , e_sub , - e_mul , e_div , e_mod , e_pow , - e_lt , e_lte , e_gt , e_gte , - e_eq , e_ne , e_and , e_nand , - e_or , e_nor , e_xor , e_xnor , - e_in , e_like , e_ilike , e_inranges , - e_ipow , e_ipowinv , e_abs , e_acos , - e_acosh , e_asin , e_asinh , e_atan , - e_atanh , e_ceil , e_cos , e_cosh , - e_exp , e_expm1 , e_floor , e_log , - e_log10 , e_log2 , e_log1p , e_neg , - e_pos , e_round , e_sin , e_sinc , - e_sinh , e_sqrt , e_tan , e_tanh , - e_cot , e_sec , e_csc , e_r2d , - e_d2r , e_d2g , e_g2d , e_notl , - e_sgn , e_erf , e_erfc , e_ncdf , - e_frac , e_trunc , e_uvouv , e_vov , - e_cov , e_voc , e_vob , e_bov , - e_cob , e_boc , e_vovov , e_vovoc , - e_vocov , e_covov , e_covoc , e_vovovov , - e_vovovoc , e_vovocov , e_vocovov , e_covovov , - e_covocov , e_vocovoc , e_covovoc , e_vococov , - e_sf3ext , e_sf4ext , e_nulleq , e_strass , - e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , - e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , - e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , - e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , - e_valvecarith , e_vecunaryop , e_break , e_continue , + e_none , e_null , e_constant , e_unary , + e_binary , e_binary_ext , e_trinary , e_quaternary , + e_vararg , e_conditional , e_while , e_repeat , + e_for , e_switch , e_mswitch , e_return , + e_retenv , e_variable , e_stringvar , e_stringconst , + e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , + e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , + e_function , e_vafunction , e_genfunction , e_strfunction , + e_strcondition , e_strccondition , e_add , e_sub , + e_mul , e_div , e_mod , e_pow , + e_lt , e_lte , e_gt , e_gte , + e_eq , e_ne , e_and , e_nand , + e_or , e_nor , e_xor , e_xnor , + e_in , e_like , e_ilike , e_inranges , + e_ipow , e_ipowinv , e_abs , e_acos , + e_acosh , e_asin , e_asinh , e_atan , + e_atanh , e_ceil , e_cos , e_cosh , + e_exp , e_expm1 , e_floor , e_log , + e_log10 , e_log2 , e_log1p , e_neg , + e_pos , e_round , e_sin , e_sinc , + e_sinh , e_sqrt , e_tan , e_tanh , + e_cot , e_sec , e_csc , e_r2d , + e_d2r , e_d2g , e_g2d , e_notl , + e_sgn , e_erf , e_erfc , e_ncdf , + e_frac , e_trunc , e_uvouv , e_vov , + e_cov , e_voc , e_vob , e_bov , + e_cob , e_boc , e_vovov , e_vovoc , + e_vocov , e_covov , e_covoc , e_vovovov , + e_vovovoc , e_vovocov , e_vocovov , e_covovov , + e_covocov , e_vocovoc , e_covovoc , e_vococov , + e_sf3ext , e_sf4ext , e_nulleq , e_strass , + e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , + e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , + e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , + e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , + e_valvecarith , e_vecunaryop , e_break , e_continue , e_swap }; typedef T value_type; typedef expression_node<T>* expression_ptr; + typedef node_collector_interface<expression_node<T> > nci_t; + typedef typename nci_t::noderef_list_t noderef_list_t; + typedef node_depth_base<expression_node<T> > ndb_t; virtual ~expression_node() {} @@ -5095,12 +5251,24 @@ namespace exprtk return std::not_equal_to<T>()(T(0),node->value()); } + template <typename T> + inline bool is_true(const std::pair<expression_node<T>*,bool>& node) + { + return std::not_equal_to<T>()(T(0),node.first->value()); + } + template <typename T> inline bool is_false(const expression_node<T>* node) { return std::equal_to<T>()(T(0),node->value()); } + template <typename T> + inline bool is_false(const std::pair<expression_node<T>*,bool>& node) + { + return std::equal_to<T>()(T(0),node.first->value()); + } + template <typename T> inline bool is_unary_node(const expression_node<T>* node) { @@ -5243,7 +5411,8 @@ namespace exprtk template <typename T> inline bool branch_deletable(expression_node<T>* node) { - return !is_variable_node(node) && + return (0 != node) && + !is_variable_node(node) && !is_string_node (node) ; } @@ -5301,6 +5470,76 @@ namespace exprtk return true; } + template <typename Node> + class node_collection_destructor + { + public: + + typedef node_collector_interface<Node> nci_t; + + typedef typename nci_t::node_ptr_t node_ptr_t; + typedef typename nci_t::node_pp_t node_pp_t; + typedef typename nci_t::noderef_list_t noderef_list_t; + + static void delete_nodes(node_ptr_t& root) + { + std::vector<node_pp_t> node_delete_list; + node_delete_list.reserve(1000); + + collect_nodes(root, node_delete_list); + + for (std::size_t i = 0; i < node_delete_list.size(); ++i) + { + node_ptr_t& node = *node_delete_list[i]; + exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast<void*>(node))); + delete node; + node = reinterpret_cast<node_ptr_t>(0); + } + } + + private: + + static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) + { + std::deque<node_ptr_t> node_list; + node_list.push_back(root); + node_delete_list.push_back(&root); + + noderef_list_t child_node_delete_list; + child_node_delete_list.reserve(1000); + + while (!node_list.empty()) + { + node_list.front()->collect_nodes(child_node_delete_list); + + if (!child_node_delete_list.empty()) + { + for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) + { + node_pp_t& node = child_node_delete_list[i]; + + if (0 == (*node)) + { + exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); + } + + node_list.push_back(*node); + } + + node_delete_list.insert( + node_delete_list.end(), + child_node_delete_list.begin(), child_node_delete_list.end()); + + child_node_delete_list.clear(); + } + + node_list.pop_front(); + } + + std::reverse(node_delete_list.begin(), node_delete_list.end()); + } + }; + template <typename NodeAllocator, typename T, std::size_t N> inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) { @@ -5325,28 +5564,239 @@ namespace exprtk } template <typename NodeAllocator, typename T> - inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false) + inline void free_node(NodeAllocator&, expression_node<T>*& node) { - if (0 != node) + if ((0 == node) || is_variable_node(node) || is_string_node(node)) { - if ( - (is_variable_node(node) || is_string_node(node)) || - force_delete - ) - return; - - node_allocator.free(node); - node = reinterpret_cast<expression_node<T>*>(0); + return; } + + node_collection_destructor<expression_node<T> > + ::delete_nodes(node); } template <typename T> inline void destroy_node(expression_node<T>*& node) { - delete node; - node = reinterpret_cast<expression_node<T>*>(0); + if (0 != node) + { + node_collection_destructor<expression_node<T> > + ::delete_nodes(node); + } } + template <typename Node> + struct node_depth_base + { + node_depth_base() + : depth_set(false), + depth(0) + {} + + virtual ~node_depth_base() {} + + virtual std::size_t node_depth() const { return 1; } + + std::size_t compute_node_depth(const Node* const& node) const + { + if (!depth_set) + { + depth = 1 + (node ? node->node_depth() : 0); + depth_set = true; + } + + return depth; + } + + std::size_t compute_node_depth(const std::pair<Node*,bool>& branch) const + { + if (!depth_set) + { + depth = 1 + (branch.first ? branch.first->node_depth() : 0); + depth_set = true; + } + + return depth; + } + + template <std::size_t N> + std::size_t compute_node_depth(const std::pair<Node*,bool> (&branch)[N]) const + { + if (!depth_set) + { + depth = 0; + for (std::size_t i = 0; i < N; ++i) + { + if (branch[i].first) + { + depth = std::max(depth,branch[i].first->node_depth()); + } + } + depth += 1; + depth_set = true; + } + + return depth; + } + + template <typename BranchType> + std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const + { + if (!depth_set) + { + depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1)); + depth_set = true; + } + + return depth; + } + + template <typename BranchType> + std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, + const BranchType& n2) const + { + if (!depth_set) + { + depth = 1 + std::max( + std::max(compute_node_depth(n0), compute_node_depth(n1)), + compute_node_depth(n2)); + depth_set = true; + } + + return depth; + } + + template <typename BranchType> + std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, + const BranchType& n2, const BranchType& n3) const + { + if (!depth_set) + { + depth = 1 + std::max( + std::max(compute_node_depth(n0), compute_node_depth(n1)), + std::max(compute_node_depth(n2), compute_node_depth(n3))); + depth_set = true; + } + + return depth; + } + + template <typename Allocator, + template <typename, typename> class Sequence> + std::size_t compute_node_depth(const Sequence<Node*, Allocator>& branch_list) const + { + if (!depth_set) + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + if (branch_list[i]) + { + depth = std::max(depth, compute_node_depth(branch_list[i])); + } + } + depth_set = true; + } + + return depth; + } + + template <typename Allocator, + template <typename, typename> class Sequence> + std::size_t compute_node_depth(const Sequence<std::pair<Node*,bool>,Allocator>& branch_list) const + { + if (!depth_set) + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + if (branch_list[i].first) + { + depth = std::max(depth, compute_node_depth(branch_list[i].first)); + } + } + depth_set = true; + } + + return depth; + } + + mutable bool depth_set; + mutable std::size_t depth; + + template <typename NodeSequence> + void collect(Node*const& node, + const bool deletable, + NodeSequence& delete_node_list) const + { + if ((0 != node) && deletable) + { + delete_node_list.push_back(const_cast<Node**>(&node)); + } + } + + template <typename NodeSequence> + void collect(const std::pair<Node*, bool>& branch, + NodeSequence& delete_node_list) const + { + collect(branch.first, branch.second, delete_node_list); + } + + template <typename NodeSequence> + void collect(Node*& node, + NodeSequence& delete_node_list) const + { + collect(node, branch_deletable(node), delete_node_list); + } + + template <std::size_t N, typename NodeSequence> + void collect(const std::pair<Node*, bool>(&branch)[N], + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < N; ++i) + { + collect(branch[i].first, branch[i].second, delete_node_list); + } + } + + template <typename Allocator, + template <typename, typename> class Sequence, + typename NodeSequence> + void collect(const Sequence<std::pair<Node*, bool>, Allocator>& branch, + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < branch.size(); ++i) + { + collect(branch[i].first, branch[i].second, delete_node_list); + } + } + + template <typename Allocator, + template <typename, typename> class Sequence, + typename NodeSequence> + void collect(const Sequence<Node*, Allocator>& branch_list, + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); + } + } + + template <typename Boolean, + typename AllocatorT, + typename AllocatorB, + template <typename, typename> class Sequence, + typename NodeSequence> + void collect(const Sequence<Node*, AllocatorT>& branch_list, + const Sequence<Boolean, AllocatorB>& branch_deletable_list, + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + collect(branch_list[i], branch_deletable_list[i], delete_node_list); + } + } + }; + template <typename Type> class vector_holder { @@ -5560,30 +6010,70 @@ namespace exprtk } }; + template <typename T, std::size_t N> + inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], + expression_node<T>* b, + const std::size_t& index) + { + if (b && (index < N)) + { + branch[index] = std::make_pair(b,branch_deletable(b)); + } + } + + template <typename T> + inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) + { + if (b) + { + branch = std::make_pair(b,branch_deletable(b)); + } + } + + template <std::size_t N, typename T> + inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], + expression_node<T>* b0, + expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) + { + construct_branch_pair(branch, b0, 0); + construct_branch_pair(branch, b1, 1); + construct_branch_pair(branch, b2, 2); + construct_branch_pair(branch, b3, 3); + construct_branch_pair(branch, b4, 4); + construct_branch_pair(branch, b5, 5); + construct_branch_pair(branch, b6, 6); + construct_branch_pair(branch, b7, 7); + construct_branch_pair(branch, b8, 8); + construct_branch_pair(branch, b9, 9); + } + template <typename T> class null_eq_node : public expression_node<T> { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - null_eq_node(expression_ptr brnch, const bool equality = true) - : branch_(brnch), - branch_deletable_(branch_deletable(branch_)), - equality_(equality) - {} - - ~null_eq_node() + explicit null_eq_node(expression_ptr branch, const bool equality = true) + : equality_(equality) { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } + construct_branch_pair(branch_, branch); } inline T value() const { - const T v = branch_->value(); + assert(branch_.first); + + const T v = branch_.first->value(); const bool result = details::numeric::is_nan(v); if (result) @@ -5604,14 +6094,23 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_,node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: - expression_ptr branch_; - const bool branch_deletable_; bool equality_; + branch_t branch_; }; template <typename T> @@ -5759,25 +6258,19 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - unary_node(const operator_type& opr, - expression_ptr brnch) - : operation_(opr), - branch_(brnch), - branch_deletable_(branch_deletable(branch_)) - {} - - ~unary_node() + unary_node(const operator_type& opr, expression_ptr branch) + : operation_(opr) { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } + construct_branch_pair(branch_,branch); } inline T value() const { - const T arg = branch_->value(); + assert(branch_.first); + + const T arg = branch_.first->value(); return numeric::process<T>(operation_,arg); } @@ -5794,94 +6287,28 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_; + return branch_.first; } inline void release() { - branch_deletable_ = false; + branch_.second = false; } - protected: - - operator_type operation_; - expression_ptr branch_; - bool branch_deletable_; - }; - - template <typename T, std::size_t D, bool B> - struct construct_branch_pair - { - template <std::size_t N> - static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*) - {} - }; - - template <typename T, std::size_t D> - struct construct_branch_pair<T,D,true> - { - template <std::size_t N> - static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b) + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) { - if (b) - { - branch[D] = std::make_pair(b,branch_deletable(b)); - } + expression_node<T>::ndb_t::collect(branch_, node_delete_list); } - }; - template <std::size_t N, typename T> - inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], - expression_node<T>* b0, - expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) - { - construct_branch_pair<T,0,(N > 0)>::process(branch,b0); - construct_branch_pair<T,1,(N > 1)>::process(branch,b1); - construct_branch_pair<T,2,(N > 2)>::process(branch,b2); - construct_branch_pair<T,3,(N > 3)>::process(branch,b3); - construct_branch_pair<T,4,(N > 4)>::process(branch,b4); - construct_branch_pair<T,5,(N > 5)>::process(branch,b5); - construct_branch_pair<T,6,(N > 6)>::process(branch,b6); - construct_branch_pair<T,7,(N > 7)>::process(branch,b7); - construct_branch_pair<T,8,(N > 8)>::process(branch,b8); - construct_branch_pair<T,9,(N > 9)>::process(branch,b9); - } - - struct cleanup_branches - { - template <typename T, std::size_t N> - static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N]) + std::size_t node_depth() const { - for (std::size_t i = 0; i < N; ++i) - { - if (branch[i].first && branch[i].second) - { - destroy_node(branch[i].first); - } - } + return expression_node<T>::ndb_t::compute_node_depth(branch_); } - template <typename T, - typename Allocator, - template <typename, typename> class Sequence> - static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch) - { - for (std::size_t i = 0; i < branch.size(); ++i) - { - if (branch[i].first && branch[i].second) - { - destroy_node(branch[i].first); - } - } - } + protected: + + operator_type operation_; + branch_t branch_; }; template <typename T> @@ -5900,13 +6327,11 @@ namespace exprtk init_branches<2>(branch_, branch0, branch1); } - ~binary_node() - { - cleanup_branches::execute<T,2>(branch_); - } - inline T value() const { + assert(branch_[0].first); + assert(branch_[1].first); + const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); @@ -5933,6 +6358,16 @@ namespace exprtk return reinterpret_cast<expression_ptr>(0); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); + } + protected: operator_type operation_; @@ -5952,13 +6387,11 @@ namespace exprtk init_branches<2>(branch_, branch0, branch1); } - ~binary_ext_node() - { - cleanup_branches::execute<T,2>(branch_); - } - inline T value() const { + assert(branch_[0].first); + assert(branch_[1].first); + const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); @@ -5985,6 +6418,16 @@ namespace exprtk return reinterpret_cast<expression_ptr>(0); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); + } + protected: branch_t branch_[2]; @@ -6007,13 +6450,12 @@ namespace exprtk init_branches<3>(branch_, branch0, branch1, branch2); } - ~trinary_node() - { - cleanup_branches::execute<T,3>(branch_); - } - inline T value() const { + assert(branch_[0].first); + assert(branch_[1].first); + assert(branch_[2].first); + const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); const T arg2 = branch_[2].first->value(); @@ -6039,6 +6481,16 @@ namespace exprtk return expression_node<T>::e_trinary; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); + } + protected: operator_type operation_; @@ -6063,11 +6515,6 @@ namespace exprtk init_branches<4>(branch_, branch0, branch1, branch2, branch3); } - ~quaternary_node() - { - cleanup_branches::execute<T,4>(branch_); - } - inline T value() const { return std::numeric_limits<T>::quiet_NaN(); @@ -6078,6 +6525,16 @@ namespace exprtk return expression_node<T>::e_quaternary; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); + } + protected: operator_type operation_; @@ -6090,42 +6547,27 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - conditional_node(expression_ptr test, + conditional_node(expression_ptr condition, expression_ptr consequent, expression_ptr alternative) - : test_(test), - consequent_(consequent), - alternative_(alternative), - test_deletable_(branch_deletable(test_)), - consequent_deletable_(branch_deletable(consequent_)), - alternative_deletable_(branch_deletable(alternative_)) - {} - - ~conditional_node() { - if (test_ && test_deletable_) - { - destroy_node(test_); - } - - if (consequent_ && consequent_deletable_ ) - { - destroy_node(consequent_); - } - - if (alternative_ && alternative_deletable_) - { - destroy_node(alternative_); - } + construct_branch_pair(condition_ , condition ); + construct_branch_pair(consequent_ , consequent ); + construct_branch_pair(alternative_, alternative); } inline T value() const { - if (is_true(test_)) - return consequent_->value(); + assert(condition_ .first); + assert(consequent_ .first); + assert(alternative_.first); + + if (is_true(condition_)) + return consequent_.first->value(); else - return alternative_->value(); + return alternative_.first->value(); } inline typename expression_node<T>::node_type type() const @@ -6133,14 +6575,24 @@ namespace exprtk return expression_node<T>::e_conditional; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); + expression_node<T>::ndb_t::collect(alternative_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth + (condition_, consequent_, alternative_); + } + private: - expression_ptr test_; - expression_ptr consequent_; - expression_ptr alternative_; - const bool test_deletable_; - const bool consequent_deletable_; - const bool alternative_deletable_; + branch_t condition_; + branch_t consequent_; + branch_t alternative_; }; template <typename T> @@ -6150,32 +6602,22 @@ namespace exprtk // Consequent only conditional statement node typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - cons_conditional_node(expression_ptr test, + cons_conditional_node(expression_ptr condition, expression_ptr consequent) - : test_(test), - consequent_(consequent), - test_deletable_(branch_deletable(test_)), - consequent_deletable_(branch_deletable(consequent_)) - {} - - ~cons_conditional_node() { - if (test_ && test_deletable_) - { - destroy_node(test_); - } - - if (consequent_ && consequent_deletable_) - { - destroy_node(consequent_); - } + construct_branch_pair(condition_ , condition ); + construct_branch_pair(consequent_, consequent); } inline T value() const { - if (is_true(test_)) - return consequent_->value(); + assert(condition_ .first); + assert(consequent_.first); + + if (is_true(condition_)) + return consequent_.first->value(); else return std::numeric_limits<T>::quiet_NaN(); } @@ -6185,12 +6627,22 @@ namespace exprtk return expression_node<T>::e_conditional; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(consequent_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t:: + compute_node_depth(condition_, consequent_); + } + private: - expression_ptr test_; - expression_ptr consequent_; - const bool test_deletable_; - const bool consequent_deletable_; + branch_t condition_; + branch_t consequent_; }; #ifndef exprtk_disable_break_continue @@ -6199,7 +6651,7 @@ namespace exprtk { public: - break_exception(const T& v) + explicit break_exception(const T& v) : value(v) {} @@ -6215,23 +6667,16 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; break_node(expression_ptr ret = expression_ptr(0)) - : return_(ret), - return_deletable_(branch_deletable(return_)) - {} - - ~break_node() { - if (return_deletable_) - { - destroy_node(return_); - } + construct_branch_pair(return_, ret); } inline T value() const { - throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN()); + throw break_exception<T>(return_.first ? return_.first->value() : std::numeric_limits<T>::quiet_NaN()); #ifndef _MSC_VER return std::numeric_limits<T>::quiet_NaN(); #endif @@ -6242,10 +6687,19 @@ namespace exprtk return expression_node<T>::e_break; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(return_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(return_); + } + private: - expression_ptr return_; - const bool return_deletable_; + branch_t return_; }; template <typename T> @@ -6268,40 +6722,90 @@ namespace exprtk }; #endif - template <typename T> - class while_loop_node : public expression_node<T> + #ifdef exprtk_enable_runtime_checks + struct loop_runtime_checker { - public: - - typedef expression_node<T>* expression_ptr; - - while_loop_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) + loop_runtime_checker(loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0), + loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) + : iteration_count_(0), + loop_runtime_check_(loop_rt_chk), + loop_type(lp_typ) {} - ~while_loop_node() + inline void reset(const _uint64_t initial_value = 0) const { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } + iteration_count_ = initial_value; + } - if (loop_body_ && loop_body_deletable_) + inline bool check() const + { + if ( + (0 == loop_runtime_check_) || + (++iteration_count_ <= loop_runtime_check_->max_loop_iterations) + ) { - destroy_node(loop_body_); + return true; } + + loop_runtime_check::violation_context ctxt; + ctxt.loop = loop_type; + ctxt.violation = loop_runtime_check::e_iteration_count; + + loop_runtime_check_->handle_runtime_violation(ctxt); + + return false; + } + + mutable _uint64_t iteration_count_; + mutable loop_runtime_check_ptr loop_runtime_check_; + loop_runtime_check::loop_types loop_type; + }; + #else + struct loop_runtime_checker + { + loop_runtime_checker(loop_runtime_check_ptr, loop_runtime_check::loop_types) + {} + + inline void reset(const _uint64_t = 0) const + {} + + inline bool check() const + { + return true; + } + }; + #endif + + template <typename T> + class while_loop_node : public expression_node<T>, + public loop_runtime_checker + { + public: + + typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; + + while_loop_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk,loop_runtime_check::e_while_loop) + { + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - while (is_true(condition_)) + loop_runtime_checker::reset(); + + while (is_true(condition_) && loop_runtime_checker::check()) { - result = loop_body_->value(); + result = loop_body_.first->value(); } return result; @@ -6312,50 +6816,55 @@ namespace exprtk return expression_node<T>::e_while; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class repeat_until_loop_node : public expression_node<T> + class repeat_until_loop_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) - {} - - ~repeat_until_loop_node() + repeat_until_loop_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); + loop_runtime_checker::reset(1); + do { - result = loop_body_->value(); + result = loop_body_.first->value(); } - while (is_false(condition_)); + while (is_false(condition_.first) && loop_runtime_checker::check()); return result; } @@ -6365,78 +6874,70 @@ namespace exprtk return expression_node<T>::e_repeat; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class for_loop_node : public expression_node<T> + class for_loop_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; for_loop_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, - expression_ptr loop_body) - : initialiser_(initialiser), - condition_ (condition ), - incrementor_(incrementor), - loop_body_ (loop_body ), - initialiser_deletable_(branch_deletable(initialiser_)), - condition_deletable_ (branch_deletable(condition_ )), - incrementor_deletable_(branch_deletable(incrementor_)), - loop_body_deletable_ (branch_deletable(loop_body_ )) - {} - - ~for_loop_node() + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) { - if (initialiser_ && initialiser_deletable_) - { - destroy_node(initialiser_); - } - - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (incrementor_ && incrementor_deletable_) - { - destroy_node(incrementor_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(initialiser_, initialiser); + construct_branch_pair(condition_ , condition ); + construct_branch_pair(incrementor_, incrementor); + construct_branch_pair(loop_body_ , loop_body ); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - if (initialiser_) - initialiser_->value(); + loop_runtime_checker::reset(); + + if (initialiser_.first) + initialiser_.first->value(); - if (incrementor_) + if (incrementor_.first) { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { - result = loop_body_->value(); - incrementor_->value(); + result = loop_body_.first->value(); + incrementor_.first->value(); } } else { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { - result = loop_body_->value(); + result = loop_body_.first->value(); } } @@ -6448,55 +6949,61 @@ namespace exprtk return expression_node<T>::e_for; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(initialiser_, node_delete_list); + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(incrementor_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth + (initialiser_, condition_, incrementor_, loop_body_); + } + private: - expression_ptr initialiser_ ; - expression_ptr condition_ ; - expression_ptr incrementor_ ; - expression_ptr loop_body_ ; - const bool initialiser_deletable_; - const bool condition_deletable_ ; - const bool incrementor_deletable_; - const bool loop_body_deletable_ ; + branch_t initialiser_; + branch_t condition_ ; + branch_t incrementor_; + branch_t loop_body_ ; }; #ifndef exprtk_disable_break_continue template <typename T> - class while_loop_bc_node : public expression_node<T> + class while_loop_bc_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - while_loop_bc_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) - {} - - ~while_loop_bc_node() + while_loop_bc_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - while (is_true(condition_)) + loop_runtime_checker::reset(); + + while (is_true(condition_) && loop_runtime_checker::check()) { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6514,50 +7021,55 @@ namespace exprtk return expression_node<T>::e_while; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class repeat_until_loop_bc_node : public expression_node<T> + class repeat_until_loop_bc_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) - {} - - ~repeat_until_loop_bc_node() + repeat_until_loop_bc_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); + loop_runtime_checker::reset(); + do { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6566,7 +7078,7 @@ namespace exprtk catch(const continue_exception&) {} } - while (is_false(condition_)); + while (is_false(condition_.first) && loop_runtime_checker::check()); return result; } @@ -6576,72 +7088,64 @@ namespace exprtk return expression_node<T>::e_repeat; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class for_loop_bc_node : public expression_node<T> + class for_loop_bc_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; for_loop_bc_node(expression_ptr initialiser, - expression_ptr condition, - expression_ptr incrementor, - expression_ptr loop_body) - : initialiser_(initialiser), - condition_ (condition ), - incrementor_(incrementor), - loop_body_ (loop_body ), - initialiser_deletable_(branch_deletable(initialiser_)), - condition_deletable_ (branch_deletable(condition_ )), - incrementor_deletable_(branch_deletable(incrementor_)), - loop_body_deletable_ (branch_deletable(loop_body_ )) - {} - - ~for_loop_bc_node() + expression_ptr condition, + expression_ptr incrementor, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) { - if (initialiser_ && initialiser_deletable_) - { - destroy_node(initialiser_); - } - - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (incrementor_ && incrementor_deletable_) - { - destroy_node(incrementor_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(initialiser_, initialiser); + construct_branch_pair(condition_ , condition ); + construct_branch_pair(incrementor_, incrementor); + construct_branch_pair(loop_body_ , loop_body ); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - if (initialiser_) - initialiser_->value(); + loop_runtime_checker::reset(); - if (incrementor_) + if (initialiser_.first) + initialiser_.first->value(); + + if (incrementor_.first) { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6650,16 +7154,16 @@ namespace exprtk catch(const continue_exception&) {} - incrementor_->value(); + incrementor_.first->value(); } } else { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6678,16 +7182,26 @@ namespace exprtk return expression_node<T>::e_for; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(initialiser_, node_delete_list); + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(incrementor_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth + (initialiser_, condition_, incrementor_, loop_body_); + } + private: - expression_ptr initialiser_; - expression_ptr condition_ ; - expression_ptr incrementor_; - expression_ptr loop_body_ ; - const bool initialiser_deletable_; - const bool condition_deletable_ ; - const bool incrementor_deletable_; - const bool loop_body_deletable_ ; + branch_t initialiser_; + branch_t condition_ ; + branch_t incrementor_; + branch_t loop_body_ ; }; #endif @@ -6697,44 +7211,31 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - switch_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) { if (1 != (arg_list.size() & 1)) return; arg_list_.resize(arg_list.size()); - delete_branch_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i], arg_list[i]); } else { arg_list_.clear(); - delete_branch_.clear(); return; } } } - ~switch_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { if (!arg_list_.empty()) @@ -6743,8 +7244,8 @@ namespace exprtk for (std::size_t i = 0; i < upper_bound; i += 2) { - expression_ptr condition = arg_list_[i ]; - expression_ptr consequent = arg_list_[i + 1]; + expression_ptr condition = arg_list_[i ].first; + expression_ptr consequent = arg_list_[i + 1].first; if (is_true(condition)) { @@ -6752,7 +7253,7 @@ namespace exprtk } } - return arg_list_[upper_bound]->value(); + return arg_list_[upper_bound].first->value(); } else return std::numeric_limits<T>::quiet_NaN(); @@ -6763,10 +7264,19 @@ namespace exprtk return expression_node<T>::e_switch; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + protected: - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + std::vector<branch_t> arg_list_; }; template <typename T, typename Switch_N> @@ -6778,7 +7288,7 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) : switch_node<T>(arg_list) {} @@ -6794,44 +7304,31 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) { if (0 != (arg_list.size() & 1)) return; arg_list_.resize(arg_list.size()); - delete_branch_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i], arg_list[i]); } else { arg_list_.clear(); - delete_branch_.clear(); return; } } } - ~multi_switch_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { T result = T(0); @@ -6845,8 +7342,8 @@ namespace exprtk for (std::size_t i = 0; i < upper_bound; i += 2) { - expression_ptr condition = arg_list_[i ]; - expression_ptr consequent = arg_list_[i + 1]; + expression_ptr condition = arg_list_[i ].first; + expression_ptr consequent = arg_list_[i + 1].first; if (is_true(condition)) { @@ -6862,10 +7359,19 @@ namespace exprtk return expression_node<T>::e_mswitch; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + private: - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + std::vector<branch_t> arg_list_; }; template <typename T> @@ -6892,7 +7398,7 @@ namespace exprtk : value_(&null_value) {} - variable_node(T& v) + explicit variable_node(T& v) : value_(&v) {} @@ -6981,30 +7487,26 @@ namespace exprtk } } - bool const_range() + bool const_range() const { return ( n0_c.first && n1_c.first) && (!n0_e.first && !n1_e.first); } - bool var_range() + bool var_range() const { return ( n0_e.first && n1_e.first) && (!n0_c.first && !n1_c.first); } - bool operator() (std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const + bool operator() (std::size_t& r0, std::size_t& r1, + const std::size_t& size = std::numeric_limits<std::size_t>::max()) const { if (n0_c.first) r0 = n0_c.second; else if (n0_e.first) { - T r0_value = n0_e.second->value(); - - if (r0_value < 0) - return false; - else - r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); + r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); } else return false; @@ -7013,12 +7515,7 @@ namespace exprtk r1 = n1_c.second; else if (n1_e.first) { - T r1_value = n1_e.second->value(); - - if (r1_value < 0) - return false; - else - r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); + r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); } else return false; @@ -7034,7 +7531,11 @@ namespace exprtk cache.first = r0; cache.second = r1; + #ifndef exprtk_enable_runtime_checks return (r0 <= r1); + #else + return range_runtime_check(r0, r1, size); + #endif } inline std::size_t const_size() const @@ -7052,6 +7553,27 @@ namespace exprtk std::pair<bool,std::size_t > n0_c; std::pair<bool,std::size_t > n1_c; mutable cached_range_t cache; + + #ifdef exprtk_enable_runtime_checks + bool range_runtime_check(const std::size_t r0, + const std::size_t r1, + const std::size_t size) const + { + if ((r0 < 0) || (r0 >= size)) + { + throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)"); + return false; + } + + if ((r1 < 0) || (r1 >= size)) + { + throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)"); + return false; + } + + return (r0 <= r1); + } + #endif }; template <typename T> @@ -7115,7 +7637,7 @@ namespace exprtk typedef vector_node<T>* vector_node_ptr; typedef vec_data_store<T> vds_t; - vector_node(vector_holder_t* vh) + explicit vector_node(vector_holder_t* vh) : vector_holder_(vh), vds_((*vector_holder_).size(),(*vector_holder_)[0]) { @@ -7179,38 +7701,31 @@ namespace exprtk { public: - typedef expression_node<T>* expression_ptr; - typedef vector_holder<T> vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; + typedef expression_node<T>* expression_ptr; + typedef vector_holder<T> vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef std::pair<expression_ptr,bool> branch_t; vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : index_(index), - vec_holder_(vec_holder), - vector_base_((*vec_holder)[0]), - index_deletable_(branch_deletable(index_)) - {} - - ~vector_elem_node() + : vec_holder_(vec_holder), + vector_base_((*vec_holder)[0]) { - if (index_ && index_deletable_) - { - destroy_node(index_); - } + construct_branch_pair(index_, index); } inline T value() const { - return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline T& ref() { - return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline const T& ref() const { - return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline typename expression_node<T>::node_type type() const @@ -7223,12 +7738,21 @@ namespace exprtk return (*vec_holder_); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(index_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(index_); + } + private: - expression_ptr index_; vector_holder_ptr vec_holder_; T* vector_base_; - const bool index_deletable_; + branch_t index_; }; template <typename T> @@ -7237,41 +7761,33 @@ namespace exprtk { public: - typedef expression_node<T>* expression_ptr; - typedef vector_holder<T> vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; - typedef vec_data_store<T> vds_t; + typedef expression_node<T>* expression_ptr; + typedef vector_holder<T> vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef vec_data_store<T> vds_t; + typedef std::pair<expression_ptr,bool> branch_t; rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : index_(index), - index_deletable_(branch_deletable(index_)), - vector_holder_(vec_holder), + : vector_holder_(vec_holder), vds_((*vector_holder_).size(),(*vector_holder_)[0]) { vector_holder_->set_ref(&vds_.ref()); - } - - ~rebasevector_elem_node() - { - if (index_ && index_deletable_) - { - destroy_node(index_); - } + construct_branch_pair(index_, index); } inline T value() const { - return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline T& ref() { - return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline const T& ref() const { - return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline typename expression_node<T>::node_type type() const @@ -7284,12 +7800,21 @@ namespace exprtk return (*vector_holder_); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(index_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(index_); + } + private: - expression_ptr index_; - const bool index_deletable_; vector_holder_ptr vector_holder_; vds_t vds_; + branch_t index_; }; template <typename T> @@ -7360,17 +7885,6 @@ namespace exprtk single_value_initialse_(single_value_initialse) {} - ~vector_assignment_node() - { - for (std::size_t i = 0; i < initialiser_list_.size(); ++i) - { - if (branch_deletable(initialiser_list_[i])) - { - destroy_node(initialiser_list_[i]); - } - } - } - inline T value() const { if (single_value_initialse_) @@ -7406,6 +7920,16 @@ namespace exprtk return expression_node<T>::e_vecdefass; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); + } + private: vector_assignment_node<T>& operator=(const vector_assignment_node<T>&); @@ -7527,6 +8051,9 @@ namespace exprtk inline T value() const { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + if (initialised_) { binary_node<T>::branch_[0].first->value(); @@ -7831,18 +8358,18 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef stringvar_node <T>* strvar_node_ptr; - typedef string_base_node<T>* str_base_ptr; - typedef range_pack <T> range_t; - typedef range_t* range_ptr; - typedef range_interface<T> irange_t; - typedef irange_t* irange_ptr; + typedef expression_node <T>* expression_ptr; + typedef stringvar_node <T>* strvar_node_ptr; + typedef string_base_node<T>* str_base_ptr; + typedef range_pack <T> range_t; + typedef range_t* range_ptr; + typedef range_interface<T> irange_t; + typedef irange_t* irange_ptr; + typedef std::pair<expression_ptr,bool> branch_t; + generic_string_range_node(expression_ptr str_branch, const range_t& brange) : initialised_(false), - branch_(str_branch), - branch_deletable_(branch_deletable(branch_)), str_base_ptr_ (0), str_range_ptr_(0), base_range_(brange) @@ -7852,14 +8379,16 @@ namespace exprtk range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; - if (is_generally_string_node(branch_)) + construct_branch_pair(branch_, str_branch); + + if (is_generally_string_node(branch_.first)) { - str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_); + str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); if (0 == str_base_ptr_) return; - str_range_ptr_ = dynamic_cast<irange_ptr>(branch_); + str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); if (0 == str_range_ptr_) return; @@ -7871,18 +8400,15 @@ namespace exprtk ~generic_string_range_node() { base_range_.free(); - - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } } inline T value() const { if (initialised_) { - branch_->value(); + assert(branch_.first); + + branch_.first->value(); std::size_t str_r0 = 0; std::size_t str_r1 = 0; @@ -7890,13 +8416,13 @@ namespace exprtk std::size_t r0 = 0; std::size_t r1 = 0; - range_t& range = str_range_ptr_->range_ref(); + const range_t& range = str_range_ptr_->range_ref(); const std::size_t base_str_size = str_base_ptr_->size(); if ( - range (str_r0,str_r1,base_str_size) && - base_range_( r0, r1,base_str_size) + range (str_r0, str_r1, base_str_size) && + base_range_( r0, r1, base_str_size) ) { const std::size_t size = (r1 - r0) + 1; @@ -7941,11 +8467,20 @@ namespace exprtk return expression_node<T>::e_strgenrange; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: bool initialised_; - expression_ptr branch_; - const bool branch_deletable_; + branch_t branch_; str_base_ptr str_base_ptr_; irange_ptr str_range_ptr_; mutable range_t base_range_; @@ -8019,6 +8554,9 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); @@ -8028,12 +8566,12 @@ namespace exprtk std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; - range_t& range0 = str0_range_ptr_->range_ref(); - range_t& range1 = str1_range_ptr_->range_ref(); + const range_t& range0 = str0_range_ptr_->range_ref(); + const range_t& range1 = str1_range_ptr_->range_ref(); if ( - range0(str0_r0,str0_r1,str0_base_ptr_->size()) && - range1(str1_r0,str1_r1,str1_base_ptr_->size()) + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) ) { const std::size_t size0 = (str0_r1 - str0_r0) + 1; @@ -8129,10 +8667,13 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref()); + std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); } return std::numeric_limits<T>::quiet_NaN(); @@ -8236,6 +8777,9 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); @@ -8245,12 +8789,12 @@ namespace exprtk std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; - range_t& range0 = (*str0_range_ptr_); - range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); if ( - range0(str0_r0,str0_r1,str0_base_ptr_->size()) && - range1(str1_r0,str1_r1,str1_base_ptr_->size()) + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) ) { const std::size_t size0 = range0.cache_size(); @@ -8288,8 +8832,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { std::swap(s0[i],s1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { std::swap(s0[i], s1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -8367,38 +8911,32 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef string_base_node<T>* str_base_ptr; + typedef expression_node <T>* expression_ptr; + typedef string_base_node<T>* str_base_ptr; + typedef std::pair<expression_ptr,bool> branch_t; + - string_size_node(expression_ptr brnch) - : branch_(brnch), - branch_deletable_(branch_deletable(branch_)), - str_base_ptr_(0) + explicit string_size_node(expression_ptr branch) + : str_base_ptr_(0) { - if (is_generally_string_node(branch_)) + construct_branch_pair(branch_, branch); + + if (is_generally_string_node(branch_.first)) { - str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_); + str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); if (0 == str_base_ptr_) return; } } - ~string_size_node() - { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } - } - inline T value() const { T result = std::numeric_limits<T>::quiet_NaN(); if (str_base_ptr_) { - branch_->value(); + branch_.first->value(); result = T(str_base_ptr_->size()); } @@ -8410,11 +8948,20 @@ namespace exprtk return expression_node<T>::e_stringsize; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: - expression_ptr branch_; - const bool branch_deletable_; - str_base_ptr str_base_ptr_; + branch_t branch_; + str_base_ptr str_base_ptr_; }; struct asn_assignment @@ -8486,12 +9033,15 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[1].first->value(); std::size_t r0 = 0; std::size_t r1 = 0; - range_t& range = (*str1_range_ptr_); + const range_t& range = (*str1_range_ptr_); if (range(r0, r1, str1_base_ptr_->size())) { @@ -8552,28 +9102,29 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef stringvar_node <T>* strvar_node_ptr; - typedef string_base_node<T>* str_base_ptr; - typedef range_pack <T> range_t; - typedef range_t* range_ptr; - typedef range_interface<T> irange_t; - typedef irange_t* irange_ptr; + typedef expression_node <T>* expression_ptr; + typedef stringvar_node <T>* strvar_node_ptr; + typedef string_range_node<T>* str_rng_node_ptr; + typedef string_base_node <T>* str_base_ptr; + typedef range_pack <T> range_t; + typedef range_t* range_ptr; + typedef range_interface<T> irange_t; + typedef irange_t* irange_ptr; assignment_string_range_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) : binary_node<T>(opr, branch0, branch1), initialised_(false), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_node_ptr_ (0), - str0_range_ptr_(0), - str1_range_ptr_(0) + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_rng_node_ptr_ (0), + str0_range_ptr_ (0), + str1_range_ptr_ (0) { if (is_string_range_node(binary_node<T>::branch_[0].first)) { - str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first); + str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(binary_node<T>::branch_[0].first); str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); @@ -8600,17 +9151,20 @@ namespace exprtk str1_range_ptr_ = &(range->range_ref()); } - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_node_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ ; + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_rng_node_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ ; } inline T value() const { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); @@ -8620,15 +9174,15 @@ namespace exprtk std::size_t s1_r0 = 0; std::size_t s1_r1 = 0; - range_t& range0 = (*str0_range_ptr_); - range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); if ( range0(s0_r0, s0_r1, str0_base_ptr_->size()) && range1(s1_r0, s1_r1, str1_base_ptr_->size()) ) { - std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1; + const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1; std::copy(str1_base_ptr_->base() + s1_r0, str1_base_ptr_->base() + s1_r0 + size, @@ -8641,27 +9195,27 @@ namespace exprtk std::string str() const { - return str0_node_ptr_->str(); + return str0_base_ptr_->str(); } char_cptr base() const { - return str0_node_ptr_->base(); + return str0_base_ptr_->base(); } std::size_t size() const { - return str0_node_ptr_->size(); + return str0_base_ptr_->size(); } range_t& range_ref() { - return str0_node_ptr_->range_ref(); + return str0_rng_node_ptr_->range_ref(); } const range_t& range_ref() const { - return str0_node_ptr_->range_ref(); + return str0_rng_node_ptr_->range_ref(); } inline typename expression_node<T>::node_type type() const @@ -8671,12 +9225,12 @@ namespace exprtk private: - bool initialised_; - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - strvar_node_ptr str0_node_ptr_; - range_ptr str0_range_ptr_; - range_ptr str1_range_ptr_; + bool initialised_; + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + str_rng_node_ptr str0_rng_node_ptr_; + range_ptr str0_range_ptr_; + range_ptr str1_range_ptr_; }; template <typename T> @@ -8693,16 +9247,16 @@ namespace exprtk typedef range_interface<T> irange_t; typedef irange_t* irange_ptr; - conditional_string_node(expression_ptr test, + conditional_string_node(expression_ptr condition, expression_ptr consequent, expression_ptr alternative) - : trinary_node<T>(details::e_default,consequent,alternative,test), + : trinary_node<T>(details::e_default,consequent,alternative,condition), initialised_(false), str0_base_ptr_ (0), str1_base_ptr_ (0), str0_range_ptr_(0), str1_range_ptr_(0), - test_ (test), + condition_ (condition), consequent_ (consequent), alternative_(alternative) { @@ -8749,14 +9303,18 @@ namespace exprtk { if (initialised_) { + assert(condition_ ); + assert(consequent_ ); + assert(alternative_); + std::size_t r0 = 0; std::size_t r1 = 0; - if (is_true(test_)) + if (is_true(condition_)) { consequent_->value(); - range_t& range = str0_range_ptr_->range_ref(); + const range_t& range = str0_range_ptr_->range_ref(); if (range(r0, r1, str0_base_ptr_->size())) { @@ -8774,7 +9332,7 @@ namespace exprtk { alternative_->value(); - range_t& range = str1_range_ptr_->range_ref(); + const range_t& range = str1_range_ptr_->range_ref(); if (range(r0, r1, str1_base_ptr_->size())) { @@ -8833,7 +9391,7 @@ namespace exprtk mutable range_t range_; mutable std::string value_; - expression_ptr test_; + expression_ptr condition_; expression_ptr consequent_; expression_ptr alternative_; }; @@ -8852,13 +9410,13 @@ namespace exprtk typedef range_interface<T> irange_t; typedef irange_t* irange_ptr; - cons_conditional_str_node(expression_ptr test, + cons_conditional_str_node(expression_ptr condition, expression_ptr consequent) - : binary_node<T>(details::e_default, consequent, test), + : binary_node<T>(details::e_default, consequent, condition), initialised_(false), str0_base_ptr_ (0), str0_range_ptr_(0), - test_ (test), + condition_ (condition), consequent_(consequent) { range_.n0_c = std::make_pair<bool,std::size_t>(true,0); @@ -8887,11 +9445,14 @@ namespace exprtk { if (initialised_) { - if (is_true(test_)) + assert(condition_ ); + assert(consequent_); + + if (is_true(condition_)) { consequent_->value(); - range_t& range = str0_range_ptr_->range_ref(); + const range_t& range = str0_range_ptr_->range_ref(); std::size_t r0 = 0; std::size_t r1 = 0; @@ -8951,7 +9512,7 @@ namespace exprtk mutable range_t range_; mutable std::string value_; - expression_ptr test_; + expression_ptr condition_; expression_ptr consequent_; }; @@ -8962,33 +9523,34 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef string_base_node<T>* str_base_ptr; - typedef range_pack <T> range_t; - typedef range_t* range_ptr; - typedef range_interface<T> irange_t; - typedef irange_t* irange_ptr; + typedef expression_node <T>* expression_ptr; + typedef string_base_node<T>* str_base_ptr; + typedef range_pack <T> range_t; + typedef range_t* range_ptr; + typedef range_interface<T> irange_t; + typedef irange_t* irange_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) - : final_node_(arg_list.back()), - final_deletable_(branch_deletable(final_node_)), - initialised_(false), + explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) + : initialised_(false), str_base_ptr_ (0), str_range_ptr_(0) { - if (0 == final_node_) + construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); + + if (0 == final_node_.first) return; - else if (!is_generally_string_node(final_node_)) + else if (!is_generally_string_node(final_node_.first)) return; - str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_); + str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); if (0 == str_base_ptr_) return; - str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_); + str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); if (0 == str_range_ptr_) return; @@ -9000,41 +9562,22 @@ namespace exprtk const std::size_t arg_list_size = arg_list.size() - 1; arg_list_.resize(arg_list_size); - delete_branch_.resize(arg_list_size); for (std::size_t i = 0; i < arg_list_size; ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i], arg_list[i]); } else { - arg_list_ .clear(); - delete_branch_.clear(); + arg_list_.clear(); return; } } } } - ~str_vararg_node() - { - if (final_node_ && final_deletable_) - { - destroy_node(final_node_); - } - - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { if (!arg_list_.empty()) @@ -9042,7 +9585,7 @@ namespace exprtk VarArgFunction::process(arg_list_); } - final_node_->value(); + final_node_.first->value(); return std::numeric_limits<T>::quiet_NaN(); } @@ -9077,15 +9620,26 @@ namespace exprtk return expression_node<T>::e_stringvararg; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(final_node_, node_delete_list); + expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); + } + + std::size_t node_depth() const + { + return std::max( + expression_node<T>::ndb_t::compute_node_depth(final_node_), + expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); + } + private: - expression_ptr final_node_; - bool final_deletable_; - bool initialised_; - str_base_ptr str_base_ptr_; - irange_ptr str_range_ptr_; - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + bool initialised_; + branch_t final_node_; + str_base_ptr str_base_ptr_; + irange_ptr str_range_ptr_; + std::vector<branch_t> arg_list_; }; #endif @@ -9118,14 +9672,14 @@ namespace exprtk template <typename T> \ struct sf##NN##_op : public sf_base<T> \ { \ - typedef typename sf_base<T>::Type Type; \ + typedef typename sf_base<T>::Type const Type; \ static inline T process(Type x, Type y, Type z) \ { \ return (OP0); \ } \ static inline std::string id() \ { \ - return OP1; \ + return (OP1); \ } \ }; \ @@ -9182,12 +9736,15 @@ namespace exprtk template <typename T> \ struct sf##NN##_op : public sf_base<T> \ { \ - typedef typename sf_base<T>::Type Type; \ + typedef typename sf_base<T>::Type const Type; \ static inline T process(Type x, Type y, Type z, Type w) \ { \ return (OP0); \ } \ - static inline std::string id() { return OP1; } \ + static inline std::string id() \ + { \ + return (OP1); \ + } \ }; \ define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") @@ -9326,6 +9883,10 @@ namespace exprtk inline T value() const { + assert(trinary_node<T>::branch_[0].first); + assert(trinary_node<T>::branch_[1].first); + assert(trinary_node<T>::branch_[2].first); + const T x = trinary_node<T>::branch_[0].first->value(); const T y = trinary_node<T>::branch_[1].first->value(); const T z = trinary_node<T>::branch_[2].first->value(); @@ -9351,6 +9912,11 @@ namespace exprtk inline T value() const { + assert(quaternary_node<T>::branch_[0].first); + assert(quaternary_node<T>::branch_[1].first); + assert(quaternary_node<T>::branch_[2].first); + assert(quaternary_node<T>::branch_[3].first); + const T x = quaternary_node<T>::branch_[0].first->value(); const T y = quaternary_node<T>::branch_[1].first->value(); const T z = quaternary_node<T>::branch_[2].first->value(); @@ -9434,47 +10000,31 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) { - arg_list_ .resize(arg_list.size()); - delete_branch_.resize(arg_list.size()); + arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i],arg_list[i]); } else { arg_list_.clear(); - delete_branch_.clear(); return; } } } - ~vararg_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { - if (!arg_list_.empty()) - return VarArgFunction::process(arg_list_); - else - return std::numeric_limits<T>::quiet_NaN(); + return VarArgFunction::process(arg_list_); } inline typename expression_node<T>::node_type type() const @@ -9482,10 +10032,19 @@ namespace exprtk return expression_node<T>::e_vararg; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + private: - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + std::vector<branch_t> arg_list_; }; template <typename T, typename VarArgFunction> @@ -9497,7 +10056,7 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) + explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) { arg_list_.resize(arg_list.size()); @@ -9540,33 +10099,29 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - vectorize_node(const expression_ptr v) - : ivec_ptr_(0), - v_(v), - v_deletable_(branch_deletable(v_)) + explicit vectorize_node(const expression_ptr v) + : ivec_ptr_(0) { - if (is_ivector_node(v)) + construct_branch_pair(v_, v); + + if (is_ivector_node(v_.first)) { - ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v); + ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); } else ivec_ptr_ = 0; } - ~vectorize_node() - { - if (v_ && v_deletable_) - { - destroy_node(v_); - } - } - inline T value() const { if (ivec_ptr_) { - v_->value(); + assert(v_.first); + + v_.first->value(); + return VecFunction::process(ivec_ptr_); } else @@ -9578,11 +10133,20 @@ namespace exprtk return expression_node<T>::e_vecfunc; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(v_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(v_); + } + private: vector_interface<T>* ivec_ptr_; - expression_ptr v_; - const bool v_deletable_; + branch_t v_; }; template <typename T> @@ -9608,6 +10172,8 @@ namespace exprtk { if (var_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = var_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9646,6 +10212,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = vec_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9684,6 +10252,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = rbvec_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9722,6 +10292,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = rbvec_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9764,6 +10336,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + const T v = binary_node<T>::branch_[1].first->value(); T* vec = vds().data(); @@ -9773,8 +10347,8 @@ namespace exprtk while (vec < upper_bound) { - #define exprtk_loop(N) \ - vec[N] = v; \ + #define exprtk_loop(N) \ + vec[N] = v; \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -9909,6 +10483,8 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[1].first->value(); if (src_is_ivec_) @@ -10030,6 +10606,8 @@ namespace exprtk { if (var_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = var_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10067,6 +10645,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = vec_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10104,6 +10684,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = rbvec_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10141,6 +10723,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = rbvec_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10182,6 +10766,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + const T v = binary_node<T>::branch_[1].first->value(); T* vec = vds().data(); @@ -10327,19 +10913,22 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); + T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(vec0[N],vec1[N]); \ + #define exprtk_loop(N) \ + vec0[N] = Operation::process(vec0[N], vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10361,8 +10950,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(vec0[i],vec1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10512,20 +11101,23 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); - T* vec2 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); + T* vec2 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec2 + lud.upper_bound; while (vec2 < upper_bound) { - #define exprtk_loop(N) \ - vec2[N] = Operation::process(vec0[N],vec1[N]); \ + #define exprtk_loop(N) \ + vec2[N] = Operation::process(vec0[N], vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10548,8 +11140,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec2[i] = Operation::process(vec0[i],vec1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10671,19 +11263,22 @@ namespace exprtk { if (vec0_node_ptr_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); const T v = binary_node<T>::branch_[1].first->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { - #define exprtk_loop(N) \ - vec1[N] = Operation::process(vec0[N],v); \ + #define exprtk_loop(N) \ + vec1[N] = Operation::process(vec0[N], v); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10705,8 +11300,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec1[i] = Operation::process(vec0[i],v); ++i; } \ + #define case_stmt(N) \ + case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10826,19 +11421,22 @@ namespace exprtk { if (vec1_node_ptr_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + const T v = binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - T* vec0 = vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); + T* vec0 = vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(v,vec1[N]); \ + #define exprtk_loop(N) \ + vec0[N] = Operation::process(v, vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10860,8 +11458,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(v,vec1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10942,15 +11540,15 @@ namespace exprtk { bool vec0_is_ivec = false; - if (is_vector_node(unary_node<T>::branch_)) + if (is_vector_node(unary_node<T>::branch_.first)) { - vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_); + vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_.first); } - else if (is_ivector_node(unary_node<T>::branch_)) + else if (is_ivector_node(unary_node<T>::branch_.first)) { vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); - if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_))) + if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_.first))) { vec0_node_ptr_ = vi->vec(); vec0_is_ivec = true; @@ -10977,12 +11575,14 @@ namespace exprtk inline T value() const { - unary_node<T>::branch_->value(); + assert(unary_node<T>::branch_.first); + + unary_node<T>::branch_.first->value(); if (vec0_node_ptr_) { - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; @@ -11090,6 +11690,9 @@ namespace exprtk inline T value() const { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + return ( std::not_equal_to<T>() (T(0),binary_node<T>::branch_[0].first->value()) && @@ -11114,6 +11717,9 @@ namespace exprtk inline T value() const { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + return ( std::not_equal_to<T>() (T(0),binary_node<T>::branch_[0].first->value()) || @@ -11133,16 +11739,11 @@ namespace exprtk typedef std::pair<expression_ptr,bool> branch_t; typedef IFunction ifunction; - function_N_node(ifunction* func) + explicit function_N_node(ifunction* func) : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)), parameter_count_(func->param_count) {} - ~function_N_node() - { - cleanup_branches::execute<T,N>(branch_); - } - template <std::size_t NumBranches> bool init_branches(expression_ptr (&b)[NumBranches]) { @@ -11409,6 +12010,16 @@ namespace exprtk return expression_node<T>::e_function; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); + } + private: ifunction* function_; @@ -11424,7 +12035,7 @@ namespace exprtk typedef expression_node<T>* expression_ptr; typedef IFunction ifunction; - function_N_node(ifunction* func) + explicit function_N_node(ifunction* func) : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) {} @@ -11466,17 +12077,6 @@ namespace exprtk value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); } - ~vararg_function_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) - { - destroy_node(arg_list_[i]); - } - } - } - inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const { return this < (&fn); @@ -11498,6 +12098,22 @@ namespace exprtk return expression_node<T>::e_vafunction; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) + { + node_delete_list.push_back(&arg_list_[i]); + } + } + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + private: inline void populate_value_list() const @@ -11533,15 +12149,23 @@ namespace exprtk typedef std::vector<type_store_t> typestore_list_t; typedef std::vector<range_data_type_t> range_list_t; - generic_function_node(const std::vector<expression_ptr>& arg_list, - GenericFunction* func = (GenericFunction*)(0)) + explicit generic_function_node(const std::vector<expression_ptr>& arg_list, + GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) : function_(func), arg_list_(arg_list) {} virtual ~generic_function_node() + {} + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const { - cleanup_branches::execute(branch_); + return expression_node<T>::ndb_t::compute_node_depth(branch_); } virtual bool init_branches() @@ -11549,7 +12173,7 @@ namespace exprtk expr_as_vec1_store_.resize(arg_list_.size(),T(0) ); typestore_list_ .resize(arg_list_.size(),type_store_t() ); range_list_ .resize(arg_list_.size(),range_data_type_t()); - branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false)); + branch_ .resize(arg_list_.size(),branch_t(reinterpret_cast<expression_ptr>(0),false)); for (std::size_t i = 0; i < arg_list_.size(); ++i) { @@ -11591,7 +12215,7 @@ namespace exprtk if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) return false; - range_t& rp = ri->range_ref(); + const range_t& rp = ri->range_ref(); if ( rp.const_range() && @@ -11670,11 +12294,11 @@ namespace exprtk if (rdt.range) { - range_t& rp = (*rdt.range); - std::size_t r0 = 0; - std::size_t r1 = 0; + const range_t& rp = (*rdt.range); + std::size_t r0 = 0; + std::size_t r1 = 0; - if (rp(r0,r1,rdt.size)) + if (rp(r0, r1, rdt.size)) { type_store_t& ts = typestore_list_[i]; @@ -11740,7 +12364,10 @@ namespace exprtk typedef typename StringFunction::parameter_list_t parameter_list_t; const T result = (*gen_function_t::function_) - (ret_string_, parameter_list_t(gen_function_t::typestore_list_)); + ( + ret_string_, + parameter_list_t(gen_function_t::typestore_list_) + ); range_.n1_c.second = ret_string_.size() - 1; range_.cache.second = range_.n1_c.second; @@ -11812,8 +12439,11 @@ namespace exprtk { typedef typename GenericFunction::parameter_list_t parameter_list_t; - return (*gen_function_t::function_)(param_seq_index_, - parameter_list_t(gen_function_t::typestore_list_)); + return (*gen_function_t::function_) + ( + param_seq_index_, + parameter_list_t(gen_function_t::typestore_list_) + ); } } @@ -11854,9 +12484,12 @@ namespace exprtk { typedef typename StringFunction::parameter_list_t parameter_list_t; - const T result = (*str_function_t::function_)(param_seq_index_, - str_function_t::ret_string_, - parameter_list_t(str_function_t::typestore_list_)); + const T result = (*str_function_t::function_) + ( + param_seq_index_, + str_function_t::ret_string_, + parameter_list_t(str_function_t::typestore_list_) + ); str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1; str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; @@ -11951,30 +12584,25 @@ namespace exprtk typedef expression_node<T>* expression_ptr; typedef results_context<T> results_context_t; + typedef std::pair<expression_ptr,bool> branch_t; return_envelope_node(expression_ptr body, results_context_t& rc) : results_context_(&rc ), - return_invoked_ (false), - body_ (body ), - body_deletable_ (branch_deletable(body_)) - {} - - ~return_envelope_node() + return_invoked_ (false) { - if (body_ && body_deletable_) - { - destroy_node(body_); - } + construct_branch_pair(body_, body); } inline T value() const { + assert(body_.first); + try { return_invoked_ = false; results_context_->clear(); - return body_->value(); + return body_.first->value(); } catch(const return_exception&) { @@ -11993,12 +12621,21 @@ namespace exprtk return &return_invoked_; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(body_); + } + private: results_context_t* results_context_; - mutable bool return_invoked_; - expression_ptr body_; - const bool body_deletable_; + mutable bool return_invoked_; + branch_t body_; }; #endif @@ -12345,11 +12982,23 @@ namespace exprtk } template <typename T> - inline T value(T* t) + inline T value(std::pair<details::expression_node<T>*,bool> n) + { + return n.first->value(); + } + + template <typename T> + inline T value(const T* t) { return (*t); } + template <typename T> + inline T value(const T& t) + { + return t; + } + template <typename T> struct vararg_add_op : public opr_base<T> { @@ -12597,16 +13246,16 @@ namespace exprtk static inline T process_4(const Sequence& arg_list) { return std::min<T>( - std::min<T>(value(arg_list[0]),value(arg_list[1])), - std::min<T>(value(arg_list[2]),value(arg_list[3]))); + std::min<T>(value(arg_list[0]), value(arg_list[1])), + std::min<T>(value(arg_list[2]), value(arg_list[3]))); } template <typename Sequence> static inline T process_5(const Sequence& arg_list) { return std::min<T>( - std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])), - std::min<T>(value(arg_list[2]),value(arg_list[3]))), + std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), + std::min<T>(value(arg_list[2]), value(arg_list[3]))), value(arg_list[4])); } }; @@ -12668,16 +13317,16 @@ namespace exprtk static inline T process_4(const Sequence& arg_list) { return std::max<T>( - std::max<T>(value(arg_list[0]),value(arg_list[1])), - std::max<T>(value(arg_list[2]),value(arg_list[3]))); + std::max<T>(value(arg_list[0]), value(arg_list[1])), + std::max<T>(value(arg_list[2]), value(arg_list[3]))); } template <typename Sequence> static inline T process_5(const Sequence& arg_list) { return std::max<T>( - std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])), - std::max<T>(value(arg_list[2]),value(arg_list[3]))), + std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), + std::max<T>(value(arg_list[2]), value(arg_list[3]))), value(arg_list[4])); } }; @@ -13181,7 +13830,7 @@ namespace exprtk for (std::size_t i = 1; i < vec_size; ++i) { - T v_i = vec[i]; + const T v_i = vec[i]; if (v_i < result) result = v_i; @@ -13205,7 +13854,7 @@ namespace exprtk for (std::size_t i = 1; i < vec_size; ++i) { - T v_i = vec[i]; + const T v_i = vec[i]; if (v_i > result) result = v_i; @@ -13296,8 +13945,8 @@ namespace exprtk { public: - virtual ~cob_base_node() - {} + virtual ~cob_base_node() + {} inline virtual operator_type operation() const { @@ -13516,24 +14165,17 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; typedef Operation operation_t; - explicit unary_branch_node(expression_ptr brnch) - : branch_(brnch), - branch_deletable_(branch_deletable(branch_)) - {} - - ~unary_branch_node() + explicit unary_branch_node(expression_ptr branch) { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(branch_->value()); + return Operation::process(branch_.first->value()); } inline typename expression_node<T>::node_type type() const @@ -13548,12 +14190,22 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_; + return branch_.first; } inline void release() { - branch_deletable_ = false; + branch_.second = false; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -13561,8 +14213,7 @@ namespace exprtk unary_branch_node(unary_branch_node<T,Operation>&); unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&); - expression_ptr branch_; - bool branch_deletable_; + branch_t branch_; }; template <typename T> struct is_const { enum {result = 0}; }; @@ -14392,7 +15043,7 @@ namespace exprtk inline T3 t3() const { - return t2_; + return t3_; } std::string type_id() const @@ -14623,20 +15274,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit vob_node(const T& var, const expression_ptr brnch) + explicit vob_node(const T& var, const expression_ptr branch) : v_(var) { - init_branches<1>(branch_,brnch); - } - - ~vob_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(v_,branch_[0].first->value()); + assert(branch_.first); + return Operation::process(v_,branch_.first->value()); } inline operator_type operation() const @@ -14651,7 +15298,17 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14660,7 +15317,7 @@ namespace exprtk vob_node<T,Operation>& operator=(const vob_node<T,Operation>&); const T& v_; - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename Operation> @@ -14673,20 +15330,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit bov_node(const expression_ptr brnch, const T& var) + explicit bov_node(const expression_ptr branch, const T& var) : v_(var) { - init_branches<1>(branch_,brnch); - } - - ~bov_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(branch_[0].first->value(),v_); + assert(branch_.first); + return Operation::process(branch_.first->value(),v_); } inline operator_type operation() const @@ -14701,7 +15354,17 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14710,7 +15373,7 @@ namespace exprtk bov_node<T,Operation>& operator=(const bov_node<T,Operation>&); const T& v_; - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename Operation> @@ -14723,20 +15386,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit cob_node(const T const_var, const expression_ptr brnch) + explicit cob_node(const T const_var, const expression_ptr branch) : c_(const_var) { - init_branches<1>(branch_,brnch); - } - - ~cob_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(c_,branch_[0].first->value()); + assert(branch_.first); + return Operation::process(c_,branch_.first->value()); } inline operator_type operation() const @@ -14756,13 +15415,23 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; } inline expression_node<T>* move_branch(const std::size_t&) { - branch_[0].second = false; - return branch_[0].first; + branch_.second = false; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14771,7 +15440,7 @@ namespace exprtk cob_node<T,Operation>& operator=(const cob_node<T,Operation>&); const T c_; - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename Operation> @@ -14784,20 +15453,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit boc_node(const expression_ptr brnch, const T const_var) + explicit boc_node(const expression_ptr branch, const T const_var) : c_(const_var) { - init_branches<1>(branch_,brnch); - } - - ~boc_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(branch_[0].first->value(),c_); + assert(branch_.first); + return Operation::process(branch_.first->value(),c_); } inline operator_type operation() const @@ -14817,13 +15482,23 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; } inline expression_node<T>* move_branch(const std::size_t&) { - branch_[0].second = false; - return branch_[0].first; + branch_.second = false; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14832,7 +15507,7 @@ namespace exprtk boc_node<T,Operation>& operator=(const boc_node<T,Operation>&); const T c_; - branch_t branch_[1]; + branch_t branch_; }; #ifndef exprtk_disable_string_capabilities @@ -15158,8 +15833,8 @@ namespace exprtk std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; - range_t& range0 = (*str0_range_ptr_); - range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); if ( range0(str0_r0, str0_r1, str0_base_ptr_->size()) && @@ -15294,19 +15969,15 @@ namespace exprtk typedef std::pair<expression_ptr, bool> branch_t; typedef PowOp operation_t; - explicit bipow_node(expression_ptr brnch) + explicit bipow_node(expression_ptr branch) { - init_branches<1>(branch_, brnch); - } - - ~bipow_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return PowOp::result(branch_[0].first->value()); + assert(branch_.first); + return PowOp::result(branch_.first->value()); } inline typename expression_node<T>::node_type type() const @@ -15314,12 +15985,22 @@ namespace exprtk return expression_node<T>::e_ipow; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: bipow_node(const bipow_node<T,PowOp>&); bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&); - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename PowOp> @@ -15361,19 +16042,15 @@ namespace exprtk typedef std::pair<expression_ptr, bool> branch_t; typedef PowOp operation_t; - explicit bipowninv_node(expression_ptr brnch) + explicit bipowninv_node(expression_ptr branch) { - init_branches<1>(branch_, brnch); - } - - ~bipowninv_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return (T(1) / PowOp::result(branch_[0].first->value())); + assert(branch_.first); + return (T(1) / PowOp::result(branch_.first->value())); } inline typename expression_node<T>::node_type type() const @@ -15381,12 +16058,22 @@ namespace exprtk return expression_node<T>::e_ipowinv; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: bipowninv_node(const bipowninv_node<T,PowOp>&); bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&); - branch_t branch_[1]; + branch_t branch_; }; template <typename T> @@ -15535,37 +16222,55 @@ namespace exprtk template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) { - return allocate<ResultNode>(operation, branch[0]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) { - return allocate<ResultNode>(operation, branch[0], branch[1]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) { - return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) { - return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) { - return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) { - return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); + result->node_depth(); + return result; } template <typename node_type> @@ -15580,89 +16285,128 @@ namespace exprtk template <typename, typename> class Sequence> inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const { - return (new node_type(seq)); + expression_node<typename node_type::value_type>* + result = (new node_type(seq)); + result->node_depth(); + return result; } template <typename node_type, typename T1> inline expression_node<typename node_type::value_type>* allocate(T1& t1) const { - return (new node_type(t1)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1)); + result->node_depth(); + return result; } template <typename node_type, typename T1> inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const { - return (new node_type(t1)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3> inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3, typename T4> inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3> inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3, typename T4> inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3, typename T4, typename T5> inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const { - return (new node_type(t1, t2, t3, t4, t5)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5)); + result->node_depth(); + return result; } template <typename node_type, @@ -15670,7 +16414,10 @@ namespace exprtk inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, const T3& t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, @@ -15679,7 +16426,10 @@ namespace exprtk inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, const T3& t3, const T4& t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, @@ -15689,7 +16439,10 @@ namespace exprtk const T3& t3, const T4& t4, const T5& t5) const { - return (new node_type(t1, t2, t3, t4, t5)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5)); + result->node_depth(); + return result; } template <typename node_type, @@ -15699,7 +16452,10 @@ namespace exprtk const T3& t3, const T4& t4, const T5& t5, const T6& t6) const { - return (new node_type(t1, t2, t3, t4, t5, t6)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6)); + result->node_depth(); + return result; } template <typename node_type, @@ -15711,7 +16467,10 @@ namespace exprtk const T5& t5, const T6& t6, const T7& t7) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); + result->node_depth(); + return result; } template <typename node_type, @@ -15724,7 +16483,10 @@ namespace exprtk const T5& t5, const T6& t6, const T7& t7, const T8& t8) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); + result->node_depth(); + return result; } template <typename node_type, @@ -15738,7 +16500,10 @@ namespace exprtk const T7& t7, const T8& t8, const T9& t9) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); + result->node_depth(); + return result; } template <typename node_type, @@ -15753,14 +16518,20 @@ namespace exprtk const T7& t7, const T8& t8, const T9& t9, const T10& t10) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3> inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, @@ -15769,7 +16540,10 @@ namespace exprtk inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3, T4 t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, @@ -15780,7 +16554,10 @@ namespace exprtk T3 t3, T4 t4, T5 t5) const { - return (new node_type(t1, t2, t3, t4, t5)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5)); + result->node_depth(); + return result; } template <typename node_type, @@ -15791,7 +16568,10 @@ namespace exprtk T3 t3, T4 t4, T5 t5, T6 t6) const { - return (new node_type(t1, t2, t3, t4, t5, t6)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6)); + result->node_depth(); + return result; } template <typename node_type, @@ -15803,12 +16583,19 @@ namespace exprtk T5 t5, T6 t6, T7 t7) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); + result->node_depth(); + return result; } template <typename T> void inline free(expression_node<T>*& e) const { + exprtk_debug(("node_allocator::free() - deleting expression_node " + "type: %03d addr: %p\n", + static_cast<int>(e->type()), + reinterpret_cast<void*>(e))); delete e; e = 0; } @@ -15971,83 +16758,84 @@ namespace exprtk virtual ~ifunction() {} - #define empty_method_body \ + #define empty_method_body(N) \ { \ + exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ return std::numeric_limits<T>::quiet_NaN(); \ } \ inline virtual T operator() () - empty_method_body + empty_method_body(0) - inline virtual T operator() (const T&) - empty_method_body + inline virtual T operator() (const T&) + empty_method_body(1) - inline virtual T operator() (const T&,const T&) - empty_method_body + inline virtual T operator() (const T&,const T&) + empty_method_body(2) - inline virtual T operator() (const T&, const T&, const T&) - empty_method_body + inline virtual T operator() (const T&, const T&, const T&) + empty_method_body(3) inline virtual T operator() (const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(4) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(5) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(6) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(7) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(8) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(9) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(10) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&) - empty_method_body + const T&) + empty_method_body(11) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(12) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(13) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(14) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(15) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(16) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(17) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(18) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(19) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(20) #undef empty_method_body @@ -16064,7 +16852,7 @@ namespace exprtk inline virtual T operator() (const std::vector<T>&) { - exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n")); + exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); return std::numeric_limits<T>::quiet_NaN(); } }; @@ -16095,7 +16883,7 @@ namespace exprtk #define igeneric_function_empty_body(N) \ { \ - exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \ + exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ return std::numeric_limits<T>::quiet_NaN(); \ } \ @@ -16150,7 +16938,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} + explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} inline T operator() () { return f(); } ff00_functor f; @@ -16160,7 +16948,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} + explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} inline T operator() (const T& v0) { return f(v0); } ff01_functor f; @@ -16170,7 +16958,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} + explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} inline T operator() (const T& v0, const T& v1) { return f(v0, v1); } ff02_functor f; @@ -16180,7 +16968,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} + explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2) { return f(v0, v1, v2); } ff03_functor f; @@ -16190,7 +16978,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} + explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) { return f(v0, v1, v2, v3); } ff04_functor f; @@ -16200,7 +16988,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} + explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) { return f(v0, v1, v2, v3, v4); } ff05_functor f; @@ -16210,7 +16998,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} + explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) { return f(v0, v1, v2, v3, v4, v5); } ff06_functor f; @@ -16220,7 +17008,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} + explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6) { return f(v0, v1, v2, v3, v4, v5, v6); } @@ -16231,7 +17019,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} + explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7) { return f(v0, v1, v2, v3, v4, v5, v6, v7); } @@ -16242,7 +17030,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} + explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8) { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } @@ -16253,7 +17041,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} + explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } @@ -16264,7 +17052,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} + explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } @@ -16275,7 +17063,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} + explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11) @@ -16287,7 +17075,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} + explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11, const T& v12) @@ -16299,7 +17087,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} + explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11, const T& v12, const T& v13) @@ -16311,7 +17099,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} + explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) @@ -16348,6 +17136,27 @@ namespace exprtk : size(0) {} + struct deleter + { + #define exprtk_define_process(Type) \ + static inline void process(std::pair<bool,Type*>& n) \ + { \ + delete n.second; \ + } \ + + exprtk_define_process(variable_node_t ) + exprtk_define_process(vector_t ) + #ifndef exprtk_disable_string_capabilities + exprtk_define_process(stringvar_node_t) + #endif + + #undef exprtk_define_process + + template <typename DeleteType> + static inline void process(std::pair<bool,DeleteType*>&) + {} + }; + inline bool symbol_exists(const std::string& symbol_name) const { if (symbol_name.empty()) @@ -16583,16 +17392,6 @@ namespace exprtk if (map.end() != itr) { - struct deleter - { - static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } - static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } - #ifndef exprtk_disable_string_capabilities - static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } - #endif - static inline void process(std::pair<bool,function_t*>&) { } - }; - if (delete_node) { deleter::process((*itr).second); @@ -16629,16 +17428,6 @@ namespace exprtk inline void clear(const bool delete_node = true) { - struct deleter - { - static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } - static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } - static inline void process(std::pair<bool,function_t*>&) { } - #ifndef exprtk_disable_string_capabilities - static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } - #endif - }; - if (!map.empty()) { if (delete_node) @@ -16704,20 +17493,20 @@ namespace exprtk } }; - typedef details::expression_node<T>* expression_ptr; - typedef typename details::variable_node<T> variable_t; - typedef typename details::vector_holder<T> vector_holder_t; - typedef variable_t* variable_ptr; + typedef details::expression_node<T>* expression_ptr; + typedef typename details::variable_node<T> variable_t; + typedef typename details::vector_holder<T> vector_holder_t; + typedef variable_t* variable_ptr; #ifndef exprtk_disable_string_capabilities typedef typename details::stringvar_node<T> stringvar_t; - typedef stringvar_t* stringvar_ptr; + typedef stringvar_t* stringvar_ptr; #endif - typedef ifunction <T> function_t; - typedef ivararg_function <T> vararg_function_t; - typedef igeneric_function<T> generic_function_t; - typedef function_t* function_ptr; - typedef vararg_function_t* vararg_function_ptr; - typedef generic_function_t* generic_function_ptr; + typedef ifunction <T> function_t; + typedef ivararg_function <T> vararg_function_t; + typedef igeneric_function<T> generic_function_t; + typedef function_t* function_ptr; + typedef vararg_function_t* vararg_function_ptr; + typedef generic_function_t* generic_function_ptr; static const std::size_t lut_size = 256; @@ -16726,16 +17515,16 @@ namespace exprtk { struct st_data { - type_store<typename details::variable_node<T>,T> variable_store; + type_store<variable_t , T > variable_store; + type_store<function_t , function_t > function_store; + type_store<vararg_function_t , vararg_function_t > vararg_function_store; + type_store<generic_function_t, generic_function_t> generic_function_store; + type_store<generic_function_t, generic_function_t> string_function_store; + type_store<generic_function_t, generic_function_t> overload_function_store; + type_store<vector_holder_t , vector_holder_t > vector_store; #ifndef exprtk_disable_string_capabilities - type_store<typename details::stringvar_node<T>,std::string> stringvar_store; + type_store<stringvar_t , std::string > stringvar_store; #endif - type_store<ifunction<T>,ifunction<T> > function_store; - type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store; - type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store; - type_store<igeneric_function<T>,igeneric_function<T> > string_function_store; - type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store; - type_store<vector_holder_t,vector_holder_t> vector_store; st_data() { @@ -16785,7 +17574,7 @@ namespace exprtk data_(st_data::create()) {} - control_block(st_data* data) + explicit control_block(st_data* data) : ref_count(1), data_(data) {} @@ -17117,7 +17906,7 @@ namespace exprtk else if (symbol_exists(variable_name)) return false; else - return local_data().variable_store.add(variable_name,t,is_constant); + return local_data().variable_store.add(variable_name, t, is_constant); } inline bool add_constant(const std::string& constant_name, const T& value) @@ -17132,7 +17921,7 @@ namespace exprtk local_data().local_symbol_list_.push_back(value); T& t = local_data().local_symbol_list_.back(); - return add_variable(constant_name,t,true); + return add_variable(constant_name, t, true); } #ifndef exprtk_disable_string_capabilities @@ -17145,7 +17934,7 @@ namespace exprtk else if (symbol_exists(stringvar_name)) return false; else - return local_data().stringvar_store.add(stringvar_name,s,is_constant); + return local_data().stringvar_store.add(stringvar_name, s, is_constant); } #endif @@ -17181,30 +17970,22 @@ namespace exprtk return false; else if (symbol_exists(function_name)) return false; - else if ( - ( - (generic_function_t::e_rtrn_scalar == function.rtrn_type) || - (generic_function_t::e_rtrn_string == function.rtrn_type) - ) && - std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|") - ) - return false; - else if ( - (generic_function_t::e_rtrn_overload == function.rtrn_type) && - std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:") - ) - return false; - - switch (function.rtrn_type) + else { - case generic_function_t::e_rtrn_scalar : - return local_data().generic_function_store.add(function_name,function); + switch (function.rtrn_type) + { + case generic_function_t::e_rtrn_scalar : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().generic_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_string : - return local_data().string_function_store.add(function_name,function); + case generic_function_t::e_rtrn_string : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().string_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_overload : - return local_data().overload_function_store.add(function_name,function); + case generic_function_t::e_rtrn_overload : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? + local_data().overload_function_store.add(function_name,function) : false; + } } return false; @@ -17270,30 +18051,22 @@ namespace exprtk return false; else if (symbol_exists(function_name,false)) return false; - else if ( - ( - (generic_function_t::e_rtrn_scalar == function.rtrn_type) || - (generic_function_t::e_rtrn_string == function.rtrn_type) - ) && - std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|") - ) - return false; - else if ( - generic_function_t::e_rtrn_overload && - std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:") - ) - return false; - - switch (function.rtrn_type) + else { - case generic_function_t::e_rtrn_scalar : - return local_data().generic_function_store.add(function_name,function); + switch (function.rtrn_type) + { + case generic_function_t::e_rtrn_scalar : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().generic_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_string : - return local_data().string_function_store.add(function_name,function); + case generic_function_t::e_rtrn_string : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().string_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_overload : - return local_data().overload_function_store.add(function_name,function); + case generic_function_t::e_rtrn_overload : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? + local_data().overload_function_store.add(function_name,function) : false; + } } return false; @@ -17323,7 +18096,7 @@ namespace exprtk else if (0 == v_size) return false; else - return local_data().vector_store.add(vector_name,v,v_size); + return local_data().vector_store.add(vector_name, v, v_size); } template <typename Allocator> @@ -17686,7 +18459,7 @@ namespace exprtk ('_' != symbol[i]) ) { - if (('.' == symbol[i]) && (i < (symbol.size() - 1))) + if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) continue; else return false; @@ -17712,7 +18485,7 @@ namespace exprtk ('_' != symbol[i]) ) { - if (('.' == symbol[i]) && (i < (symbol.size() - 1))) + if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) continue; else return false; @@ -17794,7 +18567,7 @@ namespace exprtk return_invoked(&retinv_null) {} - control_block(expression_ptr e) + explicit control_block(expression_ptr e) : ref_count(1), expr (e), results (0), @@ -17821,13 +18594,13 @@ namespace exprtk case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); break; - case e_data : delete (T*)(local_data_list[i].pointer); + case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); break; - case e_vecdata : delete [] (T*)(local_data_list[i].pointer); + case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); break; - case e_string : delete (std::string*)(local_data_list[i].pointer); + case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); break; default : break; @@ -17887,7 +18660,7 @@ namespace exprtk control_block_->ref_count++; } - expression(const symbol_table<T>& symbol_table) + explicit expression(const symbol_table<T>& symbol_table) : control_block_(0) { set_expression(new details::null_node<T>()); @@ -17946,6 +18719,9 @@ namespace exprtk inline T value() const { + assert(control_block_ ); + assert(control_block_->expr); + return control_block_->expr->value(); } @@ -18103,7 +18879,7 @@ namespace exprtk } control_block* control_block_; - symtab_list_t symbol_table_list_; + symtab_list_t symbol_table_list_; friend class parser<T>; friend class expression_helper<T>; @@ -18162,7 +18938,8 @@ namespace exprtk e_numeric = 4, e_symtab = 5, e_lexer = 6, - e_helper = 7 + e_helper = 7, + e_parser = 8 }; struct type @@ -18220,6 +18997,7 @@ namespace exprtk case e_symtab : return std::string("Symbol Error" ); case e_lexer : return std::string("Lexer Error" ); case e_helper : return std::string("Helper Error" ); + case e_parser : return std::string("Parser Error" ); default : return std::string("Unknown Error"); } } @@ -18508,7 +19286,7 @@ namespace exprtk typedef variable_node_t* variable_node_ptr; typedef parser<T> parser_t; - scope_element_manager(parser<T>& p) + explicit scope_element_manager(parser<T>& p) : parser_(p), input_param_cnt_(0) {} @@ -18619,26 +19397,24 @@ namespace exprtk inline void free_element(scope_element& se) { - #ifdef exprtk_enable_debugging exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); - #endif switch (se.type) { - case scope_element::e_variable : if (se.data ) delete (T*) se.data; - if (se.var_node) delete se.var_node; + case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); + delete se.var_node; break; - case scope_element::e_vector : if (se.data ) delete[] (T*) se.data; - if (se.vec_node) delete se.vec_node; + case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); + delete se.vec_node; break; - case scope_element::e_vecelem : if (se.var_node) delete se.var_node; + case scope_element::e_vecelem : delete se.var_node; break; #ifndef exprtk_disable_string_capabilities - case scope_element::e_string : if (se.data ) delete (std::string*) se.data; - if (se.str_node) delete se.str_node; + case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); + delete se.str_node; break; #endif @@ -18705,7 +19481,7 @@ namespace exprtk typedef parser<T> parser_t; - scope_handler(parser<T>& p) + explicit scope_handler(parser<T>& p) : parser_(p) { parser_.state_.scope_depth++; @@ -18736,6 +19512,45 @@ namespace exprtk parser_t& parser_; }; + class stack_limit_handler + { + public: + + typedef parser<T> parser_t; + + explicit stack_limit_handler(parser<T>& p) + : parser_(p), + limit_exceeded_(false) + { + if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) + { + limit_exceeded_ = true; + parser_.set_error( + make_error(parser_error::e_parser, + "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + + " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), + exprtk_error_location)); + } + } + + ~stack_limit_handler() + { + parser_.state_.stack_depth--; + } + + bool operator!() + { + return limit_exceeded_; + } + + private: + + stack_limit_handler& operator=(const stack_limit_handler&); + + parser_t& parser_; + bool limit_exceeded_; + }; + struct symtab_store { symbol_table_list_t symtab_list_; @@ -19179,11 +19994,13 @@ namespace exprtk void reset() { - parsing_return_stmt = false; - parsing_break_stmt = false; - return_stmt_present = false; - side_effect_present = false; - scope_depth = 0; + parsing_return_stmt = false; + parsing_break_stmt = false; + return_stmt_present = false; + side_effect_present = false; + scope_depth = 0; + stack_depth = 0; + parsing_loop_stmt_count = 0; } #ifndef exprtk_enable_debugging @@ -19206,6 +20023,8 @@ namespace exprtk bool side_effect_present; bool type_check_enabled; std::size_t scope_depth; + std::size_t stack_depth; + std::size_t parsing_loop_stmt_count; }; public: @@ -19532,6 +20351,8 @@ namespace exprtk e_strength_reduction; settings_store(const std::size_t compile_options = compile_all_opts) + : max_stack_depth_(400), + max_node_depth_(10000) { load_compile_options(compile_options); } @@ -19736,6 +20557,15 @@ namespace exprtk .find(assign_opr_to_string(assignment_operation)); } + bool logic_disabled(const details::operator_type logic_operation) const + { + if (disabled_logic_set_.empty()) + return false; + else + return disabled_logic_set_.end() != disabled_logic_set_ + .find(logic_opr_to_string(logic_operation)); + } + bool arithmetic_disabled(const details::operator_type arithmetic_operation) const { if (disabled_arithmetic_set_.empty()) @@ -19940,6 +20770,16 @@ namespace exprtk return (*this); } + void set_max_stack_depth(const std::size_t mx_stack_depth) + { + max_stack_depth_ = mx_stack_depth; + } + + void set_max_node_depth(const std::size_t max_node_depth) + { + max_node_depth_ = max_node_depth; + } + private: void load_compile_options(const std::size_t compile_options) @@ -20002,6 +20842,21 @@ namespace exprtk } } + std::string logic_opr_to_string(details::operator_type opr) const + { + switch (opr) + { + case details::e_and : return "and" ; + case details::e_or : return "or" ; + case details::e_xor : return "xor" ; + case details::e_nand : return "nand"; + case details::e_nor : return "nor" ; + case details::e_xnor : return "xnor"; + case details::e_notl : return "not" ; + default : return "" ; + } + } + bool enable_replacer_; bool enable_joiner_; bool enable_numeric_check_; @@ -20023,6 +20878,9 @@ namespace exprtk disabled_entity_set_t disabled_assignment_set_; disabled_entity_set_t disabled_inequality_set_; + std::size_t max_stack_depth_; + std::size_t max_node_depth_; + friend class parser<T>; }; @@ -20042,7 +20900,8 @@ namespace exprtk #pragma warning(pop) #endif operator_joiner_2_(2), - operator_joiner_3_(3) + operator_joiner_3_(3), + loop_runtime_check_(0) { init_precompilation(); @@ -20080,8 +20939,8 @@ namespace exprtk if (settings_.replacer_enabled()) { symbol_replacer_.clear(); - symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number); - symbol_replacer_.add_replace("false","0",lexer::token::e_number); + symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); + symbol_replacer_.add_replace("false", "0", lexer::token::e_number); helper_assembly_.token_modifier_list.clear(); helper_assembly_.register_modifier(&symbol_replacer_); } @@ -20146,7 +21005,7 @@ namespace exprtk { set_error( make_error(parser_error::e_syntax, - "ERR000 - Empty expression!", + "ERR001 - Empty expression!", exprtk_error_location)); return false; @@ -20162,7 +21021,7 @@ namespace exprtk { set_error( make_error(parser_error::e_syntax, - "ERR001 - Empty expression!", + "ERR002 - Empty expression!", exprtk_error_location)); return false; @@ -20191,7 +21050,7 @@ namespace exprtk dec_.return_present_ = true; e = expression_generator_ - .return_envelope(e,results_context_,retinvk_ptr); + .return_envelope(e, results_context_, retinvk_ptr); } expr.set_expression(e); @@ -20209,7 +21068,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR002 - Invalid expression encountered", + "ERR003 - Invalid expression encountered", exprtk_error_location)); } @@ -20228,13 +21087,13 @@ namespace exprtk inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) { - expression_t expr; + expression_t expression; - expr.register_symbol_table(symtab); + expression.register_symbol_table(symtab); - compile(expression_string,expr); + compile(expression_string,expression); - return expr; + return expression; } void process_lexer_errors() @@ -20243,7 +21102,7 @@ namespace exprtk { if (lexer()[i].is_error()) { - std::string diagnostic = "ERR003 - "; + std::string diagnostic = "ERR004 - "; switch (lexer()[i].type) { @@ -20311,7 +21170,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, bracket_checker_ptr->error_token(), - "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", + "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", exprtk_error_location)); } else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner))) @@ -20323,7 +21182,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, error_token, - "ERR005 - Invalid numeric token: '" + error_token.value + "'", + "ERR006 - Invalid numeric token: '" + error_token.value + "'", exprtk_error_location)); } @@ -20341,7 +21200,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, error_token.first, - "ERR006 - Invalid token sequence: '" + + "ERR007 - Invalid token sequence: '" + error_token.first.value + "' and '" + error_token.second.value + "'", exprtk_error_location)); @@ -20361,7 +21220,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, error_token.first, - "ERR007 - Invalid token sequence: '" + + "ERR008 - Invalid token sequence: '" + error_token.first.value + "' and '" + error_token.second.value + "'", exprtk_error_location)); @@ -20455,6 +21314,16 @@ namespace exprtk unknown_symbol_resolver_ = &default_usr_; } + inline void register_loop_runtime_check(loop_runtime_check& lrtchk) + { + loop_runtime_check_ = &lrtchk; + } + + inline void clear_loop_runtime_check() + { + loop_runtime_check_ = loop_runtime_check_ptr(0); + } + private: inline bool valid_base_operation(const std::string& symbol) const @@ -20498,6 +21367,11 @@ namespace exprtk settings_.function_enabled(symbol); } + bool is_invalid_logic_operation(const details::operator_type operation) const + { + return settings_.logic_disabled(operation); + } + bool is_invalid_arithmetic_operation(const details::operator_type operation) const { return settings_.arithmetic_disabled(operation); @@ -20517,13 +21391,17 @@ namespace exprtk inline void next_token() { const std::string ct_str = current_token().value; + const std::size_t ct_pos = current_token().position; parser_helper::next_token(); const std::string depth(2 * state_.scope_depth,' '); exprtk_debug(("%s" - "prev[%s] --> curr[%s]\n", + "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", depth.c_str(), ct_str.c_str(), - current_token().value.c_str())); + static_cast<unsigned int>(ct_pos), + current_token().value.c_str(), + static_cast<unsigned int>(current_token().position), + static_cast<unsigned int>(state_.stack_depth))); } #endif @@ -20532,8 +21410,6 @@ namespace exprtk std::vector<expression_node_ptr> arg_list; std::vector<bool> side_effect_list; - expression_node_ptr result = error_node(); - scoped_vec_delete<expression_node_t> sdd((*this),arg_list); lexer::token begin_token; @@ -20554,7 +21430,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR008 - Invalid expression encountered", + "ERR009 - Invalid expression encountered", exprtk_error_location)); } @@ -20600,7 +21476,7 @@ namespace exprtk dec_.final_stmt_return_ = true; } - result = simplify(arg_list,side_effect_list); + const expression_node_ptr result = simplify(arg_list,side_effect_list); sdd.delete_ptr = (0 == result); @@ -20646,6 +21522,13 @@ namespace exprtk inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) { + stack_limit_handler slh(*this); + + if (!slh) + { + return error_node(); + } + expression_node_ptr expression = parse_branch(precedence); if (0 == expression) @@ -20663,25 +21546,25 @@ namespace exprtk switch (current_token().type) { - case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break; - case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break; - case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break; - case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break; - case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break; - case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break; - case token_t::e_swap : current_state.set(e_level00,e_level00,details::e_swap ); break; - case token_t::e_lt : current_state.set(e_level05,e_level06,details:: e_lt); break; - case token_t::e_lte : current_state.set(e_level05,e_level06,details:: e_lte); break; - case token_t::e_eq : current_state.set(e_level05,e_level06,details:: e_eq); break; - case token_t::e_ne : current_state.set(e_level05,e_level06,details:: e_ne); break; - case token_t::e_gte : current_state.set(e_level05,e_level06,details:: e_gte); break; - case token_t::e_gt : current_state.set(e_level05,e_level06,details:: e_gt); break; - case token_t::e_add : current_state.set(e_level07,e_level08,details:: e_add); break; - case token_t::e_sub : current_state.set(e_level07,e_level08,details:: e_sub); break; - case token_t::e_div : current_state.set(e_level10,e_level11,details:: e_div); break; - case token_t::e_mul : current_state.set(e_level10,e_level11,details:: e_mul); break; - case token_t::e_mod : current_state.set(e_level10,e_level11,details:: e_mod); break; - case token_t::e_pow : current_state.set(e_level12,e_level12,details:: e_pow); break; + case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break; + case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break; + case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break; + case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break; + case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break; + case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break; + case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break; + case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break; + case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break; + case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break; + case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break; + case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break; + case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break; + case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break; + case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break; + case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break; + case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break; + case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break; + case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break; default : if (token_t::e_symbol == current_token().type) { static const std::string s_and = "and"; @@ -20784,14 +21667,26 @@ namespace exprtk expression_node_ptr right_branch = error_node(); expression_node_ptr new_expression = error_node(); - if (is_invalid_arithmetic_operation(current_state.operation)) + if (is_invalid_logic_operation(current_state.operation)) { free_node(node_allocator_,expression); set_error( make_error(parser_error::e_syntax, prev_token, - "ERR009 - Invalid arithmetic operation '" + details::to_str(current_state.operation) + "'", + "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); + + return error_node(); + } + else if (is_invalid_arithmetic_operation(current_state.operation)) + { + free_node(node_allocator_,expression); + + set_error( + make_error(parser_error::e_syntax, + prev_token, + "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", exprtk_error_location)); return error_node(); @@ -20803,7 +21698,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR010 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", + "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", exprtk_error_location)); return error_node(); @@ -20815,7 +21710,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR011 - Invalid assignment operation '" + details::to_str(current_state.operation) + "'", + "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", exprtk_error_location)); return error_node(); @@ -20834,7 +21729,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR012 - Return statements cannot be part of sub-expressions", + "ERR014 - Return statements cannot be part of sub-expressions", exprtk_error_location)); return error_node(); @@ -20857,7 +21752,7 @@ namespace exprtk prev_token, !synthesis_error_.empty() ? synthesis_error_ : - "ERR013 - General parsing error at token: '" + prev_token.value + "'", + "ERR015 - General parsing error at token: '" + prev_token.value + "'", exprtk_error_location)); } @@ -20882,6 +21777,20 @@ namespace exprtk } } + if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR016 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + + " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), + exprtk_error_location)); + + free_node(node_allocator_,expression); + + return error_node(); + } + return expression; } @@ -20927,7 +21836,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR014 - Failed to find variable node in symbol table", + "ERR017 - Failed to find variable node in symbol table", exprtk_error_location)); free_node(node_allocator_,node); @@ -20945,6 +21854,31 @@ namespace exprtk return reinterpret_cast<expression_node_ptr>(0); } + struct scoped_expression_delete + { + scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) + : delete_ptr(true), + parser_(pr), + expression_(expression) + {} + + ~scoped_expression_delete() + { + if (delete_ptr) + { + free_node(parser_.node_allocator_, expression_); + } + } + + bool delete_ptr; + parser<T>& parser_; + expression_node_ptr& expression_; + + private: + + scoped_expression_delete& operator=(const scoped_expression_delete&); + }; + template <typename Type, std::size_t N> struct scoped_delete { @@ -20968,7 +21902,7 @@ namespace exprtk { for (std::size_t i = 0; i < N; ++i) { - free_node(parser_.node_allocator_,p_[i]); + free_node(parser_.node_allocator_, p_[i]); } } } @@ -21050,7 +21984,7 @@ namespace exprtk struct scoped_bool_negator { - scoped_bool_negator(bool& bb) + explicit scoped_bool_negator(bool& bb) : b(bb) { b = !b; } @@ -21062,7 +21996,7 @@ namespace exprtk struct scoped_bool_or_restorer { - scoped_bool_or_restorer(bool& bb) + explicit scoped_bool_or_restorer(bool& bb) : b(bb), original_value_(bb) {} @@ -21076,6 +22010,21 @@ namespace exprtk bool original_value_; }; + struct scoped_inc_dec + { + explicit scoped_inc_dec(std::size_t& v) + : v_(v) + { ++v_; } + + ~scoped_inc_dec() + { + assert(v_ > 0); + --v_; + } + + std::size_t& v_; + }; + inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) { expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); @@ -21107,7 +22056,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR015 - Invalid number of parameters for function: '" + function_name + "'", + "ERR018 - Invalid number of parameters for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21121,7 +22070,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR016 - Failed to generate call to function: '" + function_name + "'", + "ERR019 - Failed to generate call to function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21140,7 +22089,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR017 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", + "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", exprtk_error_location)); return error_node(); @@ -21163,7 +22112,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR018 - Expecting argument list for function: '" + function_name + "'", + "ERR021 - Expecting argument list for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21178,7 +22127,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR019 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", + "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21190,7 +22139,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR020 - Invalid number of arguments for function: '" + function_name + "'", + "ERR023 - Invalid number of arguments for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21203,7 +22152,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR021 - Invalid number of arguments for function: '" + function_name + "'", + "ERR024 - Invalid number of arguments for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21211,7 +22160,7 @@ namespace exprtk else result = expression_generator_.function(function,branch); - sd.delete_ptr = false; + sd.delete_ptr = (0 == result); return result; } @@ -21232,7 +22181,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR022 - Expecting '()' to proceed call to function: '" + function_name + "'", + "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'", exprtk_error_location)); free_node(node_allocator_,result); @@ -21257,7 +22206,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR023 - Expected a '(' at start of function call to '" + function_name + + "ERR026 - Expected a '(' at start of function call to '" + function_name + "', instead got: '" + current_token().value + "'", exprtk_error_location)); @@ -21269,7 +22218,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR024 - Expected at least one input parameter for function call '" + function_name + "'", + "ERR027 - Expected at least one input parameter for function call '" + function_name + "'", exprtk_error_location)); return 0; @@ -21295,7 +22244,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR025 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", + "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", exprtk_error_location)); return 0; @@ -21307,7 +22256,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR026 - Invalid number of input parameters passed to function '" + function_name + "'", + "ERR029 - Invalid number of input parameters passed to function '" + function_name + "'", exprtk_error_location)); return 0; @@ -21330,7 +22279,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, diagnostic_token, - "ERR027 - No entry found for base operation: " + operation_name, + "ERR030 - No entry found for base operation: " + operation_name, exprtk_error_location)); return error_node(); @@ -21377,7 +22326,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, diagnostic_token, - "ERR028 - Invalid number of input parameters for call to function: '" + operation_name + "'", + "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'", exprtk_error_location)); return error_node(); @@ -21397,7 +22346,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR029 - Expected ',' between if-statement condition and consequent", + "ERR032 - Expected ',' between if-statement condition and consequent", exprtk_error_location)); result = false; } @@ -21406,7 +22355,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR030 - Failed to parse consequent for if-statement", + "ERR033 - Failed to parse consequent for if-statement", exprtk_error_location)); result = false; } @@ -21415,7 +22364,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR031 - Expected ',' between if-statement consequent and alternative", + "ERR034 - Expected ',' between if-statement consequent and alternative", exprtk_error_location)); result = false; } @@ -21424,7 +22373,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR032 - Failed to parse alternative for if-statement", + "ERR035 - Failed to parse alternative for if-statement", exprtk_error_location)); result = false; } @@ -21433,7 +22382,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR033 - Expected ')' at the end of if-statement", + "ERR036 - Expected ')' at the end of if-statement", exprtk_error_location)); result = false; } @@ -21449,13 +22398,13 @@ namespace exprtk if (consq_is_str && alter_is_str) { return expression_generator_ - .conditional_string(condition,consequent,alternative); + .conditional_string(condition, consequent, alternative); } set_error( make_error(parser_error::e_syntax, current_token(), - "ERR034 - Return types of ternary if-statement differ", + "ERR037 - Return types of ternary if-statement differ", exprtk_error_location)); result = false; @@ -21465,15 +22414,15 @@ namespace exprtk if (!result) { - free_node(node_allocator_, condition); - free_node(node_allocator_, consequent); - free_node(node_allocator_,alternative); + free_node(node_allocator_, condition ); + free_node(node_allocator_, consequent ); + free_node(node_allocator_, alternative); return error_node(); } else return expression_generator_ - .conditional(condition,consequent,alternative); + .conditional(condition, consequent, alternative); } inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) @@ -21490,7 +22439,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR035 - Failed to parse body of consequent for if-statement", + "ERR038 - Failed to parse body of consequent for if-statement", exprtk_error_location)); result = false; @@ -21513,7 +22462,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR036 - Expected ';' at the end of the consequent for if-statement", + "ERR039 - Expected ';' at the end of the consequent for if-statement", exprtk_error_location)); result = false; @@ -21524,7 +22473,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR037 - Failed to parse body of consequent for if-statement", + "ERR040 - Failed to parse body of consequent for if-statement", exprtk_error_location)); result = false; @@ -21544,7 +22493,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR038 - Failed to parse body of the 'else' for if-statement", + "ERR041 - Failed to parse body of the 'else' for if-statement", exprtk_error_location)); result = false; @@ -21557,7 +22506,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR039 - Failed to parse body of if-else statement", + "ERR042 - Failed to parse body of if-else statement", exprtk_error_location)); result = false; @@ -21570,7 +22519,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR040 - Expected ';' at the end of the 'else-if' for the if-statement", + "ERR043 - Expected ';' at the end of the 'else-if' for the if-statement", exprtk_error_location)); result = false; @@ -21581,7 +22530,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR041 - Failed to parse body of the 'else' for if-statement", + "ERR044 - Failed to parse body of the 'else' for if-statement", exprtk_error_location)); result = false; @@ -21606,7 +22555,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR042 - Return types of ternary if-statement differ", + "ERR045 - Return types of ternary if-statement differ", exprtk_error_location)); result = false; @@ -21638,7 +22587,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR043 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", + "ERR046 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", exprtk_error_location)); return error_node(); @@ -21648,7 +22597,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR044 - Failed to parse condition for if-statement", + "ERR047 - Failed to parse condition for if-statement", exprtk_error_location)); return error_node(); @@ -21680,7 +22629,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR045 - Invalid if-statement", + "ERR048 - Invalid if-statement", exprtk_error_location)); free_node(node_allocator_,condition); @@ -21701,7 +22650,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR046 - Encountered invalid condition branch for ternary if-statement", + "ERR049 - Encountered invalid condition branch for ternary if-statement", exprtk_error_location)); return error_node(); @@ -21711,7 +22660,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR047 - Expected '?' after condition of ternary if-statement", + "ERR050 - Expected '?' after condition of ternary if-statement", exprtk_error_location)); result = false; @@ -21721,7 +22670,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR048 - Failed to parse consequent for ternary if-statement", + "ERR051 - Failed to parse consequent for ternary if-statement", exprtk_error_location)); result = false; @@ -21731,7 +22680,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR049 - Expected ':' between ternary if-statement consequent and alternative", + "ERR052 - Expected ':' between ternary if-statement consequent and alternative", exprtk_error_location)); result = false; @@ -21741,7 +22690,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR050 - Failed to parse alternative for ternary if-statement", + "ERR053 - Failed to parse alternative for ternary if-statement", exprtk_error_location)); result = false; @@ -21764,7 +22713,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR051 - Return types of ternary if-statement differ", + "ERR054 - Return types of ternary if-statement differ", exprtk_error_location)); result = false; @@ -21785,6 +22734,22 @@ namespace exprtk .conditional(condition, consequent, alternative); } + inline expression_node_ptr parse_not_statement() + { + if (settings_.logic_disabled("not")) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR055 - Invalid or disabled logic operation 'not'", + exprtk_error_location)); + + return error_node(); + } + + return parse_base_operation(); + } + inline expression_node_ptr parse_while_loop() { // Parse: [while][(][test expr][)][{][expression][}] @@ -21801,7 +22766,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR052 - Expected '(' at start of while-loop condition statement", + "ERR056 - Expected '(' at start of while-loop condition statement", exprtk_error_location)); return error_node(); @@ -21811,7 +22776,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR053 - Failed to parse condition for while-loop", + "ERR057 - Failed to parse condition for while-loop", exprtk_error_location)); return error_node(); @@ -21821,7 +22786,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR054 - Expected ')' at end of while-loop condition statement", + "ERR058 - Expected ')' at end of while-loop condition statement", exprtk_error_location)); result = false; @@ -21831,12 +22796,14 @@ namespace exprtk if (result) { + scoped_inc_dec sid(state_.parsing_loop_stmt_count); + if (0 == (branch = parse_multi_sequence("while-loop"))) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR055 - Failed to parse body of while-loop")); + "ERR059 - Failed to parse body of while-loop")); result = false; } else if (0 == (result_node = expression_generator_.while_loop(condition, @@ -21846,7 +22813,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR056 - Failed to synthesize while-loop", + "ERR060 - Failed to synthesize while-loop", exprtk_error_location)); result = false; @@ -21894,6 +22861,8 @@ namespace exprtk scoped_bool_or_restorer sbr(state_.side_effect_present); + scoped_inc_dec sid(state_.parsing_loop_stmt_count); + for ( ; ; ) { state_.side_effect_present = false; @@ -21922,7 +22891,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR057 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", + "ERR061 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", exprtk_error_location)); return error_node(); @@ -21946,7 +22915,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR058 - Failed to parse body of repeat until loop", + "ERR062 - Failed to parse body of repeat until loop", exprtk_error_location)); return error_node(); @@ -21960,7 +22929,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR059 - Expected '(' before condition statement of repeat until loop", + "ERR063 - Expected '(' before condition statement of repeat until loop", exprtk_error_location)); free_node(node_allocator_,branch); @@ -21974,7 +22943,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR060 - Failed to parse condition for repeat until loop", + "ERR064 - Failed to parse condition for repeat until loop", exprtk_error_location)); free_node(node_allocator_,branch); @@ -21986,7 +22955,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR061 - Expected ')' after condition of repeat until loop", + "ERR065 - Expected ')' after condition of repeat until loop", exprtk_error_location)); free_node(node_allocator_, branch); @@ -22007,7 +22976,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR062 - Failed to synthesize repeat until loop", + "ERR066 - Failed to synthesize repeat until loop", exprtk_error_location)); free_node(node_allocator_,condition); @@ -22042,7 +23011,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR063 - Expected '(' at start of for-loop", + "ERR067 - Expected '(' at start of for-loop", exprtk_error_location)); return error_node(); @@ -22062,7 +23031,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR064 - Expected a variable at the start of initialiser section of for-loop", + "ERR068 - Expected a variable at the start of initialiser section of for-loop", exprtk_error_location)); return error_node(); @@ -22072,7 +23041,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR065 - Expected variable assignment of initialiser section of for-loop", + "ERR069 - Expected variable assignment of initialiser section of for-loop", exprtk_error_location)); return error_node(); @@ -22087,7 +23056,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR066 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", + "ERR070 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", exprtk_error_location)); return error_node(); @@ -22112,14 +23081,14 @@ namespace exprtk nse.type = scope_element::e_variable; nse.depth = state_.scope_depth; nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); + nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR067 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", + "ERR071 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -22141,7 +23110,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR068 - Failed to parse initialiser of for-loop", + "ERR072 - Failed to parse initialiser of for-loop", exprtk_error_location)); result = false; @@ -22151,7 +23120,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR069 - Expected ';' after initialiser of for-loop", + "ERR073 - Expected ';' after initialiser of for-loop", exprtk_error_location)); result = false; @@ -22165,7 +23134,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR070 - Failed to parse condition of for-loop", + "ERR074 - Failed to parse condition of for-loop", exprtk_error_location)); result = false; @@ -22175,7 +23144,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR071 - Expected ';' after condition section of for-loop", + "ERR075 - Expected ';' after condition section of for-loop", exprtk_error_location)); result = false; @@ -22189,7 +23158,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR072 - Failed to parse incrementor of for-loop", + "ERR076 - Failed to parse incrementor of for-loop", exprtk_error_location)); result = false; @@ -22199,7 +23168,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR073 - Expected ')' after incrementor section of for-loop", + "ERR077 - Expected ')' after incrementor section of for-loop", exprtk_error_location)); result = false; @@ -22210,12 +23179,14 @@ namespace exprtk { brkcnt_list_.push_front(false); + scoped_inc_dec sid(state_.parsing_loop_stmt_count); + if (0 == (loop_body = parse_multi_sequence("for-loop"))) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR074 - Failed to parse body of for-loop", + "ERR078 - Failed to parse body of for-loop", exprtk_error_location)); result = false; @@ -22265,7 +23236,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR075 - Expected keyword 'switch'", + "ERR079 - Expected keyword 'switch'", exprtk_error_location)); return error_node(); @@ -22280,85 +23251,100 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR076 - Expected '{' for call to switch statement", + "ERR080 - Expected '{' for call to switch statement", exprtk_error_location)); return error_node(); } + expression_node_ptr default_statement = error_node(); + + scoped_expression_delete defstmt_delete((*this), default_statement); + for ( ; ; ) { - if (!details::imatch("case",current_token().value)) + if (details::imatch("case",current_token().value)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR077 - Expected either a 'case' or 'default' statement", - exprtk_error_location)); + next_token(); - return error_node(); - } + expression_node_ptr condition = parse_expression(); - next_token(); + if (0 == condition) + return error_node(); + else if (!token_is(token_t::e_colon)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR081 - Expected ':' for case of switch statement", + exprtk_error_location)); - expression_node_ptr condition = parse_expression(); + free_node(node_allocator_, condition); - if (0 == condition) - return error_node(); - else if (!token_is(token_t::e_colon)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR078 - Expected ':' for case of switch statement", - exprtk_error_location)); + return error_node(); + } - return error_node(); - } + expression_node_ptr consequent = parse_expression(); - expression_node_ptr consequent = parse_expression(); + if (0 == consequent) + { + free_node(node_allocator_, condition); - if (0 == consequent) - return error_node(); - else if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR079 - Expected ';' at end of case for switch statement", - exprtk_error_location)); + return error_node(); + } + else if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR082 - Expected ';' at end of case for switch statement", + exprtk_error_location)); - return error_node(); - } + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + + return error_node(); + } + + // Can we optimise away the case statement? + if (is_constant_node(condition) && is_false(condition)) + { + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + } + else + { + arg_list.push_back( condition); + arg_list.push_back(consequent); + } - // Can we optimise away the case statement? - if (is_constant_node(condition) && is_false(condition)) - { - free_node(node_allocator_, condition); - free_node(node_allocator_, consequent); } - else + else if (details::imatch("default",current_token().value)) { - arg_list.push_back( condition); - arg_list.push_back(consequent); - } + if (0 != default_statement) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR083 - Multiple default cases for switch statement", + exprtk_error_location)); + + return error_node(); + } - if (details::imatch("default",current_token().value)) - { next_token(); + if (!token_is(token_t::e_colon)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR080 - Expected ':' for default of switch statement", + "ERR084 - Expected ':' for default of switch statement", exprtk_error_location)); return error_node(); } - expression_node_ptr default_statement = error_node(); - if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) default_statement = parse_multi_sequence("switch-default"); else @@ -22368,36 +23354,40 @@ namespace exprtk return error_node(); else if (!token_is(token_t::e_eof)) { - free_node(node_allocator_,default_statement); - set_error( make_error(parser_error::e_syntax, current_token(), - "ERR081 - Expected ';' at end of default for switch statement", + "ERR085 - Expected ';' at end of default for switch statement", exprtk_error_location)); return error_node(); } - - arg_list.push_back(default_statement); + } + else if (token_is(token_t::e_rcrlbracket)) break; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR086 - Expected '}' at end of switch statement", + exprtk_error_location)); + + return error_node(); } } - if (!token_is(token_t::e_rcrlbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR082 - Expected '}' at end of switch statement", - exprtk_error_location)); + const bool default_statement_present = (0 != default_statement); - return error_node(); + if (default_statement_present) + { + arg_list.push_back(default_statement); } - result = expression_generator_.switch_statement(arg_list); + result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); svd.delete_ptr = (0 == result); + defstmt_delete.delete_ptr = (0 == result); return result; } @@ -22405,14 +23395,13 @@ namespace exprtk inline expression_node_ptr parse_multi_switch_statement() { std::vector<expression_node_ptr> arg_list; - expression_node_ptr result = error_node(); if (!details::imatch(current_token().value,"[*]")) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR083 - Expected token '[*]'", + "ERR087 - Expected token '[*]'", exprtk_error_location)); return error_node(); @@ -22427,7 +23416,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR084 - Expected '{' for call to [*] statement", + "ERR088 - Expected '{' for call to [*] statement", exprtk_error_location)); return error_node(); @@ -22440,7 +23429,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR085 - Expected a 'case' statement for multi-switch", + "ERR089 - Expected a 'case' statement for multi-switch", exprtk_error_location)); return error_node(); @@ -22458,7 +23447,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR086 - Expected ':' for case of [*] statement", + "ERR090 - Expected ':' for case of [*] statement", exprtk_error_location)); return error_node(); @@ -22474,7 +23463,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR087 - Expected ';' at end of case for [*] statement", + "ERR091 - Expected ';' at end of case for [*] statement", exprtk_error_location)); return error_node(); @@ -22503,13 +23492,13 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR088 - Expected '}' at end of [*] statement", + "ERR092 - Expected '}' at end of [*] statement", exprtk_error_location)); return error_node(); } - result = expression_generator_.multi_switch_statement(arg_list); + const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); svd.delete_ptr = (0 == result); @@ -22519,7 +23508,6 @@ namespace exprtk inline expression_node_ptr parse_vararg_function() { std::vector<expression_node_ptr> arg_list; - expression_node_ptr result = error_node(); details::operator_type opt_type = details::e_default; const std::string symbol = current_token().value; @@ -22545,7 +23533,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR089 - Unsupported vararg function: " + symbol, + "ERR093 - Unsupported vararg function: " + symbol, exprtk_error_location)); return error_node(); @@ -22562,7 +23550,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR090 - Expected '(' for call to vararg function: " + symbol, + "ERR094 - Expected '(' for call to vararg function: " + symbol, exprtk_error_location)); return error_node(); @@ -22584,14 +23572,14 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR091 - Expected ',' for call to vararg function: " + symbol, + "ERR095 - Expected ',' for call to vararg function: " + symbol, exprtk_error_location)); return error_node(); } } - result = expression_generator_.vararg_function(opt_type,arg_list); + const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); sdd.delete_ptr = (0 == result); return result; @@ -22605,7 +23593,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR092 - Expected '[' as start of string range definition", + "ERR096 - Expected '[' as start of string range definition", exprtk_error_location)); free_node(node_allocator_,expression); @@ -22633,10 +23621,11 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR093 - Failed to generate string range node", + "ERR097 - Failed to generate string range node", exprtk_error_location)); free_node(node_allocator_,expression); + rp.free(); } rp.clear(); @@ -22769,7 +23758,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR094 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + + "ERR098 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + ((!source.empty()) ? std::string(" section of " + source): ""), exprtk_error_location)); @@ -22809,14 +23798,14 @@ namespace exprtk if (token_is(close_bracket)) break; - bool is_next_close = peek_token_is(close_bracket); + const bool is_next_close = peek_token_is(close_bracket); if (!token_is(seperator) && is_next_close) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR095 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, + "ERR099 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, exprtk_error_location)); return error_node(); @@ -22850,7 +23839,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR096 - Expected '[' for start of range", + "ERR100 - Expected '[' for start of range", exprtk_error_location)); return false; @@ -22871,7 +23860,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR097 - Failed parse begin section of range", + "ERR101 - Failed parse begin section of range", exprtk_error_location)); return false; @@ -22894,7 +23883,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR098 - Range lower bound less than zero! Constraint: r0 >= 0", + "ERR102 - Range lower bound less than zero! Constraint: r0 >= 0", exprtk_error_location)); return false; @@ -22911,7 +23900,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR099 - Expected ':' for break in range", + "ERR103 - Expected ':' for break in range", exprtk_error_location)); rp.free(); @@ -22934,7 +23923,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR100 - Failed parse end section of range", + "ERR104 - Failed parse end section of range", exprtk_error_location)); rp.free(); @@ -22959,9 +23948,11 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR101 - Range upper bound less than zero! Constraint: r1 >= 0", + "ERR105 - Range upper bound less than zero! Constraint: r1 >= 0", exprtk_error_location)); + rp.free(); + return false; } } @@ -22976,7 +23967,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR102 - Expected ']' for start of range", + "ERR106 - Expected ']' for start of range", exprtk_error_location)); rp.free(); @@ -22990,14 +23981,21 @@ namespace exprtk std::size_t r0 = 0; std::size_t r1 = 0; - const bool rp_result = rp(r0,r1); + bool rp_result = false; + + try + { + rp_result = rp(r0, r1); + } + catch (std::runtime_error&) + {} if (!rp_result || (r0 > r1)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR103 - Invalid range, Constraint: r0 <= r1", + "ERR107 - Invalid range, Constraint: r0 <= r1", exprtk_error_location)); return false; @@ -23038,7 +24036,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR104 - Unknown string symbol", + "ERR108 - Unknown string symbol", exprtk_error_location)); return error_node(); @@ -23132,6 +24130,7 @@ namespace exprtk if (!parse_range(rp)) { free_node(node_allocator_,result); + rp.free(); return error_node(); } @@ -23152,11 +24151,13 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR105 - Overflow in range for string: '" + const_str + "'[" + + "ERR109 - Overflow in range for string: '" + const_str + "'[" + (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", exprtk_error_location)); + rp.free(); + return error_node(); } @@ -23196,7 +24197,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR106 - Symbol '" + symbol+ " not a vector", + "ERR110 - Symbol '" + symbol+ " not a vector", exprtk_error_location)); return error_node(); @@ -23222,7 +24223,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR107 - Failed to parse index for vector: '" + symbol + "'", + "ERR111 - Failed to parse index for vector: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -23232,7 +24233,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR108 - Expected ']' for index of vector: '" + symbol + "'", + "ERR112 - Expected ']' for index of vector: '" + symbol + "'", exprtk_error_location)); free_node(node_allocator_,index_expr); @@ -23251,7 +24252,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR109 - Index of " + details::to_str(index) + " out of range for " + "ERR113 - Index of " + details::to_str(index) + " out of range for " "vector '" + symbol + "' of size " + details::to_str(vec_size), exprtk_error_location)); @@ -23261,7 +24262,7 @@ namespace exprtk } } - return expression_generator_.vector_element(symbol,vec,index_expr); + return expression_generator_.vector_element(symbol, vec, index_expr); } inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) @@ -23283,7 +24284,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR110 - Zero parameter call to vararg function: " + "ERR114 - Zero parameter call to vararg function: " + vararg_function_name + " not allowed", exprtk_error_location)); @@ -23308,7 +24309,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR111 - Expected ',' for call to vararg function: " + "ERR115 - Expected ',' for call to vararg function: " + vararg_function_name, exprtk_error_location)); @@ -23322,7 +24323,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR112 - Zero parameter call to vararg function: " + "ERR116 - Zero parameter call to vararg function: " + vararg_function_name + " not allowed", exprtk_error_location)); @@ -23334,7 +24335,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR113 - Invalid number of parameters to call to vararg function: " + "ERR117 - Invalid number of parameters to call to vararg function: " + vararg_function_name + ", require at least " + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", exprtk_error_location)); @@ -23346,7 +24347,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR114 - Invalid number of parameters to call to vararg function: " + "ERR118 - Invalid number of parameters to call to vararg function: " + vararg_function_name + ", require no more than " + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", exprtk_error_location)); @@ -23393,11 +24394,6 @@ namespace exprtk parse_function_prototypes(func_prototypes); } - void set_default_return_type(const std::string& return_type) - { - default_return_type_ = return_type; - } - bool verify(const std::string& param_seq, std::size_t& pseq_index) { if (function_definition_list_.empty()) @@ -23429,7 +24425,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR115 - Failed parameter type check for function '" + function_name_ + "', " + "ERR119 - Failed parameter type check for function '" + function_name_ + "', " "Expected '" + function_definition_list_[0].param_seq + "' call set: '" + param_seq + "'", exprtk_error_location)); @@ -23451,7 +24447,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR116 - Failed parameter type check for function '" + function_name_ + "', " + "ERR120 - Failed parameter type check for function '" + function_name_ + "', " "Best match: '" + function_definition_list_[max_diff_index].param_seq + "' call set: '" + param_seq + "'", exprtk_error_location)); @@ -23508,8 +24504,7 @@ namespace exprtk if (*iter == delimiter) { result.push_back(std::string(current_begin, iter)); - ++iter; - current_begin = iter; + current_begin = ++iter; } else ++iter; @@ -23594,7 +24589,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR117 - Invalid parameter sequence of '" + param_seq_list[i] + + "ERR121 - Invalid parameter sequence of '" + param_seq_list[i] + "' for function: " + function_name_, exprtk_error_location)); return; @@ -23610,7 +24605,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR118 - Function '" + function_name_ + "' has a parameter sequence conflict between " + + "ERR122 - Function '" + function_name_ + "' has a parameter sequence conflict between " + "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + "pseq_idx[" + details::to_str(i) + "] " + "param seq: " + param_seq_list[i], @@ -23649,7 +24644,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR119 - Type checker instantiation failure for generic function: " + function_name, + "ERR123 - Type checker instantiation failure for generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -23667,7 +24662,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR120 - Zero parameter call to generic function: " + "ERR124 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -23699,7 +24694,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR121 - Expected ',' for call to generic function: " + function_name, + "ERR125 - Expected ',' for call to generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -23716,7 +24711,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR122 - Zero parameter call to generic function: " + "ERR126 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -23733,7 +24728,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR123 - Invalid input parameter sequence for call to generic function: " + function_name, + "ERR127 - Invalid input parameter sequence for call to generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -23755,7 +24750,7 @@ namespace exprtk inline bool parse_igeneric_function_params(std::string& param_type_list, std::vector<expression_node_ptr>& arg_list, - const std::string function_name, + const std::string& function_name, igeneric_function<T>* function, const type_checker& tc) { @@ -23771,7 +24766,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR124 - Zero parameter call to generic function: " + "ERR128 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -23803,7 +24798,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR125 - Expected ',' for call to string function: " + function_name, + "ERR129 - Expected ',' for call to string function: " + function_name, exprtk_error_location)); return false; @@ -23850,7 +24845,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR126 - Invalid input parameter sequence for call to string function: " + function_name, + "ERR130 - Invalid input parameter sequence for call to string function: " + function_name, exprtk_error_location)); return error_node(); @@ -23902,7 +24897,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR127 - Invalid input parameter sequence for call to overloaded function: " + function_name, + "ERR131 - Invalid input parameter sequence for call to overloaded function: " + function_name, exprtk_error_location)); return error_node(); @@ -23933,7 +24928,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR128 - Invalid return type for call to overloaded function: " + function_name, + "ERR132 - Invalid return type for call to overloaded function: " + function_name, exprtk_error_location)); } @@ -23945,12 +24940,12 @@ namespace exprtk template <typename Type, std::size_t NumberOfParameters> struct parse_special_function_impl { - static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type, const std::string& sf_name) + static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) { expression_node_ptr branch[NumberOfParameters]; - expression_node_ptr result = error_node(); + expression_node_ptr result = error_node(); - std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0)); + std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); @@ -23961,7 +24956,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR129 - Expected '(' for special function '" + sf_name + "'", + "ERR133 - Expected '(' for special function '" + sf_name + "'", exprtk_error_location)); return error_node(); @@ -23982,7 +24977,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR130 - Expected ',' before next parameter of special function '" + sf_name + "'", + "ERR134 - Expected ',' before next parameter of special function '" + sf_name + "'", exprtk_error_location)); return p.error_node(); @@ -23995,7 +24990,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR131 - Invalid number of parameters for special function '" + sf_name + "'", + "ERR135 - Invalid number of parameters for special function '" + sf_name + "'", exprtk_error_location)); return p.error_node(); @@ -24022,7 +25017,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token(), - "ERR132 - Invalid special function[1]: " + sf_name, + "ERR136 - Invalid special function[1]: " + sf_name, exprtk_error_location)); return error_node(); @@ -24036,7 +25031,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token(), - "ERR133 - Invalid special function[2]: " + sf_name, + "ERR137 - Invalid special function[2]: " + sf_name, exprtk_error_location)); return error_node(); @@ -24068,7 +25063,17 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR134 - Break call within a break call is not allowed", + "ERR138 - Invoking 'break' within a break call is not allowed", + exprtk_error_location)); + + return error_node(); + } + else if (0 == state_.parsing_loop_stmt_count) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR139 - Invalid use of 'break', allowed only in the scope of a loop", exprtk_error_location)); return error_node(); @@ -24091,7 +25096,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR135 - Failed to parse return expression for 'break' statement", + "ERR140 - Failed to parse return expression for 'break' statement", exprtk_error_location)); return error_node(); @@ -24101,7 +25106,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR136 - Expected ']' at the completion of break's return expression", + "ERR141 - Expected ']' at the completion of break's return expression", exprtk_error_location)); free_node(node_allocator_,return_expr); @@ -24119,7 +25124,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR137 - Invalid use of 'break', allowed only in the scope of a loop", + "ERR142 - Invalid use of 'break', allowed only in the scope of a loop", exprtk_error_location)); } @@ -24128,25 +25133,25 @@ namespace exprtk inline expression_node_ptr parse_continue_statement() { - if (!brkcnt_list_.empty()) - { - next_token(); - - brkcnt_list_.front() = true; - state_.activate_side_effect("parse_continue_statement()"); - - return node_allocator_.allocate<details::continue_node<T> >(); - } - else + if (0 == state_.parsing_loop_stmt_count) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR138 - Invalid use of 'continue', allowed only in the scope of a loop", + "ERR143 - Invalid use of 'continue', allowed only in the scope of a loop", exprtk_error_location)); return error_node(); } + else + { + next_token(); + + brkcnt_list_.front() = true; + state_.activate_side_effect("parse_continue_statement()"); + + return node_allocator_.allocate<details::continue_node<T> >(); + } } #endif @@ -24159,7 +25164,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR139 - Expected '[' as part of vector size definition", + "ERR144 - Expected '[' as part of vector size definition", exprtk_error_location)); return error_node(); @@ -24169,7 +25174,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR140 - Failed to determine size of vector '" + vec_name + "'", + "ERR145 - Failed to determine size of vector '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -24181,13 +25186,13 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR141 - Expected a literal number as size of vector '" + vec_name + "'", + "ERR146 - Expected a literal number as size of vector '" + vec_name + "'", exprtk_error_location)); return error_node(); } - T vector_size = size_expr->value(); + const T vector_size = size_expr->value(); free_node(node_allocator_,size_expr); @@ -24203,7 +25208,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR142 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + + "ERR147 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + details::to_str(details::numeric::to_int32(vector_size)), exprtk_error_location)); @@ -24223,7 +25228,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR143 - Expected ']' as part of vector size definition", + "ERR148 - Expected ']' as part of vector size definition", exprtk_error_location)); return error_node(); @@ -24235,7 +25240,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR144 - Expected ':=' as part of vector definition", + "ERR149 - Expected ':=' as part of vector definition", exprtk_error_location)); return error_node(); @@ -24249,7 +25254,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR145 - Failed to parse single vector initialiser", + "ERR150 - Failed to parse single vector initialiser", exprtk_error_location)); return error_node(); @@ -24262,7 +25267,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR146 - Expected ']' to close single value vector initialiser", + "ERR151 - Expected ']' to close single value vector initialiser", exprtk_error_location)); return error_node(); @@ -24278,7 +25283,7 @@ namespace exprtk if (token_t::e_symbol == current_token().type) { // Is it a locally defined vector? - scope_element& se = sem_.get_active_element(current_token().value); + const scope_element& se = sem_.get_active_element(current_token().value); if (scope_element::e_vector == se.type) { @@ -24309,7 +25314,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR147 - Expected '{' as part of vector initialiser list", + "ERR152 - Expected '{' as part of vector initialiser list", exprtk_error_location)); return error_node(); @@ -24329,7 +25334,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR148 - Expected '{' as part of vector initialiser list", + "ERR153 - Expected '{' as part of vector initialiser list", exprtk_error_location)); return error_node(); @@ -24340,14 +25345,14 @@ namespace exprtk if (token_is(token_t::e_rcrlbracket)) break; - bool is_next_close = peek_token_is(token_t::e_rcrlbracket); + const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); if (!token_is(token_t::e_comma) && is_next_close) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR149 - Expected ',' between vector initialisers", + "ERR154 - Expected ',' between vector initialisers", exprtk_error_location)); return error_node(); @@ -24369,7 +25374,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR150 - Expected ';' at end of vector definition", + "ERR155 - Expected ';' at end of vector definition", exprtk_error_location)); return error_node(); @@ -24381,7 +25386,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR151 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", + "ERR156 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -24401,7 +25406,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR152 - Illegal redefinition of local vector: '" + vec_name + "'", + "ERR157 - Illegal redefinition of local vector: '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -24428,14 +25433,14 @@ namespace exprtk nse.depth = state_.scope_depth; nse.size = vec_size; nse.data = new T[vec_size]; - nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size); + nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR153 - Failed to add new local vector '" + vec_name + "' to SEM", + "ERR158 - Failed to add new local vector '" + vec_name + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -24494,7 +25499,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR154 - Illegal redefinition of local variable: '" + str_name + "'", + "ERR159 - Illegal redefinition of local variable: '" + str_name + "'", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -24519,14 +25524,14 @@ namespace exprtk nse.type = scope_element::e_string; nse.depth = state_.scope_depth; nse.data = new std::string; - nse.str_node = new stringvar_node_t(*(std::string*)(nse.data)); + nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR155 - Failed to add new local string variable '" + str_name + "' to SEM", + "ERR160 - Failed to add new local string variable '" + str_name + "' to SEM", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -24572,7 +25577,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR156 - Illegal variable definition", + "ERR161 - Illegal variable definition", exprtk_error_location)); return error_node(); @@ -24593,7 +25598,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR157 - Expected a symbol for variable definition", + "ERR162 - Expected a symbol for variable definition", exprtk_error_location)); return error_node(); @@ -24603,7 +25608,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR158 - Illegal redefinition of reserved keyword: '" + var_name + "'", + "ERR163 - Illegal redefinition of reserved keyword: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24613,7 +25618,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR159 - Illegal redefinition of variable '" + var_name + "'", + "ERR164 - Illegal redefinition of variable '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24623,7 +25628,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR160 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR165 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24643,7 +25648,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR161 - Failed to parse initialisation expression", + "ERR166 - Failed to parse initialisation expression", exprtk_error_location)); return error_node(); @@ -24661,7 +25666,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR162 - Expected ';' after variable definition", + "ERR167 - Expected ';' after variable definition", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -24689,7 +25694,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR163 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR168 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -24714,14 +25719,14 @@ namespace exprtk nse.type = scope_element::e_variable; nse.depth = state_.scope_depth; nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); + nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR164 - Failed to add new local variable '" + var_name + "' to SEM", + "ERR169 - Failed to add new local variable '" + var_name + "' to SEM", exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -24758,7 +25763,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR165 - Expected a '{}' for uninitialised var definition", + "ERR170 - Expected a '{}' for uninitialised var definition", exprtk_error_location)); return error_node(); @@ -24768,7 +25773,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR166 - Expected ';' after uninitialised variable definition", + "ERR171 - Expected ';' after uninitialised variable definition", exprtk_error_location)); return error_node(); @@ -24785,7 +25790,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR167 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR172 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24808,14 +25813,14 @@ namespace exprtk nse.depth = state_.scope_depth; nse.ip_index = sem_.next_ip_index(); nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); + nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR168 - Failed to add new local variable '" + var_name + "' to SEM", + "ERR173 - Failed to add new local variable '" + var_name + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -24848,7 +25853,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR169 - Expected '(' at start of swap statement", + "ERR174 - Expected '(' at start of swap statement", exprtk_error_location)); return error_node(); @@ -24867,7 +25872,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR170 - Expected a symbol for variable or vector element definition", + "ERR175 - Expected a symbol for variable or vector element definition", exprtk_error_location)); return error_node(); @@ -24879,7 +25884,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR171 - First parameter to swap is an invalid vector element: '" + var0_name + "'", + "ERR176 - First parameter to swap is an invalid vector element: '" + var0_name + "'", exprtk_error_location)); return error_node(); @@ -24894,7 +25899,7 @@ namespace exprtk variable0 = symtab_store_.get_variable(var0_name); } - scope_element& se = sem_.get_element(var0_name); + const scope_element& se = sem_.get_element(var0_name); if ( (se.active) && @@ -24912,7 +25917,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR172 - First parameter to swap is an invalid variable: '" + var0_name + "'", + "ERR177 - First parameter to swap is an invalid variable: '" + var0_name + "'", exprtk_error_location)); return error_node(); @@ -24926,7 +25931,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR173 - Expected ',' between parameters to swap", + "ERR178 - Expected ',' between parameters to swap", exprtk_error_location)); if (variable0_generated) @@ -24944,7 +25949,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR174 - Expected a symbol for variable or vector element definition", + "ERR179 - Expected a symbol for variable or vector element definition", exprtk_error_location)); if (variable0_generated) @@ -24961,7 +25966,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR175 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", + "ERR180 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", exprtk_error_location)); if (variable0_generated) @@ -24981,7 +25986,7 @@ namespace exprtk variable1 = symtab_store_.get_variable(var1_name); } - scope_element& se = sem_.get_element(var1_name); + const scope_element& se = sem_.get_element(var1_name); if ( (se.active) && @@ -24999,7 +26004,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR176 - Second parameter to swap is an invalid variable: '" + var1_name + "'", + "ERR181 - Second parameter to swap is an invalid variable: '" + var1_name + "'", exprtk_error_location)); if (variable0_generated) @@ -25018,7 +26023,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR177 - Expected ')' at end of swap statement", + "ERR182 - Expected ')' at end of swap statement", exprtk_error_location)); if (variable0_generated) @@ -25075,7 +26080,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR178 - Return call within a return call is not allowed", + "ERR183 - Return call within a return call is not allowed", exprtk_error_location)); return error_node(); @@ -25099,7 +26104,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR179 - Expected '[' at start of return statement", + "ERR184 - Expected '[' at start of return statement", exprtk_error_location)); return error_node(); @@ -25122,7 +26127,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR180 - Expected ',' between values during call to return", + "ERR185 - Expected ',' between values during call to return", exprtk_error_location)); return error_node(); @@ -25134,7 +26139,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR181 - Zero parameter return statement not allowed", + "ERR186 - Zero parameter return statement not allowed", exprtk_error_location)); return error_node(); @@ -25149,7 +26154,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR182 - Invalid ']' found during return call", + "ERR187 - Invalid ']' found during return call", exprtk_error_location)); return error_node(); @@ -25202,7 +26207,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR183 - Invalid sequence of variable '"+ symbol + "' and bracket", + "ERR188 - Invalid sequence of variable '"+ symbol + "' and bracket", exprtk_error_location)); return false; @@ -25250,7 +26255,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR184 - Invalid sequence of brackets", + "ERR189 - Invalid sequence of brackets", exprtk_error_location)); return false; @@ -25347,7 +26352,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR185 - Failed to generate node for function: '" + symbol + "'", + "ERR190 - Failed to generate node for function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25373,7 +26378,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR186 - Failed to generate node for vararg function: '" + symbol + "'", + "ERR191 - Failed to generate node for vararg function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25399,7 +26404,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR187 - Failed to generate node for generic function: '" + symbol + "'", + "ERR192 - Failed to generate node for generic function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25426,7 +26431,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR188 - Failed to generate node for string function: '" + symbol + "'", + "ERR193 - Failed to generate node for string function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25452,7 +26457,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR189 - Failed to generate node for overload function: '" + symbol + "'", + "ERR194 - Failed to generate node for overload function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25478,7 +26483,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR190 - Invalid use of reserved symbol '" + symbol + "'", + "ERR195 - Invalid use of reserved symbol '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25541,7 +26546,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR191 - Failed to create variable: '" + symbol + "'" + + "ERR196 - Failed to create variable: '" + symbol + "'" + (error_message.empty() ? "" : " - " + error_message), exprtk_error_location)); @@ -25561,7 +26566,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR192 - Failed to resolve symbol: '" + symbol + "'" + + "ERR197 - Failed to resolve symbol: '" + symbol + "'" + (error_message.empty() ? "" : " - " + error_message), exprtk_error_location)); } @@ -25573,7 +26578,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR193 - Undefined symbol: '" + symbol + "'", + "ERR198 - Undefined symbol: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25592,11 +26597,16 @@ namespace exprtk static const std::string symbol_var = "var" ; static const std::string symbol_swap = "swap" ; static const std::string symbol_return = "return" ; + static const std::string symbol_not = "not" ; if (valid_vararg_operation(current_token().value)) { return parse_vararg_function(); } + else if (details::imatch(current_token().value, symbol_not)) + { + return parse_not_statement(); + } else if (valid_base_operation(current_token().value)) { return parse_base_operation(); @@ -25680,7 +26690,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR194 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value, + "ERR199 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value, exprtk_error_location)); return error_node(); @@ -25689,6 +26699,13 @@ namespace exprtk inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) { + stack_limit_handler slh(*this); + + if (!slh) + { + return error_node(); + } + expression_node_ptr branch = error_node(); if (token_t::e_number == current_token().type) @@ -25704,7 +26721,7 @@ namespace exprtk set_error( make_error(parser_error::e_numeric, current_token(), - "ERR195 - Failed generate node for scalar: '" + current_token().value + "'", + "ERR200 - Failed generate node for scalar: '" + current_token().value + "'", exprtk_error_location)); return error_node(); @@ -25718,7 +26735,7 @@ namespace exprtk set_error( make_error(parser_error::e_numeric, current_token(), - "ERR196 - Failed to convert '" + current_token().value + "' to a number", + "ERR201 - Failed to convert '" + current_token().value + "' to a number", exprtk_error_location)); return error_node(); @@ -25745,7 +26762,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR197 - Expected ')' instead of: '" + current_token().value + "'", + "ERR202 - Expected ')' instead of: '" + current_token().value + "'", exprtk_error_location)); free_node(node_allocator_,branch); @@ -25770,7 +26787,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR198 - Expected ']' instead of: '" + current_token().value + "'", + "ERR203 - Expected ']' instead of: '" + current_token().value + "'", exprtk_error_location)); free_node(node_allocator_,branch); @@ -25795,7 +26812,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR199 - Expected '}' instead of: '" + current_token().value + "'", + "ERR204 - Expected '}' instead of: '" + current_token().value + "'", exprtk_error_location)); free_node(node_allocator_,branch); @@ -25822,7 +26839,16 @@ namespace exprtk ) ) { - branch = expression_generator_(details::e_neg,branch); + expression_node_ptr result = expression_generator_(details::e_neg,branch); + + if (0 == result) + { + free_node(node_allocator_,branch); + + return error_node(); + } + else + branch = result; } } else if (token_t::e_add == current_token().type) @@ -25835,7 +26861,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR200 - Premature end of expression[1]", + "ERR205 - Premature end of expression[1]", exprtk_error_location)); return error_node(); @@ -25845,7 +26871,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR201 - Premature end of expression[2]", + "ERR206 - Premature end of expression[2]", exprtk_error_location)); return error_node(); @@ -26839,6 +27865,19 @@ namespace exprtk } #endif + inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const + { + if ( + parser_->loop_runtime_check_ && + (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) + ) + { + return parser_->loop_runtime_check_; + } + + return loop_runtime_check_ptr(0); + } + inline expression_node_ptr while_loop(expression_node_ptr& condition, expression_node_ptr& branch, const bool brkcont = false) const @@ -26864,10 +27903,20 @@ namespace exprtk return branch; } else if (!brkcont) - return node_allocator_->allocate<while_loop_node_t>(condition,branch); + return node_allocator_->allocate<while_loop_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_while_loop) + ); #ifndef exprtk_disable_break_continue else - return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch); + return node_allocator_->allocate<while_loop_bc_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_while_loop) + ); #else return error_node(); #endif @@ -26901,10 +27950,20 @@ namespace exprtk return branch; } else if (!brkcont) - return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch); + return node_allocator_->allocate<repeat_until_loop_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop) + ); #ifndef exprtk_disable_break_continue else - return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch); + return node_allocator_->allocate<repeat_until_loop_bc_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop) + ); #else return error_node(); #endif @@ -26947,7 +28006,8 @@ namespace exprtk initialiser, condition, incrementor, - loop_body + loop_body, + get_loop_runtime_check(loop_runtime_check::e_for_loop) ); #ifndef exprtk_disable_break_continue @@ -26957,7 +28017,8 @@ namespace exprtk initialiser, condition, incrementor, - loop_body + loop_body, + get_loop_runtime_check(loop_runtime_check::e_for_loop) ); #else return error_node(); @@ -27038,10 +28099,10 @@ namespace exprtk struct switch_nodes { - typedef std::vector<expression_node_ptr> arg_list_t; + typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; - #define case_stmt(N) \ - if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \ + #define case_stmt(N) \ + if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ struct switch_1 { @@ -27049,7 +28110,7 @@ namespace exprtk { case_stmt(0) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27059,7 +28120,7 @@ namespace exprtk { case_stmt(0) case_stmt(1) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27070,7 +28131,7 @@ namespace exprtk case_stmt(0) case_stmt(1) case_stmt(2) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27081,7 +28142,7 @@ namespace exprtk case_stmt(0) case_stmt(1) case_stmt(2) case_stmt(3) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27093,7 +28154,7 @@ namespace exprtk case_stmt(2) case_stmt(3) case_stmt(4) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27105,7 +28166,7 @@ namespace exprtk case_stmt(2) case_stmt(3) case_stmt(4) case_stmt(5) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27118,7 +28179,7 @@ namespace exprtk case_stmt(4) case_stmt(5) case_stmt(6) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27127,14 +28188,13 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) + inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) { if (arg_list.empty()) return error_node(); else if ( - !all_nodes_valid(arg_list) || - (arg_list.size() < 3) || - ((arg_list.size() % 2) != 1) + !all_nodes_valid(arg_list) || + (!default_statement_present && (arg_list.size() < 2)) ) { details::free_all_nodes(*node_allocator_,arg_list); @@ -27631,24 +28691,31 @@ namespace exprtk if (details::is_constant_node(result)) return result; else if (!all_nodes_valid(b)) + { + details::free_node(*node_allocator_,result); + std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); + return error_node(); + } else if (N != f->param_count) { - details::free_all_nodes(*node_allocator_,b); + details::free_node(*node_allocator_,result); + std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); return error_node(); } - function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result); + function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); - if (func_node_ptr->init_branches(b)) - return result; - else + if (!func_node_ptr->init_branches(b)) { - details::free_all_nodes(*node_allocator_,b); + details::free_node(*node_allocator_,result); + std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); return error_node(); } + + return result; } } @@ -27872,7 +28939,7 @@ namespace exprtk return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base); } - scope_element& se = parser_->sem_.get_element(symbol,i); + const scope_element& se = parser_->sem_.get_element(symbol,i); if (se.index == i) { @@ -28724,8 +29791,9 @@ namespace exprtk { expression_node_ptr result = error_node(); - const bool synthesis_result = synthesize_sf4ext_expression::template compile_right<vtype> - (expr_gen, v, operation, branch[1], result); + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_right<vtype> + (expr_gen, v, operation, branch[1], result); if (synthesis_result) { @@ -28798,8 +29866,9 @@ namespace exprtk { expression_node_ptr result = error_node(); - const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<vtype> - (expr_gen, v, operation, branch[0], result); + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_left<vtype> + (expr_gen, v, operation, branch[0], result); if (synthesis_result) { @@ -28980,7 +30049,11 @@ namespace exprtk { expression_node_ptr result = error_node(); - if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result)) + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_right<ctype> + (expr_gen, c, operation, branch[1], result); + + if (synthesis_result) { free_node(*expr_gen.node_allocator_,branch[1]); @@ -29095,8 +30168,9 @@ namespace exprtk { expression_node_ptr result = error_node(); - const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<ctype> - (expr_gen, c, operation, branch[0], result); + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_left<ctype> + (expr_gen, c, operation, branch[0], result); if (synthesis_result) { @@ -30450,7 +31524,7 @@ namespace exprtk const bool synthesis_result = synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> - (expr_gen, id(expr_gen, o0, o1), c0, v, c1,result); + (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); if (synthesis_result) return result; @@ -30946,7 +32020,7 @@ namespace exprtk const bool synthesis_result = synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3,result); + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); if (synthesis_result) return result; @@ -34572,8 +35646,8 @@ namespace exprtk { const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref (); - range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); - range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range(); + const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); + const range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range(); static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); @@ -34586,9 +35660,9 @@ namespace exprtk inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) { - std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); + const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str (); - range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); + const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); @@ -34599,10 +35673,10 @@ namespace exprtk inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) { - std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); - std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); - range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); - range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); + const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); + const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); + const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); + const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); @@ -34847,8 +35921,8 @@ namespace exprtk typedef typename details::null_eq_node<T> nulleq_node_t; - bool b0_null = details::is_null_node(branch[0]); - bool b1_null = details::is_null_node(branch[1]); + const bool b0_null = details::is_null_node(branch[0]); + const bool b1_null = details::is_null_node(branch[1]); if (b0_null && b1_null) { @@ -34909,21 +35983,22 @@ namespace exprtk { return branch[0]; } - else if ( - (details::e_lt == operation) || (details::e_lte == operation) || - (details::e_gt == operation) || (details::e_gte == operation) || - (details::e_and == operation) || (details::e_nand == operation) || - (details::e_or == operation) || (details::e_nor == operation) || - (details::e_xor == operation) || (details::e_xnor == operation) || - (details::e_in == operation) || (details::e_like == operation) || - (details::e_ilike == operation) - ) + + details::free_node(*node_allocator_, branch[0]); + + if ( + (details::e_lt == operation) || (details::e_lte == operation) || + (details::e_gt == operation) || (details::e_gte == operation) || + (details::e_and == operation) || (details::e_nand == operation) || + (details::e_or == operation) || (details::e_nor == operation) || + (details::e_xor == operation) || (details::e_xnor == operation) || + (details::e_in == operation) || (details::e_like == operation) || + (details::e_ilike == operation) + ) { return node_allocator_->allocate_c<literal_node_t>(T(0)); } - details::free_node(*node_allocator_,branch[0]); - return node_allocator_->allocate<details::null_node<Type> >(); } @@ -34953,7 +36028,7 @@ namespace exprtk if (is_constant_foldable<N>(branch)) { - Type v = expression_point->value(); + const Type v = expression_point->value(); details::free_node(*node_allocator_,expression_point); return node_allocator_->allocate<literal_node_t>(v); @@ -35328,40 +36403,116 @@ namespace exprtk lexer::helper::sequence_validator sequence_validator_; lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; + loop_runtime_check_ptr loop_runtime_check_; + template <typename ParserType> friend void details::disable_type_checking(ParserType& p); }; + namespace details + { + template <typename T> + struct collector_helper + { + typedef exprtk::symbol_table<T> symbol_table_t; + typedef exprtk::expression<T> expression_t; + typedef exprtk::parser<T> parser_t; + typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; + typedef typename parser_t::unknown_symbol_resolver usr_t; + + struct resolve_as_vector : public parser_t::unknown_symbol_resolver + { + typedef exprtk::parser<T> parser_t; + + resolve_as_vector() + : usr_t(usr_t::e_usrmode_extended) + {} + + virtual bool process(const std::string& unknown_symbol, + symbol_table_t& symbol_table, + std::string&) + { + static T v[1]; + symbol_table.add_vector(unknown_symbol,v); + return true; + } + }; + + static inline bool collection_pass(const std::string& expression_string, + std::set<std::string>& symbol_set, + const bool collect_variables, + const bool collect_functions, + const bool vector_pass, + symbol_table_t& ext_symbol_table) + { + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + resolve_as_vector vect_resolver; + + expression.register_symbol_table(symbol_table ); + expression.register_symbol_table(ext_symbol_table); + + if (vector_pass) + parser.enable_unknown_symbol_resolver(&vect_resolver); + else + parser.enable_unknown_symbol_resolver(); + + if (collect_variables) + parser.dec().collect_variables() = true; + + if (collect_functions) + parser.dec().collect_functions() = true; + + bool pass_result = false; + + details::disable_type_checking(parser); + + if (parser.compile(expression_string, expression)) + { + pass_result = true; + + std::deque<symbol_t> symb_list; + parser.dec().symbols(symb_list); + + for (std::size_t i = 0; i < symb_list.size(); ++i) + { + symbol_set.insert(symb_list[i].first); + } + } + + return pass_result; + } + }; + } + template <typename Allocator, template <typename, typename> class Sequence> - inline bool collect_variables(const std::string& expr_str, + inline bool collect_variables(const std::string& expression, Sequence<std::string, Allocator>& symbol_list) { typedef double T; - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef parser_t::dependent_entity_collector::symbol_t symbol_t; + typedef details::collector_helper<T> collect_t; - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; + collect_t::symbol_table_t null_symbol_table; - expression.register_symbol_table(symbol_table); + std::set<std::string> symbol_set; - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_variables() = true; + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, true, false, false, null_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, true, false, true, null_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35370,37 +36521,28 @@ namespace exprtk template <typename T, typename Allocator, template <typename, typename> class Sequence> - inline bool collect_variables(const std::string& expr_str, + inline bool collect_variables(const std::string& expression, exprtk::symbol_table<T>& extrnl_symbol_table, Sequence<std::string, Allocator>& symbol_list) { - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; - - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; - - expression.register_symbol_table(symbol_table); - expression.register_symbol_table(extrnl_symbol_table); + typedef details::collector_helper<T> collect_t; - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_variables() = true; + std::set<std::string> symbol_set; - details::disable_type_checking(parser); + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, true, false, false, extrnl_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, true, false, true, extrnl_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35408,34 +36550,30 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - inline bool collect_functions(const std::string& expr_str, + inline bool collect_functions(const std::string& expression, Sequence<std::string, Allocator>& symbol_list) { typedef double T; - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef parser_t::dependent_entity_collector::symbol_t symbol_t; + typedef details::collector_helper<T> collect_t; - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; + collect_t::symbol_table_t null_symbol_table; - expression.register_symbol_table(symbol_table); + std::set<std::string> symbol_set; - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_functions() = true; + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, false, true, false, null_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, false, true, true, null_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35444,37 +36582,28 @@ namespace exprtk template <typename T, typename Allocator, template <typename, typename> class Sequence> - inline bool collect_functions(const std::string& expr_str, + inline bool collect_functions(const std::string& expression, exprtk::symbol_table<T>& extrnl_symbol_table, Sequence<std::string, Allocator>& symbol_list) { - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; - - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; + typedef details::collector_helper<T> collect_t; - expression.register_symbol_table(symbol_table); - expression.register_symbol_table(extrnl_symbol_table); - - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_functions() = true; + std::set<std::string> symbol_set; - details::disable_type_checking(parser); + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, false, true, false, extrnl_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, false, true, true, extrnl_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35520,8 +36649,8 @@ namespace exprtk if (var) { T& x = var->ref(); - T x_original = x; - T result = integrate(e,x,r0,r1,number_of_intervals); + const T x_original = x; + const T result = integrate(e, x, r0, r1, number_of_intervals); x = x_original; return result; @@ -35611,8 +36740,8 @@ namespace exprtk if (var) { T& x = var->ref(); - T x_original = x; - T result = derivative(e,x,h); + const T x_original = x; + const T result = derivative(e, x, h); x = x_original; return result; @@ -35639,7 +36768,7 @@ namespace exprtk { T& x = var->ref(); const T x_original = x; - const T result = second_derivative(e,x,h); + const T result = second_derivative(e, x, h); x = x_original; return result; @@ -35666,7 +36795,7 @@ namespace exprtk { T& x = var->ref(); const T x_original = x; - const T result = third_derivative(e,x,h); + const T result = third_derivative(e, x, h); x = x_original; return result; @@ -35959,62 +37088,62 @@ namespace exprtk inline virtual T operator() (const T& x, const T& c1, const T& c0) { - poly_rtrn(1) poly_impl<T,1>::evaluate(x,c1,c0); + poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); } inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) { - poly_rtrn(2) poly_impl<T,2>::evaluate(x,c2,c1,c0); + poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(3) poly_impl<T,3>::evaluate(x,c3,c2,c1,c0); + poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(4) poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0); + poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(5) poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0); + poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(6) poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(7) poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(8) poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(9) poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(10) poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(11) poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(12) poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } #undef poly_rtrn @@ -36202,7 +37331,7 @@ namespace exprtk typedef typename expression_t::control_block::local_data_list_t ldl_t; - ldl_t ldl = expr.local_data_list(); + const ldl_t ldl = expr.local_data_list(); std::vector<std::size_t> index_list; @@ -36371,8 +37500,16 @@ namespace exprtk template <typename BaseFuncType> struct scoped_bft { - scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); } - ~scoped_bft() { bft_.post(); } + explicit scoped_bft(BaseFuncType& bft) + : bft_(bft) + { + bft_.pre (); + } + + ~scoped_bft() + { + bft_.post(); + } BaseFuncType& bft_; @@ -36472,7 +37609,7 @@ namespace exprtk typedef typename results_context_t::type_store_t type_t; typedef typename type_t::scalar_view scalar_t; - T result = e.value(); + const T result = e.value(); if (e.return_invoked()) { @@ -36566,6 +37703,11 @@ namespace exprtk return symbol_table_; } + inline const symbol_table_t& symbol_table() const + { + return symbol_table_; + } + inline void add_auxiliary_symtab(symbol_table_t& symtab) { auxiliary_symtab_list_.push_back(&symtab); @@ -36781,89 +37923,90 @@ namespace exprtk template <typename T> inline bool pgo_primer() { - static const std::string expression_list[] - = { - "(y + x)", - "2 * (y + x)", - "(2 * y + 2 * x)", - "(y + x / y) * (x - y / x)", - "x / ((x + y) * (x - y)) / y", - "1 - ((x * y) + (y / x)) - 3", - "sin(2 * x) + cos(pi / y)", - "1 - sin(2 * x) + cos(pi / y)", - "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", - "(x^2 / sin(2 * pi / y)) -x / 2", - "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", - "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", - "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", - "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", - "(yy + xx)", - "2 * (yy + xx)", - "(2 * yy + 2 * xx)", - "(yy + xx / yy) * (xx - yy / xx)", - "xx / ((xx + yy) * (xx - yy)) / yy", - "1 - ((xx * yy) + (yy / xx)) - 3", - "sin(2 * xx) + cos(pi / yy)", - "1 - sin(2 * xx) + cos(pi / yy)", - "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", - "(xx^2 / sin(2 * pi / yy)) -xx / 2", - "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", - "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", - "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", - "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", - "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", - "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", - "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", - "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", - "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", - "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", - "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", - "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", - "2 + (x * (y / 3))", "x + (2 * (3 / y))", - "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", - "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", - "x + ((2 * 3) / y)", "(((x + y) * z) / w)", - "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", - "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", - "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", - "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", - "((x + (2 * 3)) / y)", - "(xx + yy) * zz", "xx + (yy * zz)", - "(xx + yy) * 7", "xx + (yy * 7)", - "(xx + 7) * yy", "xx + (7 * yy)", - "(7 + xx) * yy", "7 + (xx * yy)", - "(2 + x) * 3", "2 + (x * 3)", - "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", - "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", - "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", - "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", - "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", - "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", - "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", - "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", - "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", - "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", - "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", - "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", - "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", - "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", - "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", - "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", - "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", - "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", - "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", - "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", - "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", - "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", - "((xx + (2 * 3)) / yy)" - }; + static const std::string expression_list[] = + { + "(y + x)", + "2 * (y + x)", + "(2 * y + 2 * x)", + "(y + x / y) * (x - y / x)", + "x / ((x + y) * (x - y)) / y", + "1 - ((x * y) + (y / x)) - 3", + "sin(2 * x) + cos(pi / y)", + "1 - sin(2 * x) + cos(pi / y)", + "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", + "(x^2 / sin(2 * pi / y)) -x / 2", + "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", + "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", + "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", + "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", + "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", + "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", + "(yy + xx)", + "2 * (yy + xx)", + "(2 * yy + 2 * xx)", + "(yy + xx / yy) * (xx - yy / xx)", + "xx / ((xx + yy) * (xx - yy)) / yy", + "1 - ((xx * yy) + (yy / xx)) - 3", + "sin(2 * xx) + cos(pi / yy)", + "1 - sin(2 * xx) + cos(pi / yy)", + "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", + "(xx^2 / sin(2 * pi / yy)) -xx / 2", + "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", + "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", + "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", + "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", + "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", + "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", + "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", + "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", + "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", + "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", + "(x + 2) * 3", "x + (2 * 3)", + "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", + "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", + "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", + "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", + "2 + (x * (y / 3))", "x + (2 * (3 / y))", + "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", + "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", + "x + ((2 * 3) / y)", "(((x + y) * z) / w)", + "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", + "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", + "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", + "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", + "((x + (2 * 3)) / y)", + "(xx + yy) * zz", "xx + (yy * zz)", + "(xx + yy) * 7", "xx + (yy * 7)", + "(xx + 7) * yy", "xx + (7 * yy)", + "(7 + xx) * yy", "7 + (xx * yy)", + "(2 + x) * 3", "2 + (x * 3)", + "(2 + 3) * x", "2 + (3 * x)", + "(x + 2) * 3", "x + (2 * 3)", + "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", + "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", + "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", + "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", + "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", + "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", + "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", + "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", + "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", + "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", + "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", + "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", + "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", + "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", + "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", + "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", + "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", + "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", + "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", + "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", + "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", + "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", + "((xx + (2 * 3)) / yy)" + }; + static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); T x = T(0); @@ -37048,14 +38191,14 @@ namespace exprtk { if (stop_time_.tv_sec >= start_time_.tv_sec) { - return 1000000LLU * static_cast<unsigned long long int>(stop_time_.tv_sec - start_time_.tv_sec ) + - static_cast<unsigned long long int>(stop_time_.tv_usec - start_time_.tv_usec) ; + return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + + static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; } else - return std::numeric_limits<unsigned long long int>::max(); + return std::numeric_limits<details::_uint64_t>::max(); } else - return std::numeric_limits<unsigned long long int>::max(); + return std::numeric_limits<details::_uint64_t>::max(); } inline double time() const @@ -38107,10 +39250,13 @@ namespace exprtk ) return T(0); - std::size_t dist = r1 - r0 + 1; - std::size_t shift = n % dist; + const std::size_t dist = r1 - r0 + 1; + const std::size_t shift = n % dist; - std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + shift, + vec.begin() + r1 + 1); return T(1); } @@ -38158,7 +39304,10 @@ namespace exprtk std::size_t dist = r1 - r0 + 1; std::size_t shift = (dist - (n % dist)) % dist; - std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + shift, + vec.begin() + r1 + 1); return T(1); } @@ -38203,12 +39352,15 @@ namespace exprtk ) return T(0); - std::size_t dist = r1 - r0 + 1; + const std::size_t dist = r1 - r0 + 1; if (n > dist) return T(0); - std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + n, + vec.begin() + r1 + 1); for (std::size_t i = r1 - n + 1; i <= r1; ++i) { @@ -38258,14 +39410,17 @@ namespace exprtk ) return T(0); - std::size_t dist = r1 - r0 + 1; + const std::size_t dist = r1 - r0 + 1; if (n > dist) return T(0); - std::size_t shift = (dist - (n % dist)) % dist; + const std::size_t shift = (dist - (n % dist)) % dist; - std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + shift, + vec.begin() + r1 + 1); for (std::size_t i = r0; i < r0 + n; ++i) { @@ -38882,9 +40037,11 @@ namespace exprtk namespace information { static const char* library = "Mathematical Expression Toolkit"; - static const char* version = "2.71828182845904523536028747135266249775724709369995957" - "4966967627724076630353547594571382178525166427427466391"; - static const char* date = "20190818"; + static const char* version = "2.718281828459045235360287471352" + "66249775724709369995957496696762" + "77240766303535475945713821785251" + "66427427466391932003059921817413"; + static const char* date = "20210101"; static inline std::string data() {