#pragma once
#include <cstdint>

namespace font {
	/**
	 * @brief 读取无符号8位整数
	 * @param p 数据指针
	 * @return 8位无符号整数
	 */
	static uint8_t read_u8(const uint8_t* p) { return p[0]; }

	/**
	 * @brief 读取有符号8位整数
	 * @param p 数据指针
	 * @return 8位有符号整数
	 */
	static int8_t read_i8(const uint8_t* p) { return static_cast<int8_t>(p[0]); }

	/**
	 * @brief 读取无符号短整型（2字节，大端序）
	 * @param p 数据指针
	 * @return 16位无符号整数
	 */
	static uint16_t read_u16(const uint8_t* p) { return static_cast<uint16_t>(p[0] << 8 | p[1]); }

	/**
	 * @brief 读取有符号短整型（2字节，大端序）
	 * @param p 数据指针
	 * @return 16位有符号整数
	 */
	static int16_t read_i16(const uint8_t* p) { return static_cast<int16_t>(p[0] << 8 | p[1]); }

	/**
	 * @brief 读取无符号整型（4字节，大端序）
	 * @param p 数据指针
	 * @return 32位无符号整数
	 */
	static uint32_t read_u32(const uint8_t* p) {
		return static_cast<uint32_t>(p[0]) << 24 | static_cast<uint32_t>(p[1]) << 16 | static_cast<uint32_t>(p[2]) << 8
		       | static_cast<uint32_t>(p[3]);
	}

	/**
	 * @brief 检查标签是否匹配
	 * @param tag_data 标签数据
	 * @param tag 标签字符串
	 * @return 是否匹配
	 */
	static bool check_tag(const uint8_t* tag_data, const char* tag) {
		return tag_data[0] == tag[0] && tag_data[1] == tag[1] && tag_data[2] == tag[2] && tag_data[3] == tag[3];
	}

	/**
	 * @brief 在字体数据中查找特定表的偏移量
	 * @param data 字体数据
	 * @param font_start 字体起始偏移
	 * @param tag 表标签
	 * @return 表偏移量，不存在则返回0
	 */
	static uint32_t find_table_offset(const uint8_t* data, uint32_t font_start, const char* tag) {
		const auto     num_tables = read_u16(data + font_start + 4);
		const uint32_t table_dir  = font_start + 12;

		for (int i = 0; i < num_tables; ++i) {
			const uint32_t loc = table_dir + 16 * i;
			if (check_tag(data + loc, tag)) { return read_u32(data + loc + 8); }
		}

		return 0; // 表不存在
	}
}
