neptools

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

file.cpp (3108B)


      1 #include "file.hpp"
      2 #include "header.hpp"
      3 #include "../cstring_item.hpp"
      4 #include "../eof_item.hpp"
      5 #include "../raw_item.hpp"
      6 #include "../../open.hpp"
      7 
      8 #include <boost/algorithm/string/replace.hpp>
      9 
     10 namespace Neptools::Stsc
     11 {
     12 
     13   File::File(Source src, Flavor flavor) : flavor{flavor}
     14   {
     15     ADD_SOURCE(Parse_(src), src);
     16   }
     17 
     18   void File::Parse_(Source& src)
     19   {
     20     auto root = Create<RawItem>(src);
     21     SetupParseFrom(*root);
     22     root->Split(root->GetSize(), Create<EofItem>());
     23     HeaderItem::CreateAndInsert({&*root, 0}, flavor);
     24   }
     25 
     26   void File::Inspect_(std::ostream& os, unsigned indent) const
     27   {
     28     LIBSHIT_ASSERT(GetLabels().empty());
     29     os << "neptools.stsc.file(neptools.stsc.flavor." << ToString(flavor) << ")";
     30     InspectChildren(os, indent);
     31   }
     32 
     33   static const char SEP_DASH[] = {
     34 #define REP_MACRO(x,y,z) '-',
     35     BOOST_PP_REPEAT(40, REP_MACRO, )
     36     '\r', 0,
     37   };
     38 
     39   void File::WriteTxt_(std::ostream& os) const
     40   {
     41     for (auto& it : GetChildren())
     42     {
     43       auto str = dynamic_cast<const CStringItem*>(&it);
     44       if (str)
     45       {
     46         os << boost::replace_all_copy(str->string, "\\n", "\r\n")
     47            << "\r\n" << SEP_DASH << '\n';
     48       }
     49     }
     50   }
     51 
     52   void File::ReadTxt_(std::istream& is)
     53   {
     54     std::string line, msg;
     55     auto it = GetChildren().begin();
     56     auto end = GetChildren().end();
     57     while (it != end && !dynamic_cast<CStringItem*>(&*it)) ++it;
     58 
     59     is.exceptions(std::ios_base::badbit);
     60     while (!std::getline(is, line).fail())
     61     {
     62       if (line == SEP_DASH)
     63       {
     64         if (it == end)
     65           LIBSHIT_THROW(Libshit::DecodeError, "StscTxt: too many strings");
     66 
     67         LIBSHIT_ASSERT(msg.empty() || msg.substr(msg.length()-2) == "\\n");
     68         if (!msg.empty()) { msg.pop_back(); msg.pop_back(); }
     69         static_cast<CStringItem&>(*it).string = std::move(msg);
     70 
     71         ++it;
     72         while (it != end && !dynamic_cast<CStringItem*>(&*it)) ++it;
     73 
     74         msg.clear();
     75       }
     76       else
     77       {
     78         if (!line.empty() && line.back() == '\r') line.pop_back();
     79         msg.append(line).append("\\n");
     80       }
     81     }
     82 
     83     if (it != end)
     84       LIBSHIT_THROW(Libshit::DecodeError, "StscTxt: not enough strings");
     85   }
     86 
     87   static Flavor glob_flavor = Flavor::NOIRE;
     88   static Libshit::Option flavor_opt{
     89     GetFlavorOptions(), "stsc-flavor", 1, "FLAVOR",
     90 #define GEN_HELP(x,y) "\t\t" #x "\n"
     91     "Set STSC flavor:\n" NEPTOOLS_GEN_STSC_FLAVOR(GEN_HELP,),
     92 #undef GEN_HELP
     93     [](auto&, auto&& args)
     94     {
     95       if (false); // NOLINT
     96 #define GEN_IFS(x, y)                         \
     97       else if (strcmp(args.front(), #x) == 0) \
     98         glob_flavor = Flavor::x;
     99 
    100       NEPTOOLS_GEN_STSC_FLAVOR(GEN_IFS,)
    101 #undef GEN_IFS
    102       else throw Libshit::InvalidParam{"invalid argument"};
    103     }};
    104 
    105   static OpenFactory stsc_open{[](const Source& src) -> Libshit::SmartPtr<Dumpable>
    106   {
    107     if (src.GetSize() < sizeof(HeaderItem::Header)) return nullptr;
    108     char buf[4];
    109     src.PreadGen(0, buf);
    110     if (memcmp(buf, "STSC", 4) == 0)
    111       return Libshit::MakeSmart<File>(src, glob_flavor);
    112     else
    113       return nullptr;
    114   }};
    115 
    116 }
    117 
    118 #include "file.binding.hpp"