blob: ad36e16ac4e9cda97a5f4ac3de730a07fd82af07 [file] [log] [blame]
#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 = reader.readVarUintAs<int>();
if (reader.didOverflow()) {
return false;
}
header.m_MinorVersion = reader.readVarUintAs<int>();
if (reader.didOverflow()) {
return false;
}
header.m_FileId = reader.readVarUintAs<int>();
if (reader.didOverflow()) {
return false;
}
std::vector<int> propertyKeys;
for (int propertyKey = reader.readVarUintAs<int>(); propertyKey != 0;
propertyKey = reader.readVarUintAs<int>())
{
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