fork download
  1. #include <cstdint>
  2. #include <iostream>
  3. #include <stdexcept>
  4. #include <utility>
  5.  
  6.  
  7. // store the string in a char_array for constexpr manipulation
  8. template <size_t N>
  9. struct pattern
  10. {
  11. uint8_t pattern[N];
  12. uint8_t wildcard[N];
  13. };
  14.  
  15. namespace detail
  16. {
  17.  
  18. constexpr uint8_t char_to_byte(char c)
  19. {
  20. if (c >= '0' && c <= '9')
  21. return c - '0';
  22. else if (c >= 'a' && c <= 'f')
  23. return 0x0A + c - 'a';
  24. else if (c >= 'A' && c <= 'F')
  25. return 0x0A + c - 'A';
  26. else
  27. throw std::runtime_error("Not a hex character.");
  28. }
  29.  
  30. template <size_t N>
  31. constexpr uint8_t get_wildcard_byte(const char(&s)[N], size_t idx)
  32. {
  33. return (s[idx * 3] == '?' ? 2 : 0) | (s[idx * 3 + 1] == '?' ? 1 : 0);
  34. }
  35.  
  36. template <size_t N>
  37. constexpr uint8_t get_pattern_byte(const char(&s)[N], size_t idx)
  38. {
  39. if (s[idx * 3 + 2] != ' ' && s[idx * 3 + 2] != '\0')
  40. throw std::runtime_error("Improperly formatted pattern.");
  41. else
  42. return (char_to_byte(s[idx * 3]) << 4) | char_to_byte(s[idx * 3 + 1]);
  43. }
  44.  
  45. template <size_t N, size_t ...Is>
  46. constexpr pattern<sizeof...(Is)> str_to_pattern(const char(&s)[N], std::index_sequence<Is...>)
  47. {
  48. return {
  49. { get_pattern_byte(s, Is)... },
  50. { get_wildcard_byte(s, Is)... },
  51. };
  52. }
  53.  
  54. } // namespace detail
  55.  
  56. template <size_t N>
  57. constexpr const pattern<N / 3> create_binary_pattern(const char(&s)[N])
  58. {
  59. return (N % 3) == 0 ? detail::str_to_pattern(s, std::make_index_sequence<N / 3>()) :
  60. throw std::runtime_error("Improperly formatted pattern.");
  61. }
  62.  
  63. template<typename Type=uint8_t*, typename Addr, size_t N>
  64. Type find_pattern1(Addr start, int size, const pattern<N>& pattern)
  65. {
  66. std::cout << pattern.pattern << sizeof(pattern.pattern);
  67. std::cout << pattern.wildcard << sizeof(pattern.wildcard);
  68. return 0;
  69. }
  70.  
  71. template<typename Type=uint8_t*, typename Addr, size_t N>
  72. Type find_pattern2(Addr start, int size, const char(&s)[N])
  73. {
  74. constexpr auto pattern = create_binary_pattern(s);
  75. return find_pattern1(start, size, pattern);
  76. }
  77.  
  78.  
  79. int main()
  80. {
  81. // Works
  82. auto res1 = find_pattern1(0, 0, create_binary_pattern("ad 02 03 04 05 06 07 08"));
  83. // Does not
  84. auto res2 = find_pattern2(0, 0, "ad 02 03 04 05 06 07 08");
  85. return 0;
  86. }
  87.  
Compilation error #stdin compilation error #stdout 0s 15232KB
stdin
Standard input is empty
compilation info
prog.cpp: In instantiation of ‘Type find_pattern2(Addr, int, const char (&)[N]) [with Type = unsigned char*; Addr = int; long unsigned int N = 24ul]’:
prog.cpp:84:62:   required from here
prog.cpp:74:51:   in constexpr expansion of ‘create_binary_pattern<24ul>((* & s))’
prog.cpp:59:49:   in constexpr expansion of ‘detail::str_to_pattern<24ul, {0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul}>(s, (std::make_index_sequence<8ul>(), std::make_index_sequence<8ul>()))’
prog.cpp:49:27:   in constexpr expansion of ‘detail::get_pattern_byte<24ul>(s, 0ul)’
prog.cpp:74:53: error: ‘s’ is not a constant expression
     constexpr auto pattern = create_binary_pattern(s);
                                                     ^
stdout
Standard output is empty