From c0d3c3b364f1b10d7c4829c50b21d5c5b2320a40 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Tue, 30 Dec 2014 15:58:51 +1100 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ exprtk_test.cpp | 9 ++++++- readme.txt | 7 +++--- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index b19268e..5d73cd7 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -192,6 +192,45 @@ namespace exprtk return result; } + inline bool is_hex_digit(const std::string::value_type digit) + { + return (('0' <= digit) && (digit <= '9')) || + (('A' <= digit) && (digit <= 'F')) || + (('a' <= digit) && (digit <= 'f')) ; + } + + inline unsigned char hex_to_bin(unsigned char h) + { + if (('0' <= h) && (h <= '9')) + return (h - '0'); + else + return (std::toupper(h) - 'A'); + } + + template + inline void 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))) + ) + { + result = hex_to_bin(*(itr + 2)) << 4 | hex_to_bin(*(itr + 3)); + itr += 3; + } + else + result = '\0'; + } + inline void cleanup_escapes(std::string& s) { std::string::iterator itr1 = s.begin(); @@ -214,6 +253,9 @@ namespace exprtk 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; @@ -2362,7 +2404,31 @@ namespace exprtk break; } else if (escaped) + { + if (!is_end(s_itr_) && ('0' == *(s_itr_))) + { + if ( + is_end(s_itr_ + 1) || + is_end(s_itr_ + 2) || + is_end(s_itr_ + 3) || + ( + ('x' != *(s_itr_ + 1)) && + ('X' != *(s_itr_ + 1)) + ) || + (!details::is_hex_digit(*(s_itr_ + 2))) || + (!details::is_hex_digit(*(s_itr_ + 3))) + ) + { + t.set_error(token::e_err_string,initial_itr,s_itr_,base_itr_); + token_list_.push_back(t); + return; + } + else + s_itr_ += 3; + } + escaped = false; + } ++s_itr_; } diff --git a/exprtk_test.cpp b/exprtk_test.cpp index c0e5157..3296de4 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -2237,7 +2237,13 @@ inline bool run_test02() test_ab("(a[3:9] := b); (a == '012ABCDE89');", "0123456789","ABCDE" ,T(1.0)), test_ab("(a[3:9] := b); (a == '012ABCDEF9');", "0123456789","ABCDEF" ,T(1.0)), test_ab("(a[r1 / r0:r2] := b[3:b[] - r3]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[r0:r2 + 1] := b[r3:b[] - r3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)) + test_ab("(a[r0:r2 + 1] := b[r3:b[] - r3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("'\\0x30\\0x31\\0x32\\0x33\\0x34\\0x35\\0x36\\0x37\\0x38\\0x39' == '0123456789'","","",T(1.0)), + test_ab("'abc\\0x30\\0x31\\0x32\\0x33xyz' == 'abc0123xyz'" ,"","",T(1.0)), + test_ab("'\\0x30\\n\\0x31\\n\\0x32\\n\\0x33' == '0\\n1\\n2\\n3'" ,"","",T(1.0)), + test_ab("('\\0x30' + '') == '0'" ,"","",T(1.0)), + test_ab("('\\0x30' + '\\0x31\\0x32') == '012'" ,"","",T(1.0)), + test_ab("('\\0x30' + '\\0x31\\0x32' + '\\0x33\\0x34\\0x35') == '012345'" ,"","",T(1.0)) }; static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab); @@ -2246,6 +2252,7 @@ inline bool run_test02() for (std::size_t r = 0; r < rounds; ++r) { bool result = true; + for (std::size_t i = 0; i < test_list_size; ++i) { test_ab& test = const_cast&>(test_list[i]); diff --git a/readme.txt b/readme.txt index 3d1e536..d2db35a 100644 --- a/readme.txt +++ b/readme.txt @@ -1881,9 +1881,10 @@ into account when using Exprtk: ('\n', '\r', '\t', '\b', '\v', '\f') (13) Strings may be comprised of any combination of letters, digits - or special characters including (~!@#$%^&*()[]|=+ ,./?<>;:"`~_), - and must be enclosed with single-quotes. - eg: 'Frankly my dear, 1 do n0t give a damn!' + special characters including (~!@#$%^&*()[]|=+ ,./?<>;:"`~_) or + hexadecimal escaped sequences (eg: \0x30) and must be enclosed + with single-quotes. + eg: 'Frankly my dear, \0x49 do n0t give a damn!' (14) User defined normal functions can have up to 20 parameters, where as user defined generic-functions and vararg-functions