mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-25 18:03:08 +00:00
Use fail function to verify nif stream state
If there is a failure to read the file like incomplete read, bad returns false, but fail returns true. This is important for reading number of items more than the file actually has.
This commit is contained in:
parent
b49b048f72
commit
1ae0aadfed
4 changed files with 37 additions and 18 deletions
|
|
@ -1,5 +1,13 @@
|
|||
#include "stream.hpp"
|
||||
|
||||
#include <osg/Vec2f>
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Vec4f>
|
||||
|
||||
#include <format>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace Bgsm
|
||||
{
|
||||
template <>
|
||||
|
|
@ -30,8 +38,9 @@ namespace Bgsm
|
|||
throw std::runtime_error("Requested string length is too large: " + std::to_string(length));
|
||||
str = std::string(length, '\0');
|
||||
mStream->read(str.data(), length);
|
||||
if (mStream->bad())
|
||||
throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars");
|
||||
if (mStream->fail())
|
||||
throw std::runtime_error(std::format(
|
||||
"Failed to read sized string of {} chars: {}", length, std::generic_category().message(errno)));
|
||||
std::size_t end = str.find('\0');
|
||||
if (end != std::string::npos)
|
||||
str.erase(end);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <istream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
|
@ -23,9 +23,9 @@ namespace Bgsm
|
|||
{
|
||||
static_assert(std::is_arithmetic_v<T>, "Buffer element type is not arithmetic");
|
||||
pIStream->read(reinterpret_cast<char*>(dest), numInstances * sizeof(T));
|
||||
if (pIStream->bad())
|
||||
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") buffer of "
|
||||
+ std::to_string(numInstances) + " instances");
|
||||
if (pIStream->fail())
|
||||
throw std::runtime_error(std::format("Failed to read typed ({}) buffer of {} instances: {}",
|
||||
typeid(T).name(), numInstances, std::generic_category().message(errno)));
|
||||
if constexpr (Misc::IS_BIG_ENDIAN)
|
||||
for (std::size_t i = 0; i < numInstances; i++)
|
||||
Misc::swapEndiannessInplace(dest[i]);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#include "nifstream.hpp"
|
||||
|
||||
#include <cerrno>
|
||||
#include <format>
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
||||
#include <components/toutf8/toutf8.hpp>
|
||||
|
||||
|
|
@ -55,8 +59,9 @@ namespace Nif
|
|||
{
|
||||
std::string str(length, '\0');
|
||||
mStream->read(str.data(), length);
|
||||
if (mStream->bad())
|
||||
throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars");
|
||||
if (mStream->fail())
|
||||
throw std::runtime_error(std::format(
|
||||
"Failed to read sized string of {} chars: {}", length, std::generic_category().message(errno)));
|
||||
size_t end = str.find('\0');
|
||||
if (end != std::string::npos)
|
||||
str.erase(end);
|
||||
|
|
@ -76,8 +81,9 @@ namespace Nif
|
|||
{
|
||||
std::string result;
|
||||
std::getline(*mStream, result);
|
||||
if (mStream->bad())
|
||||
throw std::runtime_error("Failed to read version string");
|
||||
if (mStream->fail())
|
||||
throw std::runtime_error(
|
||||
std::format("Failed to read version string: {}", std::generic_category().message(errno)));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -86,8 +92,9 @@ namespace Nif
|
|||
size_t size = get<uint32_t>();
|
||||
std::string str(size, '\0');
|
||||
mStream->read(str.data(), size);
|
||||
if (mStream->bad())
|
||||
throw std::runtime_error("Failed to read string palette of " + std::to_string(size) + " chars");
|
||||
if (mStream->fail())
|
||||
throw std::runtime_error(std::format(
|
||||
"Failed to read string palette of {} chars: {}", size, std::generic_category().message(errno)));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,13 @@
|
|||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <format>
|
||||
#include <istream>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -40,9 +43,9 @@ namespace Nif
|
|||
std::is_arithmetic_v<T> || std::is_same_v<T, Misc::float16_t>, "Buffer element type is not arithmetic");
|
||||
static_assert(!std::is_same_v<T, bool>, "Buffer element type is boolean");
|
||||
pIStream->read((char*)dest, numInstances * sizeof(T));
|
||||
if (pIStream->bad())
|
||||
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") buffer of "
|
||||
+ std::to_string(numInstances) + " instances");
|
||||
if (pIStream->fail())
|
||||
throw std::runtime_error(std::format("Failed to read typed ({}) dynamic buffer of {} instances: {}",
|
||||
typeid(T).name(), numInstances, std::generic_category().message(errno)));
|
||||
if constexpr (Misc::IS_BIG_ENDIAN)
|
||||
for (std::size_t i = 0; i < numInstances; i++)
|
||||
Misc::swapEndiannessInplace(dest[i]);
|
||||
|
|
@ -61,9 +64,9 @@ namespace Nif
|
|||
std::is_arithmetic_v<T> || std::is_same_v<T, Misc::float16_t>, "Buffer element type is not arithmetic");
|
||||
static_assert(!std::is_same_v<T, bool>, "Buffer element type is boolean");
|
||||
pIStream->read((char*)dest, numInstances * sizeof(T));
|
||||
if (pIStream->bad())
|
||||
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") dynamic buffer of "
|
||||
+ std::to_string(numInstances) + " instances");
|
||||
if (pIStream->fail())
|
||||
throw std::runtime_error(std::format("Failed to read typed ({}) dynamic buffer of {} instances: {}",
|
||||
typeid(T).name(), numInstances, std::generic_category().message(errno)));
|
||||
if constexpr (Misc::IS_BIG_ENDIAN)
|
||||
for (std::size_t i = 0; i < numInstances; i++)
|
||||
Misc::swapEndiannessInplace(dest[i]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue