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"