diff --git a/components/esm4/loadcrea.cpp b/components/esm4/loadcrea.cpp index 3da8a0c114..a18f3b28a8 100644 --- a/components/esm4/loadcrea.cpp +++ b/components/esm4/loadcrea.cpp @@ -121,15 +121,8 @@ void ESM4::Creature::load(ESM4::Reader& reader) case ESM4::SUB_NAM1: reader.getZString(mBloodDecal); break; case ESM4::SUB_NIFZ: { - std::string str; - if (!reader.getZString(str)) + if (!reader.getZeroTerminatedStringArray(mNif)) throw std::runtime_error ("CREA NIFZ data read error"); - - std::stringstream ss(str); - std::string file; - while (std::getline(ss, file, '\0')) // split the strings - mNif.push_back(file); - break; } case ESM4::SUB_NIFT: @@ -149,15 +142,8 @@ void ESM4::Creature::load(ESM4::Reader& reader) } case ESM4::SUB_KFFZ: { - std::string str; - if (!reader.getZString(str)) + if (!reader.getZeroTerminatedStringArray(mKf)) throw std::runtime_error ("CREA KFFZ data read error"); - - std::stringstream ss(str); - std::string file; - while (std::getline(ss, file, '\0')) // split the strings - mKf.push_back(file); - break; } case ESM4::SUB_TPLT: reader.get(mBaseTemplate); break; // FO3 diff --git a/components/esm4/loadnpc.cpp b/components/esm4/loadnpc.cpp index 7c3597b029..78a65d2d62 100644 --- a/components/esm4/loadnpc.cpp +++ b/components/esm4/loadnpc.cpp @@ -144,19 +144,12 @@ void ESM4::Npc::load(ESM4::Reader& reader) case ESM4::SUB_MODB: reader.get(mBoundRadius); break; case ESM4::SUB_KFFZ: { - std::string str; - if (!reader.getZString(str)) - throw std::runtime_error ("NPC_ KFFZ data read error"); - // Seems to be only below 3, and only happens 3 times while loading TES4: // Forward_SheogorathWithCane.kf // TurnLeft_SheogorathWithCane.kf // TurnRight_SheogorathWithCane.kf - std::stringstream ss(str); - std::string file; - while (std::getline(ss, file, '\0')) // split the strings - mKf.push_back(file); - + if (!reader.getZeroTerminatedStringArray(mKf)) + throw std::runtime_error ("NPC_ KFFZ data read error"); break; } case ESM4::SUB_LNAM: reader.get(mHairLength); break; diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index cc13f5db97..0e661007d5 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -693,4 +693,30 @@ bool Reader::getStringImpl(std::string& str, std::size_t size, return false; // FIXME: throw instead? } +bool Reader::getZeroTerminatedStringArray(std::vector& values) +{ + const std::size_t size = mCtx.subRecordHeader.dataSize; + std::string input(size, '\0'); + mStream->read(input.data(), size); + + if (mStream->gcount() != static_cast(size)) + return false; + + std::string_view inputView(input.data(), input.size()); + std::string buffer; + while (true) + { + std::string_view value(inputView.data()); + const std::size_t next = inputView.find_first_not_of('\0', value.size()); + if (mEncoder != nullptr) + value = mEncoder->getUtf8(value, ToUTF8::BufferAllocationPolicy::UseGrowFactor, buffer); + values.emplace_back(value); + if (next == std::string_view::npos) + break; + inputView = inputView.substr(next); + } + + return true; +} + } diff --git a/components/esm4/reader.hpp b/components/esm4/reader.hpp index a3f6efea39..69a45d6ef2 100644 --- a/components/esm4/reader.hpp +++ b/components/esm4/reader.hpp @@ -293,6 +293,8 @@ namespace ESM4 { return getStringImpl(str, mCtx.subRecordHeader.dataSize, *mStream, mEncoder); } + bool getZeroTerminatedStringArray(std::vector& values); + void enterGroup(); void exitGroupCheck();