Fix reading array of zero terminated strings

NIFZ and KFFZ subrecords store multiple strings separated by \0 character.
make_linux_ci_do_zoomies
elsid 2 years ago
parent ae812701ec
commit 6f00641c8a
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

@ -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

@ -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;

@ -693,4 +693,30 @@ bool Reader::getStringImpl(std::string& str, std::size_t size,
return false; // FIXME: throw instead?
}
bool Reader::getZeroTerminatedStringArray(std::vector<std::string>& values)
{
const std::size_t size = mCtx.subRecordHeader.dataSize;
std::string input(size, '\0');
mStream->read(input.data(), size);
if (mStream->gcount() != static_cast<std::streamsize>(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;
}
}

@ -293,6 +293,8 @@ namespace ESM4 {
return getStringImpl(str, mCtx.subRecordHeader.dataSize, *mStream, mEncoder);
}
bool getZeroTerminatedStringArray(std::vector<std::string>& values);
void enterGroup();
void exitGroupCheck();

Loading…
Cancel
Save