Advertisement
Guest User

Untitled

a guest
Dec 4th, 2016
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.92 KB | None | 0 0
  1. #include <cassert>
  2. #include <string>
  3. #include <algorithm>
  4.  
  5. #define wxToupper toupper
  6. using wxString = std::string;
  7.  
  8. /**
  9.  * class CONST_WX_STRING_VIEW
  10.  * represents a const_iterator range inside a wxString, helper class for parsing needs.
  11.  */
  12. class CONST_WX_STRING_VIEW
  13. {
  14. public:
  15.     using iterator = wxString::const_iterator;
  16.     using value_type = iterator::value_type;
  17.  
  18.     CONST_WX_STRING_VIEW(iterator aBegin, iterator aEnd)
  19.         : m_begin(std::move(aBegin)), m_end(std::move(aEnd))
  20.     {}
  21.  
  22.     CONST_WX_STRING_VIEW(const wxString& aString)
  23.         : m_begin(aString.begin()), m_end(aString.end())
  24.     {
  25.     }
  26.  
  27.     CONST_WX_STRING_VIEW(const wxString& aString, size_t aCount)
  28.         : m_begin(aString.begin())
  29.     {
  30.         auto it = aString.begin();
  31.         std::advance(it, std::min(aCount, aString.size()));
  32.         m_end = it;
  33.     }
  34.  
  35.     CONST_WX_STRING_VIEW(const CONST_WX_STRING_VIEW& aString, size_t aCount)
  36.         : m_begin(aString.begin())
  37.     {
  38.         auto it = aString.begin();
  39.         std::advance(it, std::min(aCount, aString.size()));
  40.         m_end = it;
  41.     }
  42.  
  43.     CONST_WX_STRING_VIEW(const CONST_WX_STRING_VIEW&) = default;
  44.     CONST_WX_STRING_VIEW(CONST_WX_STRING_VIEW&&) = default;
  45.     CONST_WX_STRING_VIEW& operator=(CONST_WX_STRING_VIEW&&) = default;
  46.     CONST_WX_STRING_VIEW& operator=(const CONST_WX_STRING_VIEW&) = default;
  47.  
  48.     CONST_WX_STRING_VIEW& operator++()
  49.     {
  50.         ++m_begin;
  51.         return *this;
  52.     }
  53.  
  54.     CONST_WX_STRING_VIEW operator++(int)
  55.     {
  56.         auto temp = *this;
  57.         ++m_begin;
  58.         return temp;
  59.     }
  60.  
  61.     size_t size() const {
  62.         return std::distance(m_begin, m_end);
  63.     }
  64.  
  65.     value_type operator*() const
  66.     {
  67.         return *m_begin;
  68.     }
  69.  
  70.     explicit operator bool() const
  71.     {
  72.         return m_begin != m_end;
  73.     }
  74.  
  75.     const iterator& begin() const {
  76.         return m_begin;
  77.     }
  78.  
  79.     const iterator& end() const {
  80.         return m_end;
  81.     }
  82.  
  83.     wxString str() const {
  84.         return wxString(m_begin, m_end);
  85.     }
  86.  
  87. private:
  88.     iterator m_begin, m_end;
  89. };
  90.  
  91. //
  92. // Flags for StrNumCmp
  93. //
  94. enum class STR_NUM_CMP_FLAGS : unsigned int {
  95.     Default = 0,
  96.     ExtendedNumbers = 1, // 3V3 => 3.3
  97.     IgnoreCase = 2
  98. };
  99.  
  100. // Helper for flag concatenation
  101. constexpr STR_NUM_CMP_FLAGS operator| (STR_NUM_CMP_FLAGS lhs, STR_NUM_CMP_FLAGS rhs)
  102. {
  103.     return (STR_NUM_CMP_FLAGS)(static_cast<unsigned int>(lhs) | static_cast<unsigned int>(rhs));
  104. }
  105.  
  106. // Helper for flag testing
  107. constexpr bool operator& (STR_NUM_CMP_FLAGS lhs, STR_NUM_CMP_FLAGS rhs)
  108. {
  109.     return (static_cast<unsigned int>(lhs) & static_cast<unsigned int>(rhs)) != 0;
  110. }
  111.  
  112. //
  113. // Helper functions
  114. //
  115. namespace {
  116.  
  117.     bool use_extended_numbers(STR_NUM_CMP_FLAGS flags) {
  118.         return flags & STR_NUM_CMP_FLAGS::ExtendedNumbers;
  119.     }
  120.  
  121.     bool use_ignore_case(STR_NUM_CMP_FLAGS flags)
  122.     {
  123.         return flags & STR_NUM_CMP_FLAGS::IgnoreCase;
  124.     }
  125.  
  126.     bool parse_number(CONST_WX_STRING_VIEW& aString, double& aDouble, STR_NUM_CMP_FLAGS aFlags)
  127.     {
  128.         auto   local = aString;
  129.         size_t digits = 0;
  130.         double factor = 1;
  131.         size_t decimals = 0;
  132.         double number = 0;
  133.  
  134.         bool parsed_decimal_point = false;
  135.  
  136.         while(local) {
  137.              if(isdigit(*local))
  138.             {
  139.                 if(parsed_decimal_point) {
  140.                     ++decimals;
  141.                     number += double(*local - '0') * pow(10., -static_cast<int>(decimals));
  142.                 }
  143.                 else {
  144.                     number = number * 10 + double(*local - '0');
  145.                 }
  146.                 ++digits;
  147.             }
  148.             else if(use_extended_numbers(aFlags) && digits == 0 && (*local == '+') || (*local == '-'))
  149.             {
  150.                 if(*local == '-') {
  151.                     factor = -1;
  152.                 }
  153.             }
  154.             else if(use_extended_numbers(aFlags) && !parsed_decimal_point)
  155.             {
  156.                 switch((*local)/*.GetValue()*/ ) {
  157.                 case 'V':
  158.                 case 'v':
  159.                 case '.':
  160.                     parsed_decimal_point = true;
  161.                 }
  162.  
  163.                 if(!parsed_decimal_point) break;
  164.             }
  165.             else
  166.             {
  167.                 break;
  168.             }
  169.  
  170.             ++local;
  171.         }
  172.  
  173.         if(digits > 0)
  174.         {
  175.             aString = local;
  176.             aDouble = factor * number;
  177.             return true;
  178.         }
  179.         else
  180.         {
  181.             return false;
  182.         }
  183.     }
  184.  
  185. }
  186.  
  187. int StrNumCmp(CONST_WX_STRING_VIEW aString1, CONST_WX_STRING_VIEW aString2,
  188.     STR_NUM_CMP_FLAGS flags = STR_NUM_CMP_FLAGS::Default);
  189.  
  190. int StrNumCmp(CONST_WX_STRING_VIEW aString1, CONST_WX_STRING_VIEW aString2, size_t aCount,
  191.     STR_NUM_CMP_FLAGS flags = STR_NUM_CMP_FLAGS::Default);
  192.  
  193. int StrNumCmp(CONST_WX_STRING_VIEW aString1, CONST_WX_STRING_VIEW aString2, STR_NUM_CMP_FLAGS flags)
  194. {
  195.     while(aString1 && aString2) {
  196.         double num1;
  197.         double num2;
  198.         bool is_num1 = parse_number(aString1, num1, flags);
  199.         bool is_num2 = parse_number(aString2, num2, flags);
  200.  
  201.         if(is_num1 && is_num2)
  202.         {
  203.             if(num1 < num2) return -1;
  204.             if(num2 < num1) return  1;
  205.         }
  206.         else
  207.         {
  208.             auto a = *aString1;
  209.             auto b = *aString2;
  210.  
  211.             if(use_ignore_case(flags))
  212.             {
  213.                 a = wxToupper(a);
  214.                 b = wxToupper(b);
  215.             }
  216.  
  217.             if(a < b) return -1;
  218.             if(b < a) return  1;
  219.  
  220.             ++aString1;
  221.             ++aString2;
  222.         }
  223.     }
  224.  
  225.     if(aString1 && !aString2) return  1;
  226.     if(aString2 && !aString1) return -1;
  227.  
  228.     return 0;
  229. }
  230.  
  231. int StrNumCmp(CONST_WX_STRING_VIEW aString1, CONST_WX_STRING_VIEW aString2, size_t aCount, STR_NUM_CMP_FLAGS aFlags)
  232. {
  233.     return StrNumCmp({ aString1, aCount }, { aString2, aCount }, aFlags);
  234. }
  235.  
  236. int main()
  237. {
  238.     assert( StrNumCmp( {   "" }, {  "" } )    ==  0 );
  239.     assert( StrNumCmp( {  "A" }, {  "" } )   ==  1 );
  240.     assert( StrNumCmp( {   "" }, { "B" } )   == -1 );
  241.     assert( StrNumCmp( {  "1" }, { "2" } )  == -1 );
  242.     assert( StrNumCmp( { "10" }, { "2" } ) ==  1 );
  243.     assert( StrNumCmp( {  "a" }, { "b" } )  == -1 );
  244.     assert( StrNumCmp( {  "a" }, { "A" } )  ==  1 );
  245.     assert( StrNumCmp( {  "aAa" }, { "AaA" }, STR_NUM_CMP_FLAGS::IgnoreCase) == 0);
  246.     assert( StrNumCmp( { "A34B32C43D2" }, { "A34B32C230D" }) == -1 );
  247.  
  248.     // constrained mode
  249.     assert(StrNumCmp({ "P100" }, { "P2" }, 2) == -1);
  250.  
  251.     // Gyros-Mode
  252.     assert( StrNumCmp({   "3V3" }, {  "3.3" }, STR_NUM_CMP_FLAGS::ExtendedNumbers) ==  0 );
  253.     assert( StrNumCmp({  "+3V3" }, {  "3.3" }, STR_NUM_CMP_FLAGS::ExtendedNumbers) ==  0 );
  254.     assert( StrNumCmp({ "+3V3A" }, { "3.3B" }, STR_NUM_CMP_FLAGS::ExtendedNumbers) == -1 );
  255.     assert( StrNumCmp({  "-3V3" }, {  "3.3" }, STR_NUM_CMP_FLAGS::ExtendedNumbers) == -1 );
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement