#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <utility>
// store the string in a char_array for constexpr manipulation
template < size_t N>
struct pattern
{
uint8_t pattern[ N] ;
uint8_t wildcard[ N] ;
} ;
namespace detail
{
constexpr uint8_t char_to_byte( char c)
{
if ( c >= '0' && c <= '9' )
return c - '0' ;
else if ( c >= 'a' && c <= 'f' )
return 0x0A + c - 'a' ;
else if ( c >= 'A' && c <= 'F' )
return 0x0A + c - 'A' ;
else
throw std:: runtime_error ( "Not a hex character." ) ;
}
template < size_t N>
constexpr uint8_t get_wildcard_byte( const char ( & s) [ N] , size_t idx)
{
return ( s[ idx * 3 ] == '?' ? 2 : 0 ) | ( s[ idx * 3 + 1 ] == '?' ? 1 : 0 ) ;
}
template < size_t N>
constexpr uint8_t get_pattern_byte( const char ( & s) [ N] , size_t idx)
{
if ( s[ idx * 3 + 2 ] ! = ' ' && s[ idx * 3 + 2 ] ! = '\0 ' )
throw std:: runtime_error ( "Improperly formatted pattern." ) ;
else
return ( char_to_byte( s[ idx * 3 ] ) << 4 ) | char_to_byte( s[ idx * 3 + 1 ] ) ;
}
template < size_t N, size_t ...Is >
constexpr pattern< sizeof ...( Is) > str_to_pattern( const char ( & s) [ N] , std:: index_sequence < Is...> )
{
return {
{ get_pattern_byte( s, Is) ... } ,
{ get_wildcard_byte( s, Is) ... } ,
} ;
}
} // namespace detail
template < size_t N>
constexpr const pattern< N / 3 > create_binary_pattern( const char ( & s) [ N] )
{
return ( N % 3 ) == 0 ? detail:: str_to_pattern ( s, std:: make_index_sequence < N / 3 > ( ) ) :
throw std:: runtime_error ( "Improperly formatted pattern." ) ;
}
template < typename Type= uint8_t * , typename Addr, size_t N>
Type find_pattern1( Addr start, int size, const pattern< N> & pattern)
{
std:: cout << pattern.pattern << sizeof ( pattern.pattern ) ;
std:: cout << pattern.wildcard << sizeof ( pattern.wildcard ) ;
return 0 ;
}
template < typename Type= uint8_t * , typename Addr, size_t N>
Type find_pattern2( Addr start, int size, const char ( & s) [ N] )
{
constexpr auto pattern = create_binary_pattern( s) ;
return find_pattern1( start, size, pattern) ;
}
int main( )
{
// Works
auto res1 = find_pattern1( 0 , 0 , create_binary_pattern( "ad 02 03 04 05 06 07 08" ) ) ;
// Does not
auto res2 = find_pattern2( 0 , 0 , "ad 02 03 04 05 06 07 08" ) ;
return 0 ;
}
I2luY2x1ZGUgPGNzdGRpbnQ+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHN0ZGV4Y2VwdD4KI2luY2x1ZGUgPHV0aWxpdHk+CgkJCgovLyBzdG9yZSB0aGUgc3RyaW5nIGluIGEgY2hhcl9hcnJheSBmb3IgY29uc3RleHByIG1hbmlwdWxhdGlvbgp0ZW1wbGF0ZSA8c2l6ZV90IE4+CnN0cnVjdCBwYXR0ZXJuCnsKICAgIHVpbnQ4X3QgcGF0dGVybltOXTsKICAgIHVpbnQ4X3Qgd2lsZGNhcmRbTl07Cn07CgpuYW1lc3BhY2UgZGV0YWlsCnsKCmNvbnN0ZXhwciB1aW50OF90IGNoYXJfdG9fYnl0ZShjaGFyIGMpCnsKICAgIGlmIChjID49ICcwJyAmJiBjIDw9ICc5JykKICAgICAgICByZXR1cm4gYyAtICcwJzsKICAgIGVsc2UgaWYgKGMgPj0gJ2EnICYmIGMgPD0gJ2YnKQogICAgICAgIHJldHVybiAweDBBICsgYyAtICdhJzsKICAgIGVsc2UgaWYgKGMgPj0gJ0EnICYmIGMgPD0gJ0YnKQogICAgICAgIHJldHVybiAweDBBICsgYyAtICdBJzsKICAgIGVsc2UKICAgICAgICB0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoIk5vdCBhIGhleCBjaGFyYWN0ZXIuIik7Cn0KCnRlbXBsYXRlIDxzaXplX3QgTj4KY29uc3RleHByIHVpbnQ4X3QgZ2V0X3dpbGRjYXJkX2J5dGUoY29uc3QgY2hhcigmcylbTl0sIHNpemVfdCBpZHgpCnsKICAgIHJldHVybiAoc1tpZHggKiAzXSA9PSAnPycgPyAyIDogMCkgfCAoc1tpZHggKiAzICsgMV0gPT0gJz8nID8gMSA6IDApOwp9Cgp0ZW1wbGF0ZSA8c2l6ZV90IE4+CmNvbnN0ZXhwciB1aW50OF90IGdldF9wYXR0ZXJuX2J5dGUoY29uc3QgY2hhcigmcylbTl0sIHNpemVfdCBpZHgpCnsKICAgIGlmIChzW2lkeCAqIDMgKyAyXSAhPSAnICcgJiYgc1tpZHggKiAzICsgMl0gIT0gJ1wwJykKICAgICAgICB0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoIkltcHJvcGVybHkgZm9ybWF0dGVkIHBhdHRlcm4uIik7CiAgICBlbHNlCiAgICAgICAgcmV0dXJuIChjaGFyX3RvX2J5dGUoc1tpZHggKiAzXSkgPDwgNCkgfCBjaGFyX3RvX2J5dGUoc1tpZHggKiAzICsgMV0pOwp9Cgp0ZW1wbGF0ZSA8c2l6ZV90IE4sIHNpemVfdCAuLi5Jcz4KY29uc3RleHByIHBhdHRlcm48c2l6ZW9mLi4uKElzKT4gc3RyX3RvX3BhdHRlcm4oY29uc3QgY2hhcigmcylbTl0sIHN0ZDo6aW5kZXhfc2VxdWVuY2U8SXMuLi4+KQp7CiAgICByZXR1cm4gewogICAgICAgIHsgZ2V0X3BhdHRlcm5fYnl0ZShzLCBJcykuLi4gfSwKICAgICAgICB7IGdldF93aWxkY2FyZF9ieXRlKHMsIElzKS4uLiB9LAogICAgfTsKfQoKfSAgIC8vIG5hbWVzcGFjZSBkZXRhaWwKCnRlbXBsYXRlIDxzaXplX3QgTj4KY29uc3RleHByIGNvbnN0IHBhdHRlcm48TiAvIDM+IGNyZWF0ZV9iaW5hcnlfcGF0dGVybihjb25zdCBjaGFyKCZzKVtOXSkKewogICAgcmV0dXJuIChOICUgMykgPT0gMCA/IGRldGFpbDo6c3RyX3RvX3BhdHRlcm4ocywgc3RkOjptYWtlX2luZGV4X3NlcXVlbmNlPE4gLyAzPigpKSA6CiAgICB0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoIkltcHJvcGVybHkgZm9ybWF0dGVkIHBhdHRlcm4uIik7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFR5cGU9dWludDhfdCosIHR5cGVuYW1lIEFkZHIsIHNpemVfdCBOPgpUeXBlIGZpbmRfcGF0dGVybjEoQWRkciBzdGFydCwgaW50IHNpemUsIGNvbnN0IHBhdHRlcm48Tj4mIHBhdHRlcm4pCnsKICAgIHN0ZDo6Y291dCA8PCBwYXR0ZXJuLnBhdHRlcm4gIDw8IHNpemVvZihwYXR0ZXJuLnBhdHRlcm4pOwogICAgc3RkOjpjb3V0IDw8IHBhdHRlcm4ud2lsZGNhcmQgPDwgc2l6ZW9mKHBhdHRlcm4ud2lsZGNhcmQpOwogICAgcmV0dXJuIDA7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFR5cGU9dWludDhfdCosIHR5cGVuYW1lIEFkZHIsIHNpemVfdCBOPgpUeXBlIGZpbmRfcGF0dGVybjIoQWRkciBzdGFydCwgaW50IHNpemUsIGNvbnN0IGNoYXIoJnMpW05dKQp7CiAgICBjb25zdGV4cHIgYXV0byBwYXR0ZXJuID0gY3JlYXRlX2JpbmFyeV9wYXR0ZXJuKHMpOwogICAgcmV0dXJuIGZpbmRfcGF0dGVybjEoc3RhcnQsIHNpemUsIHBhdHRlcm4pOwp9CgoKaW50IG1haW4oKQp7CiAgICAvLyBXb3JrcwogICAgYXV0byByZXMxID0gZmluZF9wYXR0ZXJuMSgwLCAwLCBjcmVhdGVfYmluYXJ5X3BhdHRlcm4oImFkIDAyIDAzIDA0IDA1IDA2IDA3IDA4IikpOwogICAgLy8gRG9lcyBub3QKICAgIGF1dG8gcmVzMiA9IGZpbmRfcGF0dGVybjIoMCwgMCwgImFkIDAyIDAzIDA0IDA1IDA2IDA3IDA4Iik7CiAgICByZXR1cm4gMDsKfQo=
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