#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2013 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_GRAPHICS_INTROSPECTION_MINIREADER_H #define NUCLEX_GRAPHICS_INTROSPECTION_MINIREADER_H #include "Nuclex/Graphics/Config.h" #include #include #include #include #include namespace Nuclex { namespace Graphics { namespace Introspection { // ------------------------------------------------------------------------------------------- // /// Helper class for reading structured data from a memory region /// /// This is simplified version of the BinaryReader in Nuclex.Storage.Native, reading /// binary data from a memory region (and ensuring no out of range accesses are taking /// place). I favored reimplementation here to avoid a dependency on mentioned library. /// class MiniReader { /// Initializes a new memory reader /// Compiled shader bytecode that will be read /// Total length of the compiled shader bytecode in bytes public: MiniReader(const std::uint8_t *bytecode, std::size_t length) : bytecode(bytecode), end(bytecode + length) {} /// Reads an unsigned 32 bit integer from the memory region /// 32 bit integer that will receive the value read public: void Read(std::uint32_t &value) { if((this->bytecode + sizeof(std::uint32_t)) > this->end) { throw std::runtime_error("Unexpected end of file"); } value = *reinterpret_cast(this->bytecode); this->bytecode += sizeof(std::uint32_t); } /// Reads an unsigned 16 bit integer from the memory region /// 16 bit integer that will receive the value read public: void Read(std::uint16_t &value) { if((this->bytecode + sizeof(std::uint16_t)) > this->end) { throw std::runtime_error("Unexpected end of file"); } value = *reinterpret_cast(this->bytecode); this->bytecode += sizeof(std::uint16_t); } /// Reads an unsigned 8 bit integer from the memory region /// 8 bit integer that will receive the value read public: void Read(std::uint8_t &value) { if((this->bytecode + sizeof(std::uint8_t)) > this->end) { throw std::runtime_error("Unexpected end of file"); } value = *this->bytecode; ++this->bytecode; } /// Reads a zero-terminated variable length string /// String that will receive the value read public: void Read(std::string &value) { value.clear(); for(;;) { if((this->bytecode) >= this->end) { return; } char nextCharacter = *reinterpret_cast(this->bytecode); if(nextCharacter == 0) { break; } value.push_back(nextCharacter); ++this->bytecode; } } /// Reads a block of binary data with a fixed length /// Vector that will receive the binary data /// Number of bytes that will be read public: void Read(std::vector &value, std::size_t length) { if((this->bytecode + length) > this->end) { throw std::runtime_error("Unexpected end of file"); } value.resize(length); std::copy_n(this->bytecode, length, &value[0]); this->bytecode += length; } /// Skips a number of bytes in the memory region /// Number of bytes that will be skipped public: void Skip(std::size_t byteCount) { if((this->bytecode + byteCount) > this->end) { throw std::runtime_error("Unexpected end of file"); } this->bytecode += byteCount; } /// Byte code the reader is reading from private: const std::uint8_t *bytecode; /// One past the last byte the reader is allowed to read private: const std::uint8_t *end; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Graphics::Introspection #endif // NUCLEX_GRAPHICS_INTROSPECTION_MINIREADER_H