neptools

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

context.cpp (4540B)


      1 #include "context.hpp"
      2 
      3 #include "item.hpp"
      4 #include "../utils.hpp"
      5 
      6 #include <libshit/except.hpp>
      7 #include <libshit/string_utils.hpp>
      8 
      9 #include <iomanip>
     10 #include <fstream>
     11 #include <sstream>
     12 
     13 namespace Neptools
     14 {
     15 
     16   Context::Context()
     17     : ItemWithChildren{Key{}, *this}
     18   {}
     19 
     20   Context::~Context()
     21   {
     22     Context::Dispose();
     23   }
     24 
     25   void Context::SetupParseFrom(Item& item)
     26   {
     27     pmap[0] = &item;
     28     GetChildren().push_back(item); // noexcept
     29   }
     30 
     31   void Context::Fixup()
     32   {
     33     pmap.clear();
     34 
     35     FilePosition pos = 0;
     36     for (auto& c : GetChildren())
     37     {
     38       c.UpdatePosition(pos);
     39       pos += c.GetSize();
     40     }
     41     // todo? size = pos;
     42   }
     43 
     44 
     45   Libshit::NotNull<LabelPtr> Context::GetLabel(const std::string& name) const
     46   {
     47     auto it = labels.find(name);
     48     if (it == labels.end())
     49       LIBSHIT_THROW(std::out_of_range, "Context::GetLabel",
     50                     "Affected label", name);
     51     return MakeNotNull(const_cast<Label*>(&*it));
     52   }
     53 
     54   Libshit::NotNull<LabelPtr> Context::CreateLabel(
     55     std::string name, ItemPointer ptr)
     56   {
     57     auto lbl = new Label{std::move(name), ptr};
     58     auto pair = labels.insert(*lbl);
     59     if (!pair.second)
     60     {
     61       name = std::move(lbl->name);
     62       delete lbl;
     63       LIBSHIT_THROW(std::out_of_range, "label already exists",
     64                     "Affected label", std::move(name));
     65     }
     66 
     67     ptr->labels.insert(*pair.first);
     68     return MakeNotNull(&*pair.first);
     69   }
     70 
     71   Libshit::NotNull<LabelPtr> Context::CreateLabelFallback(
     72     const std::string& name, ItemPointer ptr)
     73   {
     74     LabelsMap::insert_commit_data commit;
     75     std::string str = name;
     76 
     77     auto pair = labels.insert_check(str, commit);
     78     for (int i = 1; !pair.second; ++i)
     79     {
     80       std::stringstream ss;
     81       ss << name << '_' << i;
     82       str = ss.str();
     83       pair = labels.insert_check(str, commit);
     84     }
     85 
     86     auto it = labels.insert_commit(*new Label{std::move(str), ptr}, commit);
     87 
     88     ptr->labels.insert(*it);
     89     return MakeNotNull(&*it);
     90   }
     91 
     92   Libshit::NotNull<LabelPtr> Context::CreateOrSetLabel(
     93     std::string name, ItemPointer ptr)
     94   {
     95     LabelsMap::insert_commit_data commit;
     96     auto [it, insertable] = labels.insert_check(name, commit);
     97 
     98     if (insertable)
     99     {
    100       auto it = labels.insert_commit(*new Label{std::move(name), ptr}, commit);
    101       ptr->labels.insert(*it);
    102       return MakeNotNull(&*it);
    103     }
    104     else
    105     {
    106       if (it->ptr != nullptr) it->ptr->labels.remove_node(*it);
    107       it->ptr = ptr;
    108       ptr->labels.insert(*it);
    109       return MakeNotNull(&*it);
    110     }
    111   }
    112 
    113   Libshit::NotNull<LabelPtr> Context::GetOrCreateDummyLabel(std::string name)
    114   {
    115     LabelsMap::insert_commit_data commit;
    116     auto [it, insertable] = labels.insert_check(name, commit);
    117 
    118     if (insertable)
    119       it = labels.insert_commit(
    120         *new Label{std::move(name), {nullptr,0}}, commit);
    121     return MakeNotNull(const_cast<Label*>(&*it));
    122   }
    123 
    124   Libshit::NotNull<LabelPtr> Context::GetLabelTo(ItemPointer ptr)
    125   {
    126     auto& lctr = ptr.item->labels;
    127     auto it = lctr.find(ptr.offset);
    128     if (it != lctr.end()) return MakeNotNull(&*it);
    129 
    130     std::stringstream ss;
    131     ss << "loc_" << std::setw(8) << std::setfill('0') << std::hex
    132        << ptr.item->GetPosition() + ptr.offset;
    133     return CreateLabelFallback(ss.str(), ptr);
    134   }
    135 
    136   Libshit::NotNull<LabelPtr> Context::GetLabelTo(
    137     FilePosition pos, const std::string& name)
    138   {
    139     auto ptr = GetPointer(pos);
    140     auto& lctr = ptr.item->labels;
    141     auto it = lctr.find(ptr.offset);
    142     if (it != lctr.end()) return MakeNotNull(&*it);
    143 
    144     return CreateLabelFallback(name, ptr);
    145   }
    146 
    147   ItemPointer Context::GetPointer(FilePosition pos) const noexcept
    148   {
    149     auto it = pmap.upper_bound(pos);
    150     LIBSHIT_ASSERT_MSG(it != pmap.begin(), "file position out of range");
    151     --it;
    152     LIBSHIT_ASSERT(it->first == it->second->GetPosition());
    153     return {it->second, pos - it->first};
    154   }
    155 
    156   void Context::Dispose() noexcept
    157   {
    158     pmap.clear();
    159     struct Disposer
    160     {
    161       void operator()(Label* l)
    162       {
    163         auto& item = l->ptr.item;
    164         if (item)
    165         {
    166           item->labels.erase(item->labels.iterator_to(*l));
    167           item = nullptr;
    168         }
    169         l->RemoveRef();
    170       }
    171     };
    172     labels.clear_and_dispose(Disposer{});
    173     GetChildren().clear();
    174 
    175     ItemWithChildren::Dispose();
    176   }
    177 
    178   std::ostream& operator<<(std::ostream& os, PrintLabelStruct l)
    179   {
    180     if (l.label == nullptr)
    181       return os << "nil";
    182     return os << "l(" << Libshit::Quoted(l.label->GetName()) << ')';
    183   }
    184 
    185 }
    186 
    187 #include "context.binding.hpp"