209 lines
5.3 KiB
C++
209 lines
5.3 KiB
C++
#pragma once
|
|
|
|
#include <frostbite2D/types/type_alias.h>
|
|
#include <frostbite2D/resource/pvf_archive.h>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cstring>
|
|
|
|
namespace frostbite2D {
|
|
|
|
/**
|
|
* @brief 脚本指令操作码枚举
|
|
*/
|
|
enum class ScriptOpcode : uint8 {
|
|
Integer = 2, ///< 整数值
|
|
Float = 4, ///< 浮点值
|
|
StringRef5 = 5, ///< 二进制字符串引用(类型5)
|
|
StringRef6 = 6, ///< 二进制字符串引用(类型6)
|
|
StringRef7 = 7, ///< 二进制字符串引用(类型7)
|
|
StringRef8 = 8, ///< 二进制字符串引用(类型8)
|
|
ExtendedString9 = 9, ///< 扩展字符串(带额外字节)
|
|
ExtendedString10 = 10, ///< 扩展字符串
|
|
};
|
|
|
|
/**
|
|
* @brief 脚本值类型
|
|
*/
|
|
enum class ScriptValueType {
|
|
Empty, ///< 空值
|
|
Integer, ///< 整数值
|
|
Float, ///< 浮点值
|
|
String, ///< 字符串值
|
|
};
|
|
|
|
/**
|
|
* @brief 脚本解析结果值
|
|
*/
|
|
struct ScriptValue {
|
|
ScriptValueType type = ScriptValueType::Empty; ///< 值类型
|
|
int32 intValue = 0; ///< 整数值(type == Integer 时有效)
|
|
double floatValue = 0.0; ///< 浮点值(type == Float 时有效)
|
|
std::string stringValue; ///< 字符串值(type == String 时有效)
|
|
|
|
/**
|
|
* @brief 判断是否为空值
|
|
*/
|
|
bool isEmpty() const { return type == ScriptValueType::Empty; }
|
|
|
|
/**
|
|
* @brief 转换为字符串表示
|
|
*/
|
|
std::string toString() const;
|
|
};
|
|
|
|
/**
|
|
* @brief 脚本二进制数据解析器
|
|
*
|
|
* 用于解析 PVF 存档中的脚本二进制数据。
|
|
* 每条指令为 5 字节:1 字节操作码 + 4 字节数据。
|
|
* 支持与 PvfArchive 交互获取字符串资源。
|
|
*
|
|
* @example
|
|
* auto& archive = PvfArchive::get();
|
|
* if (auto rawData = archive.getFileRawData("script/example.bin")) {
|
|
* ScriptParser parser(*rawData, "script/example.bin");
|
|
*
|
|
* // 迭代解析
|
|
* while (!parser.isEnd()) {
|
|
* if (auto value = parser.next()) {
|
|
* // 处理 value
|
|
* }
|
|
* }
|
|
*
|
|
* // 或者一次性解析所有
|
|
* auto allValues = parser.parseAll();
|
|
* }
|
|
*/
|
|
class ScriptParser {
|
|
public:
|
|
/**
|
|
* @brief 从 RawData 构造
|
|
* @param data 原始数据
|
|
* @param filePath 文件路径(用于提取文件类型)
|
|
*/
|
|
ScriptParser(const RawData& data, const std::string& filePath);
|
|
|
|
/**
|
|
* @brief 从字节数组构造
|
|
* @param data 字节数组
|
|
* @param filePath 文件路径(用于提取文件类型)
|
|
*/
|
|
ScriptParser(const std::vector<uint8>& data, const std::string& filePath);
|
|
|
|
/**
|
|
* @brief 从指针和大小构造
|
|
* @param data 数据指针
|
|
* @param size 数据大小
|
|
* @param filePath 文件路径(用于提取文件类型)
|
|
*/
|
|
ScriptParser(const char* data, size_t size, const std::string& filePath);
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 迭代器风格 API
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 获取下一个值
|
|
* @return 解析的值,失败或结束返回 std::nullopt
|
|
*/
|
|
std::optional<ScriptValue> next();
|
|
|
|
/**
|
|
* @brief 回退一个指令
|
|
*/
|
|
void back();
|
|
|
|
/**
|
|
* @brief 检查是否已到达数据末尾
|
|
* @return 到达末尾返回 true
|
|
*/
|
|
bool isEnd() const;
|
|
|
|
/**
|
|
* @brief 重置解析位置到开头
|
|
*/
|
|
void reset();
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 批量解析
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 解析所有值
|
|
* @return 所有解析值的列表
|
|
*/
|
|
std::vector<ScriptValue> parseAll();
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 状态查询
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief 获取当前解析位置
|
|
* @return 当前位置(字节偏移)
|
|
*/
|
|
size_t position() const;
|
|
|
|
/**
|
|
* @brief 获取数据总大小
|
|
* @return 数据大小(字节)
|
|
*/
|
|
size_t size() const;
|
|
|
|
/**
|
|
* @brief 获取文件路径
|
|
* @return 文件路径
|
|
*/
|
|
const std::string& filePath() const;
|
|
|
|
/**
|
|
* @brief 获取文件类型(从路径提取)
|
|
* @return 文件类型
|
|
*/
|
|
const std::string& fileType() const;
|
|
|
|
/**
|
|
* @brief 检查解析器是否有效(有数据)
|
|
* @return 有效返回 true
|
|
*/
|
|
bool isValid() const;
|
|
|
|
private:
|
|
/**
|
|
* @brief 从文件路径提取文件类型
|
|
* @param filePath 文件路径
|
|
* @return 文件类型
|
|
*/
|
|
std::string extractFileType(const std::string& filePath) const;
|
|
|
|
/**
|
|
* @brief 读取 1 字节
|
|
* @param offset 偏移位置
|
|
* @return 字节值
|
|
*/
|
|
uint8 readByte(size_t offset) const;
|
|
|
|
/**
|
|
* @brief 读取 4 字节整数
|
|
* @param offset 偏移位置
|
|
* @return 整数值
|
|
*/
|
|
int32 readInt32(size_t offset) const;
|
|
|
|
/**
|
|
* @brief 解析单个值
|
|
* @param offset 偏移位置
|
|
* @return 解析的值
|
|
*/
|
|
std::optional<ScriptValue> parseValueAt(size_t offset) const;
|
|
|
|
std::vector<char> data_; ///< 数据副本
|
|
size_t position_ = 2; ///< 当前解析位置(从第 2 字节开始)
|
|
std::string filePath_; ///< 文件路径
|
|
std::string fileType_; ///< 文件类型
|
|
};
|
|
|
|
} // namespace frostbite2D
|