From 87ada56edd9d5d5b0a9e6a8dcfd06eb09b161746 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 20:58:01 +0000 Subject: [PATCH] Various fixes for niftest --- components/nif/niffile.cpp | 12 +++++------ components/nif/nifstream.cpp | 2 +- components/nif/nifstream.hpp | 41 ++++++++++++++++++++---------------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 3e226b35e..864a388e8 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -212,7 +212,7 @@ void NIFFile::parse(Files::IStreamPtr stream) userVer = nif.getUInt(); // Number of records - unsigned int recNum = nif.getUInt(); + const std::size_t recNum = nif.getUInt(); records.resize(recNum); // Bethesda stream header @@ -251,7 +251,7 @@ void NIFFile::parse(Files::IStreamPtr stream) std::vector recSizes; // Currently unused nif.getUInts(recSizes, recNum); } - unsigned int stringNum = nif.getUInt(); + const std::size_t stringNum = nif.getUInt(); nif.getUInt(); // Max string length if (stringNum) nif.getSizedStrings(strings, stringNum); @@ -264,7 +264,7 @@ void NIFFile::parse(Files::IStreamPtr stream) } const bool hasRecordSeparators = ver >= NIFStream::generateVersion(10,0,0,0) && ver < NIFStream::generateVersion(10,2,0,0); - for (unsigned int i = 0; i < recNum; i++) + for (std::size_t i = 0; i < recNum; i++) { Record *r = nullptr; @@ -308,14 +308,14 @@ void NIFFile::parse(Files::IStreamPtr stream) r->read(&nif); } - unsigned int rootNum = nif.getUInt(); + const std::size_t rootNum = nif.getUInt(); roots.resize(rootNum); //Determine which records are roots - for (unsigned int i = 0; i < rootNum; i++) + for (std::size_t i = 0; i < rootNum; i++) { int idx = nif.getInt(); - if (idx >= 0 && idx < int(records.size())) + if (idx >= 0 && static_cast(idx) < records.size()) { roots[i] = records[idx]; } diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index 07c9c917c..6129a1739 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -7,7 +7,7 @@ namespace Nif osg::Quat NIFStream::getQuaternion() { float f[4]; - readLittleEndianBufferOfType<4, float>(inp, (float*)&f); + readLittleEndianBufferOfType<4, float>(inp, f); osg::Quat quat; quat.w() = f[0]; quat.x() = f[1]; diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 4d221b867..b6bf01ce5 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -22,31 +24,32 @@ namespace Nif class NIFFile; -/* - readLittleEndianBufferOfType: This template should only be used with arithmetic types -*/ -template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) +template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) { + static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); + if (pIStream->bad()) + throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name()) + ") buffer of " + + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) - for (uint32_t i = 0; i < numInstances; i++) + for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } -/* - readLittleEndianDynamicBufferOfType: This template should only be used with arithmetic types -*/ -template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, uint32_t numInstances) +template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, std::size_t numInstances) { + static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); + if (pIStream->bad()) + throw std::runtime_error("Failed to read little endian dynamic buffer of " + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) - for (uint32_t i = 0; i < numInstances; i++) + for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } template type inline readLittleEndianType(Files::IStreamPtr &pIStream) { type val; - readLittleEndianBufferOfType<1, type>(pIStream, (type*)&val); + readLittleEndianBufferOfType<1, type>(pIStream, &val); return val; } @@ -96,21 +99,21 @@ public: osg::Vec2f getVector2() { osg::Vec2f vec; - readLittleEndianBufferOfType<2,float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<2,float>(inp, vec._v); return vec; } osg::Vec3f getVector3() { osg::Vec3f vec; - readLittleEndianBufferOfType<3, float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<3, float>(inp, vec._v); return vec; } osg::Vec4f getVector4() { osg::Vec4f vec; - readLittleEndianBufferOfType<4, float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<4, float>(inp, vec._v); return vec; } @@ -142,11 +145,11 @@ public: ///Read in a string of the given length std::string getSizedString(size_t length) { - std::vector str(length + 1, 0); - + std::string str(length, '\0'); inp->read(str.data(), length); - - return str.data(); + if (inp->bad()) + throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars"); + return str; } ///Read in a string of the length specified in the file std::string getSizedString() @@ -167,6 +170,8 @@ public: { std::string result; std::getline(*inp, result); + if (inp->bad()) + throw std::runtime_error("Failed to read version string"); return result; }