270 lines
5.9 KiB
C++
270 lines
5.9 KiB
C++
#pragma once
|
|
|
|
#include <frostbite2D/types/type_alias.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
|
|
namespace frostbite2D {
|
|
|
|
/**
|
|
* @brief 二进制文件读取器
|
|
*
|
|
* 将整个二进制文件加载到内存中,提供便捷的读取接口。
|
|
* 支持各种基本类型的读取、定位操作和 CRC 解码。
|
|
*
|
|
* @example
|
|
* BinaryReader reader("data.bin");
|
|
* if (reader.isOpen()) {
|
|
* int32 value = reader.read<int32>();
|
|
* std::string str = reader.readString(10);
|
|
* }
|
|
*/
|
|
class BinaryReader {
|
|
public:
|
|
/**
|
|
* @brief 默认构造函数
|
|
*/
|
|
BinaryReader() = default;
|
|
|
|
/**
|
|
* @brief 从文件构造
|
|
* @param filePath 文件路径
|
|
*/
|
|
explicit BinaryReader(const std::string& filePath);
|
|
|
|
/**
|
|
* @brief 从内存数据构造
|
|
* @param data 数据指针
|
|
* @param size 数据大小
|
|
*/
|
|
BinaryReader(const char* data, size_t size);
|
|
|
|
/**
|
|
* @brief 析构函数
|
|
*/
|
|
~BinaryReader() = default;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 文件操作
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 打开文件
|
|
* @param filePath 文件路径
|
|
* @return 打开成功返回 true
|
|
*/
|
|
bool open(const std::string& filePath);
|
|
|
|
/**
|
|
* @brief 从内存加载数据
|
|
* @param data 数据指针
|
|
* @param size 数据大小
|
|
*/
|
|
void loadFromMemory(const char* data, size_t size);
|
|
|
|
/**
|
|
* @brief 关闭并清空数据
|
|
*/
|
|
void close();
|
|
|
|
/**
|
|
* @brief 检查文件是否成功打开
|
|
* @return 已打开返回 true
|
|
*/
|
|
bool isOpen() const;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 位置操作
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 获取当前读取位置
|
|
* @return 当前位置(字节偏移)
|
|
*/
|
|
size_t tell() const;
|
|
|
|
/**
|
|
* @brief 设置读取位置
|
|
* @param pos 目标位置(字节偏移)
|
|
*/
|
|
void seek(size_t pos);
|
|
|
|
/**
|
|
* @brief 跳过指定字节数
|
|
* @param count 要跳过的字节数
|
|
*/
|
|
void skip(size_t count);
|
|
|
|
/**
|
|
* @brief 检查是否已到达文件末尾
|
|
* @return 到达末尾返回 true
|
|
*/
|
|
bool eof() const;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 信息获取
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 获取数据总大小
|
|
* @return 数据大小(字节)
|
|
*/
|
|
size_t size() const;
|
|
|
|
/**
|
|
* @brief 获取剩余可读取的字节数
|
|
* @return 剩余字节数
|
|
*/
|
|
size_t remaining() const;
|
|
|
|
/**
|
|
* @brief 获取上一次读取的字节数
|
|
* @return 上次读取的字节数
|
|
*/
|
|
size_t lastReadCount() const;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 原始数据读取
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 读取原始字节数据
|
|
* @param buffer 输出缓冲区
|
|
* @param size 要读取的字节数
|
|
* @return 实际读取的字节数
|
|
*/
|
|
size_t read(char* buffer, size_t size);
|
|
|
|
/**
|
|
* @brief 读取原始字节数据到 vector
|
|
* @param size 要读取的字节数
|
|
* @return 读取的数据
|
|
*/
|
|
std::vector<uint8> readBytes(size_t size);
|
|
|
|
/**
|
|
* @brief 获取数据指针(不移动读取位置)
|
|
* @return 当前位置的数据指针
|
|
*/
|
|
const char* data() const;
|
|
|
|
/**
|
|
* @brief 获取当前位置的数据指针(不移动读取位置)
|
|
* @return 当前位置的数据指针
|
|
*/
|
|
const char* currentData() const;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 类型化读取(模板方法)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 读取指定类型的值
|
|
* @tparam T 要读取的类型
|
|
* @return 读取的值
|
|
*/
|
|
template <typename T>
|
|
T read() {
|
|
T value;
|
|
read(reinterpret_cast<char*>(&value), sizeof(T));
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* @brief 读取 int8
|
|
* @return 读取的值
|
|
*/
|
|
int8 readInt8();
|
|
|
|
/**
|
|
* @brief 读取 int16
|
|
* @return 读取的值
|
|
*/
|
|
int16 readInt16();
|
|
|
|
/**
|
|
* @brief 读取 int32
|
|
* @return 读取的值
|
|
*/
|
|
int32 readInt32();
|
|
|
|
/**
|
|
* @brief 读取 int64
|
|
* @return 读取的值
|
|
*/
|
|
int64 readInt64();
|
|
|
|
/**
|
|
* @brief 读取 uint8
|
|
* @return 读取的值
|
|
*/
|
|
uint8 readUInt8();
|
|
|
|
/**
|
|
* @brief 读取 uint16
|
|
* @return 读取的值
|
|
*/
|
|
uint16 readUInt16();
|
|
|
|
/**
|
|
* @brief 读取 uint32
|
|
* @return 读取的值
|
|
*/
|
|
uint32 readUInt32();
|
|
|
|
/**
|
|
* @brief 读取 uint64
|
|
* @return 读取的值
|
|
*/
|
|
uint64 readUInt64();
|
|
|
|
/**
|
|
* @brief 读取 float
|
|
* @return 读取的值
|
|
*/
|
|
float readFloat();
|
|
|
|
/**
|
|
* @brief 读取 double
|
|
* @return 读取的值
|
|
*/
|
|
double readDouble();
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 字符串读取
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 读取指定长度的字符串
|
|
* @param length 字符串长度(字节)
|
|
* @return 读取的字符串
|
|
*/
|
|
std::string readString(size_t length);
|
|
|
|
/**
|
|
* @brief 读取以 null 结尾的字符串
|
|
* @return 读取的字符串
|
|
*/
|
|
std::string readNullTerminatedString();
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRC 解码
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief CRC 解码
|
|
* @param length 要解码的数据长度(字节)
|
|
* @param crc32 CRC32 值
|
|
*/
|
|
void crcDecode(size_t length, uint32 crc32);
|
|
|
|
private:
|
|
std::vector<char> data_; ///< 存储的数据
|
|
size_t position_ = 0; ///< 当前读取位置
|
|
size_t lastReadCount_ = 0; ///< 上一次读取的字节数
|
|
};
|
|
|
|
} // namespace frostbite2D
|