| #ifndef _RIVE_RUNTIME_HEADER_HPP_ |
| #define _RIVE_RUNTIME_HEADER_HPP_ |
| |
| #include "rive/core/binary_reader.hpp" |
| #include <unordered_map> |
| |
| namespace rive { |
| /// Rive file runtime header. The header is fonud at the beginning of every |
| /// Rive runtime file, and begins with a specific 4-byte format: "RIVE". |
| /// This is followed by the major and minor version of Rive used to create |
| /// the file. Finally the owner and file ids are at the end of header; these |
| /// unsigned integers may be zero. |
| class RuntimeHeader { |
| private: |
| static constexpr char fingerprint[] = "RIVE"; |
| |
| int m_MajorVersion; |
| int m_MinorVersion; |
| int m_FileId; |
| std::unordered_map<int, int> m_PropertyToFieldIndex; |
| |
| public: |
| /// @returns the file's major version |
| int majorVersion() const { return m_MajorVersion; } |
| /// @returns the file's minor version |
| int minorVersion() const { return m_MinorVersion; } |
| /// @returns the file's id; may be zero |
| int fileId() const { return m_FileId; } |
| |
| int propertyFieldId(int propertyKey) const { |
| auto itr = m_PropertyToFieldIndex.find(propertyKey); |
| if (itr == m_PropertyToFieldIndex.end()) { |
| return -1; |
| } |
| |
| return itr->second; |
| } |
| |
| /// Reads the header from a binary buffer/ |
| /// @param reader the binary reader attached to the buffer |
| /// @param header a pointer to the header where the data will be stored. |
| /// @returns true if the header is successfully read |
| static bool read(BinaryReader& reader, RuntimeHeader& header) { |
| for (int i = 0; i < 4; i++) { |
| auto b = reader.readByte(); |
| if (fingerprint[i] != b) { |
| return false; |
| } |
| } |
| |
| header.m_MajorVersion = (int)reader.readVarUint64(); |
| if (reader.didOverflow()) { |
| return false; |
| } |
| header.m_MinorVersion = (int)reader.readVarUint64(); |
| if (reader.didOverflow()) { |
| return false; |
| } |
| |
| header.m_FileId = (int)reader.readVarUint64(); |
| |
| if (reader.didOverflow()) { |
| return false; |
| } |
| |
| std::vector<int> propertyKeys; |
| for (int propertyKey = (int)reader.readVarUint64(); |
| propertyKey != 0; |
| propertyKey = (int)reader.readVarUint64()) |
| { |
| propertyKeys.push_back(propertyKey); |
| if (reader.didOverflow()) { |
| return false; |
| } |
| } |
| |
| int currentInt = 0; |
| int currentBit = 8; |
| for (auto propertyKey : propertyKeys) { |
| if (currentBit == 8) { |
| currentInt = reader.readUint32(); |
| currentBit = 0; |
| } |
| int fieldIndex = (currentInt >> currentBit) & 3; |
| header.m_PropertyToFieldIndex[propertyKey] = fieldIndex; |
| currentBit += 2; |
| if (reader.didOverflow()) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| }; |
| } // namespace rive |
| #endif |