neptools

Modding tools to Neptunia games
git clone https://git.neptards.moe/neptards/neptools.git
Log | Files | Refs | Submodules | README | LICENSE

pattern.cpp (6875B)


      1 #include "pattern_parse.hpp"
      2 
      3 #include <libshit/doctest.hpp>
      4 
      5 namespace Neptools::Test
      6 {
      7   TEST_SUITE_BEGIN("Neptools::Pattern");
      8 
      9   // static test...
     10   auto fuck_you_cpp_committee = NEPTOOLS_PATTERN("01 02 03 04");
     11   static_assert(std::is_same_v<
     12     decltype(fuck_you_cpp_committee),
     13     PatternParse::Pattern<
     14       PatternParse::ByteSequence<1,2,3,4>,
     15       PatternParse::ByteSequence<0xff,0xff,0xff,0xff>>>,
     16     "simple pattern");
     17 
     18   auto why_cant_I_use_fucking_lambdas = NEPTOOLS_PATTERN("11 05 f3 14");
     19   static_assert(std::is_same_v<
     20     decltype(why_cant_I_use_fucking_lambdas),
     21     PatternParse::Pattern<
     22       PatternParse::ByteSequence<0x11,0x05,0xf3,0x14>,
     23       PatternParse::ByteSequence<0xff,0xff,0xff,0xff>>>,
     24     "multi digit");
     25 
     26   auto in_an_unevaluated_context_like_decltype = NEPTOOLS_PATTERN("11 5 f3 4");
     27   static_assert(std::is_same_v<
     28     decltype(in_an_unevaluated_context_like_decltype),
     29     PatternParse::Pattern<
     30       PatternParse::ByteSequence<0x11,0x05,0xf3,0x04>,
     31       PatternParse::ByteSequence<0xff,0xff,0xff,0xff>>>,
     32     "shortcuts");
     33 
     34   auto or_why_cant_you_add_a_sane_way_to_use = NEPTOOLS_PATTERN("11 ?? f3 04");
     35   static_assert(std::is_same_v<
     36     decltype(or_why_cant_you_add_a_sane_way_to_use),
     37     PatternParse::Pattern<
     38       PatternParse::ByteSequence<0x11,0x00,0xf3,0x04>,
     39       PatternParse::ByteSequence<0xff,0x00,0xff,0xff>>>,
     40     "placeholder");
     41 
     42   auto fucking_strings_as_template_arguments = NEPTOOLS_PATTERN("11 ? f3 04");
     43   static_assert(std::is_same_v<
     44     decltype(fucking_strings_as_template_arguments),
     45     PatternParse::Pattern<
     46       PatternParse::ByteSequence<0x11,0x00,0xf3,0x04>,
     47       PatternParse::ByteSequence<0xff,0x00,0xff,0xff>>>,
     48     "short placeholder");
     49   // PS. you should add ctr instead of shit like a wrapper around cairo
     50 
     51   auto with_mask = NEPTOOLS_PATTERN("11 22/ff 33/f0 44/77 55/00");
     52   static_assert(std::is_same_v<
     53     decltype(with_mask),
     54     PatternParse::Pattern<
     55       PatternParse::ByteSequence<0x11, 0x22, 0x30, 0x44, 0x00>,
     56       PatternParse::ByteSequence<0xff, 0xff, 0xf0, 0x77, 0x00>>>);
     57 
     58   Byte data[] = {
     59     /* 00 */ 0xff, 0xf0, 0x64, 0x22, 0x50, 0xca, 0x9f, 0x23,
     60     /* 08 */ 0x92, 0xf7, 0xb3, 0x8f, 0xb1, 0x30, 0x8a, 0xd6,
     61     /* 10 */ 0x1e, 0x38, 0xd8, 0xf3, 0xa7, 0xfa, 0x98, 0xee,
     62     /* 18 */ 0x58, 0xec, 0x21, 0xa8, 0xfe, 0x00, 0x1c, 0xfb,
     63     /* 20 */ 0x5e, 0x0a, 0x48, 0x38, 0xc5, 0x64, 0xb5, 0xbe,
     64     /* 28 */ 0xc1, 0x48, 0xdd, 0x7f, 0x3e, 0x58, 0xec, 0x21,
     65     /* 30 */ 0x82, 0xf4, 0xca, 0x11, 0x47, 0x22, 0xcf, 0x98,
     66     /* 38 */ 0x40, 0xfe, 0x18, 0x0e, 0x2e, 0xb9, 0xfc, 0xce,
     67   };
     68   TEST_CASE("simple patterns")
     69   {
     70     Pattern p = NEPTOOLS_PATTERN("a8 fe 0 1c"); //middle
     71     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x1b);
     72     CHECK(p.Find({data, sizeof(data)}) == data + 0x1b);
     73 
     74     p = NEPTOOLS_PATTERN("ff f0 64"); //beginning
     75     CHECK(p.MaybeFind({data, sizeof(data)}) == data);
     76     CHECK(p.Find({data, sizeof(data)}) == data);
     77 
     78     p = NEPTOOLS_PATTERN("18 e 2e b9 fc ce"); //end
     79     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x3a);
     80     CHECK(p.Find({data, sizeof(data)}) == data + 0x3a);
     81   }
     82   TEST_CASE("simple not match")
     83   {
     84     auto p = NEPTOOLS_PATTERN("12 34 56 76");
     85     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
     86     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
     87   }
     88   TEST_CASE("multiple match")
     89   {
     90     auto p = NEPTOOLS_PATTERN("58 ec 21");
     91     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
     92     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
     93   }
     94 
     95   TEST_CASE("wildcards")
     96   {
     97     Pattern p = NEPTOOLS_PATTERN("48 ? c5 ? ? be"); // mid
     98     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x22);
     99     CHECK(p.Find({data, sizeof(data)}) == data + 0x22);
    100 
    101     p = NEPTOOLS_PATTERN("ff ? ? 22 50"); // begin
    102     CHECK(p.MaybeFind({data, sizeof(data)}) == data);
    103     CHECK(p.Find({data, sizeof(data)}) == data);
    104 
    105 
    106     p = NEPTOOLS_PATTERN("e ? b9 ? ce"); // end
    107     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x3b);
    108     CHECK(p.Find({data, sizeof(data)}) == data + 0x3b);
    109 
    110     p = NEPTOOLS_PATTERN("? ? fe 00 ?"); // mid
    111     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x1a);
    112     CHECK(p.Find({data, sizeof(data)}) == data + 0x1a);
    113 
    114     p = NEPTOOLS_PATTERN("? ? 64 22 ?"); // begin
    115     CHECK(p.MaybeFind({data, sizeof(data)}) == data);
    116     CHECK(p.Find({data, sizeof(data)}) == data);
    117 
    118     p = NEPTOOLS_PATTERN("? 2e b9 ? ?"); // end
    119     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x3b);
    120     CHECK(p.Find({data, sizeof(data)}) == data + 0x3b);
    121   }
    122   TEST_CASE("wildcards not match")
    123   {
    124     Pattern p = NEPTOOLS_PATTERN("12 34 ?? 56 ?? 78");
    125     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    126     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    127 
    128     p = NEPTOOLS_PATTERN("? ? 12 34 56");
    129     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    130     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    131 
    132     p = NEPTOOLS_PATTERN("12 34 ? 56 ? ? ?");
    133     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    134     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    135   }
    136   TEST_CASE("wildcards multiple match")
    137   {
    138     Pattern p = NEPTOOLS_PATTERN("58 ? 21");
    139     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    140     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    141 
    142     p = NEPTOOLS_PATTERN("? 58 ? ?");
    143     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    144     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    145 
    146     p = NEPTOOLS_PATTERN("? ? ? ?");
    147     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    148     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    149   }
    150 
    151   TEST_CASE("mask")
    152   {
    153     Byte pat[]  = { 0x58, 0xe0, 0x21, 0x28, 0x3e };
    154     Byte mask[] = { 0xff, 0xf0, 0xff, 0x2f, 0x3f };
    155     auto p = Pattern{pat, mask, 5};
    156     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x18);
    157     CHECK(p.Find({data, sizeof(data)}) == data + 0x18);
    158   }
    159 
    160   TEST_CASE("mask no match")
    161   {
    162     Byte pat[]  = { 0x58, 0xe0, 0x21, 0x18, 0x3e };
    163     Byte mask[] = { 0xff, 0xf0, 0xff, 0x1f, 0x3f };
    164     auto p = Pattern{pat, mask, 5};
    165     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    166     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    167   }
    168 
    169   TEST_CASE("mask no 0xff")
    170   {
    171     Byte pat[]  = { 0x58, 0xe0, 0x20, 0x28, 0x3e };
    172     Byte mask[] = { 0x5f, 0xf0, 0xf2, 0x2f, 0x3f };
    173     auto p = Pattern{pat, mask, 5};
    174     CHECK(p.MaybeFind({data, sizeof(data)}) == data + 0x18);
    175     CHECK(p.Find({data, sizeof(data)}) == data + 0x18);
    176 
    177     Byte pat2[]  = { 0x58, 0xe0, 0x20, 0x18, 0x3e };
    178     Byte mask2[] = { 0x5f, 0xf0, 0xf2, 0x1f, 0x3f };
    179     p = Pattern{pat2, mask2, 5};
    180     CHECK(p.MaybeFind({data, sizeof(data)}) == nullptr);
    181     CHECK_THROWS_AS(p.Find({data, sizeof(data)}), std::runtime_error);
    182   }
    183 
    184   TEST_SUITE_END();
    185 }