scraps

Abandon all hope, ye who enter here.
git clone https://git.neptards.moe/neptards/scraps.git
Log | Files | Refs | Submodules | README | LICENSE

property.cpp (6272B)


      1 #include "scraps/game/text_replace/text_replace_private.hpp" // IWYU pragma: associated
      2 
      3 #include "scraps/game/character_state.hpp"
      4 #include "scraps/game/game_state.hpp"
      5 #include "scraps/game/object_state.hpp" // IWYU pragma: keep
      6 #include "scraps/game/room_state.hpp" // IWYU pragma: keep
      7 #include "scraps/game/timer_state.hpp" // IWYU pragma: keep
      8 #include "scraps/game/variable_state.hpp" // IWYU pragma: keep
      9 #include "scraps/string_utils.hpp"
     10 #include "scraps/uuid.hpp"
     11 
     12 #include <libshit/char_utils.hpp>
     13 #include <libshit/doctest_std.hpp>
     14 
     15 #include <optional>
     16 
     17 #define LIBSHIT_LOG_NAME "text_replace"
     18 #include <libshit/logger_helper.hpp>
     19 
     20 // IWYU pragma: no_include <type_traits>
     21 // IWYU pragma: no_forward_declare Scraps::Game::NameKey
     22 // IWYU pragma: no_forward_declare Scraps::Game::UuidKey
     23 
     24 namespace Scraps::Game::TextReplacePrivate
     25 {
     26   using namespace Libshit::NonowningStringLiterals;
     27   TEST_SUITE_BEGIN("Scraps::Game::TextReplace");
     28 
     29   template <typename T>
     30   static MacroRes GetGenProp(
     31     MacroParam p, Libshit::StringView val, Libshit::StringView what, T fun)
     32   {
     33     auto colon0 = val.find_first_of(':');
     34     if (colon0 == Libshit::StringView::npos) return { ""_ns, p.macro.size() };
     35     auto name = Trim(val.substr(0, colon0));
     36     auto key = Trim(
     37       val.substr(colon0 + 1, val.find_first_of(':', colon0 + 1) - colon0 - 1));
     38 
     39     auto r = fun(name);
     40     if (!r.has_value())
     41     {
     42       WARN << Libshit::Quoted(p.macro) << ": No such " << what << std::endl;
     43       return { ""_ns, p.macro.size() };
     44     }
     45 
     46     auto prop = r->GetProperties().Get(key);
     47     if (!prop)
     48     {
     49       WARN << Libshit::Quoted(p.macro) << ": No such " << what << " property"
     50            << std::endl;
     51       return { ""_ns, p.macro.size() };
     52     }
     53 
     54     if (p.new_value)
     55     {
     56       // need to copy the old value out since Set *might* invalidate the old sv
     57       p.tmp_str.assign(prop->second);
     58       PropertiesProxy{ProxyConstCast{}, r->GetProperties()}.
     59         Set(key, p.new_value->to_string());
     60       return { p.tmp_str, p.macro.size() };
     61     }
     62     return { prop->second, p.macro.size() };
     63   }
     64 
     65   template <typename T>
     66   static MacroRes GetSimpleProp(
     67     MacroParam p, Libshit::StringView val, Libshit::StringView what,
     68     const T& coll)
     69   {
     70     return GetGenProp(
     71       p, val, what, [&](Libshit::StringView name)
     72       { return coll.template Get<NameKey>(name); });
     73   }
     74 
     75   template <typename T>
     76   static MacroRes GetUuidProp(
     77     MacroParam p, Libshit::StringView val, Libshit::StringView what,
     78     const T& coll)
     79   {
     80     return GetGenProp(p, val, what, [&](Libshit::StringView name)
     81       -> decltype(coll.template Get<NameKey>(name))
     82     {
     83       if (auto paren = name.find_first_of('('); paren != Libshit::StringView::npos)
     84       {
     85         auto uuid = Uuid::TryParse(name.substr(0, paren)); if (!uuid) return {};
     86         return coll.template Get<UuidKey>(*uuid);
     87       }
     88       else
     89         return coll.template Get<NameKey>(name);
     90     });
     91   }
     92 
     93   MacroRes GetCharacterProp(MacroParam p, Libshit::StringView val)
     94   { return GetSimpleProp(p, val, "character", p.gs.GetCharacterColl()); }
     95 
     96   MacroRes GetObjectProp(MacroParam p, Libshit::StringView val)
     97   { return GetUuidProp(p, val, "object", p.gs.GetObjectColl()); }
     98 
     99   MacroRes GetPlayerProp(MacroParam p, Libshit::StringView val)
    100   {
    101     auto x = p.gs.GetPlayer().GetProperties().Get(Trim(val));
    102     return { x ? x->second : ""_ns, p.macro.size() };
    103   }
    104 
    105   MacroRes GetRoomProp(MacroParam p, Libshit::StringView val)
    106   { return GetUuidProp(p, val, "room", p.gs.GetRoomColl()); }
    107 
    108   MacroRes GetTimerProp(MacroParam p, Libshit::StringView val)
    109   { return GetSimpleProp(p, val, "timer", p.gs.GetTimerColl()); }
    110 
    111   MacroRes GetVariableProp(MacroParam p, Libshit::StringView val)
    112   {
    113     return GetGenProp(
    114       p, val, "variable", [&](Libshit::StringView name)
    115       {
    116         return p.gs.GetVariableColl().Get<NameKey>(
    117           StripIndexFromVariableName(name));
    118       });
    119   }
    120 
    121   TEST_CASE_FIXTURE(MacroFixture, "properties")
    122   {
    123 #define RP(str) GetRoomProp(COLON_ARGS("rp", str, {}))
    124     // valid
    125     CHECK(RP("room_0:key_0") == MacroRes{"Value 0", 17});
    126     CHECK(RP(" room_0 : key_0 ") == MacroRes{"Value 0", 21});
    127     CHECK(RP("roOM_0:Key_0") == MacroRes{"Value 0", 17});
    128     CHECK(RP("00000000-0000-4004-0000-000000000001(:key_0") ==
    129           MacroRes{"Value 0", 48});
    130     CHECK(RP("00000000-0000-4004-0000-000000000001 (:key_0") ==
    131           MacroRes{"Value 0", 49});
    132     CHECK(RP("room_0:key_0:garbage") == MacroRes{"Value 0", 25});
    133 
    134     // invalid
    135     CHECK(RP("room_0:key_z") == MacroRes{"", 17});
    136     CHECK(RP("room_z:key_0") == MacroRes{"", 17});
    137     CHECK(RP("00000000-0000-4004-0000000000000001(:key_0") == MacroRes{"", 47});
    138     CHECK(RP("foo") == MacroRes{"", 8});
    139 #undef RP
    140 
    141     // object is pretty much the same as room
    142     CHECK(GetObjectProp(COLON_ARGS("ip", "object_0:key_1", {})) ==
    143           MacroRes{"Value 1", 19});
    144 
    145     // and the simple ones
    146     CHECK(GetCharacterProp(COLON_ARGS("cp", "chara_0:key_0", {})) ==
    147           MacroRes{"Value 0", 18});
    148     CHECK(GetVariableProp(COLON_ARGS("vp", " Var_0 : Key_1 ", {})) ==
    149           MacroRes{"Value 1", 20});
    150     CHECK(GetVariableProp(COLON_ARGS("vp", " Var_0(foo : Key_1 ", {})) ==
    151           MacroRes{"Value 1", 24});
    152     CHECK(GetTimerProp(COLON_ARGS("tp", "timeR_0 : Key_0", {})) ==
    153           MacroRes{"Value 0", 20});
    154     CHECK(GetTimerProp(COLON_ARGS("tp", "timer_0:no", {})) == MacroRes{"", 15});
    155     CHECK(GetTimerProp(COLON_ARGS("tp", "no:key_0", {})) == MacroRes{"", 13});
    156 
    157     // player is completely different
    158 #define PP(str) GetPlayerProp(COLON_ARGS("pp", str, {}))
    159     CHECK(PP("key_0") == MacroRes{"Value 0", 10});
    160     CHECK(PP(" Key_1 ") == MacroRes{"Value 1", 12});
    161     CHECK(PP("no") == MacroRes{"", 7});
    162     CHECK(PP("key_0:") == MacroRes{"", 11});
    163 #undef PP
    164 
    165     // set tests
    166     auto props = gs.GetCharacterColl().At(0).GetProperties();
    167     CHECK(GetCharacterProp(COLON_ARGS("cp", "chara_0:key_0", "new")) ==
    168                            MacroRes{"Value 0", 18});
    169     CHECK(props.Get("key_0").value().second == "new");
    170     CHECK(GetCharacterProp(COLON_ARGS("cp", "chara_0:key_0", "other")) ==
    171                            MacroRes{"new", 18});
    172     CHECK(props.Get("key_0").value().second == "other");
    173   }
    174 
    175   TEST_SUITE_END();
    176 }