Feature: Embed language resources, disk files act as optional patches
This commit is contained in:
@@ -50,47 +50,71 @@ public:
|
||||
char line[4096];
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
// 去除行尾换行符
|
||||
size_t len = strlen(line);
|
||||
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
|
||||
line[--len] = '\0';
|
||||
ParseLine(line, currentSection);
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
continue;
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 跳过注释
|
||||
if (line[0] == ';' || line[0] == '#')
|
||||
continue;
|
||||
// 从内存加载 INI 数据,返回是否成功
|
||||
// 用于加载嵌入的资源数据
|
||||
bool LoadFromMemory(const char* data, size_t size)
|
||||
{
|
||||
Clear();
|
||||
|
||||
// 检测 section 头: [SectionName]
|
||||
// 真正的 section 头:']' 后面没有 '='(否则是 key=value)
|
||||
if (line[0] == '[') {
|
||||
char* end = strchr(line, ']');
|
||||
if (end) {
|
||||
char* eqAfter = strchr(end + 1, '=');
|
||||
if (!eqAfter) {
|
||||
// 纯 section 头,如 [Strings]
|
||||
*end = '\0';
|
||||
currentSection = line + 1;
|
||||
continue;
|
||||
}
|
||||
// ']' 后有 '=',如 [使用FRP]=[Using FRP],当作 key=value 处理
|
||||
}
|
||||
if (!data || size == 0)
|
||||
return false;
|
||||
|
||||
std::string currentSection;
|
||||
const char* p = data;
|
||||
const char* end = data + size;
|
||||
|
||||
while (p < end) {
|
||||
// 找到行尾
|
||||
const char* lineEnd = p;
|
||||
while (lineEnd < end && *lineEnd != '\n' && *lineEnd != '\r')
|
||||
lineEnd++;
|
||||
|
||||
// 复制行内容
|
||||
size_t lineLen = lineEnd - p;
|
||||
if (lineLen > 0 && lineLen < 4096) {
|
||||
char line[4096];
|
||||
memcpy(line, p, lineLen);
|
||||
line[lineLen] = '\0';
|
||||
ParseLine(line, currentSection);
|
||||
}
|
||||
|
||||
// 不在任何 section 内则跳过
|
||||
if (currentSection.empty())
|
||||
continue;
|
||||
// 跳过换行符
|
||||
p = lineEnd;
|
||||
while (p < end && (*p == '\n' || *p == '\r'))
|
||||
p++;
|
||||
}
|
||||
|
||||
// 解析 key=value(只按第一个 '=' 分割,不 trim)
|
||||
// key 和 value 均做反转义(\n \r \t \\ \")
|
||||
char* eq = strchr(line, '=');
|
||||
if (eq && eq != line) {
|
||||
*eq = '\0';
|
||||
std::string key = Unescape(std::string(line));
|
||||
std::string value = Unescape(std::string(eq + 1));
|
||||
m_sections[currentSection][key] = value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 追加加载(不清除现有数据,用于覆盖)
|
||||
bool LoadFileAppend(const char* filePath)
|
||||
{
|
||||
if (!filePath || !filePath[0])
|
||||
return false;
|
||||
|
||||
FILE* f = nullptr;
|
||||
#ifdef _MSC_VER
|
||||
if (fopen_s(&f, filePath, "r") != 0 || !f)
|
||||
return false;
|
||||
#else
|
||||
f = fopen(filePath, "r");
|
||||
if (!f)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
std::string currentSection;
|
||||
char line[4096];
|
||||
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
ParseLine(line, currentSection);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
@@ -138,6 +162,52 @@ public:
|
||||
private:
|
||||
TSections m_sections;
|
||||
|
||||
// 解析单行 INI 内容
|
||||
void ParseLine(char* line, std::string& currentSection)
|
||||
{
|
||||
// 去除行尾换行符
|
||||
size_t len = strlen(line);
|
||||
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
|
||||
line[--len] = '\0';
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
// 跳过注释
|
||||
if (line[0] == ';' || line[0] == '#')
|
||||
return;
|
||||
|
||||
// 检测 section 头: [SectionName]
|
||||
// 真正的 section 头:']' 后面没有 '='(否则是 key=value)
|
||||
if (line[0] == '[') {
|
||||
char* end = strchr(line, ']');
|
||||
if (end) {
|
||||
char* eqAfter = strchr(end + 1, '=');
|
||||
if (!eqAfter) {
|
||||
// 纯 section 头,如 [Strings]
|
||||
*end = '\0';
|
||||
currentSection = line + 1;
|
||||
return;
|
||||
}
|
||||
// ']' 后有 '=',如 [使用FRP]=[Using FRP],当作 key=value 处理
|
||||
}
|
||||
}
|
||||
|
||||
// 不在任何 section 内则跳过
|
||||
if (currentSection.empty())
|
||||
return;
|
||||
|
||||
// 解析 key=value(只按第一个 '=' 分割,不 trim)
|
||||
// key 和 value 均做反转义(\n \r \t \\ \")
|
||||
char* eq = strchr(line, '=');
|
||||
if (eq && eq != line) {
|
||||
*eq = '\0';
|
||||
std::string key = Unescape(std::string(line));
|
||||
std::string value = Unescape(std::string(eq + 1));
|
||||
m_sections[currentSection][key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// 反转义:将字面量 \n \r \t \\ \" 转为对应的控制字符
|
||||
static std::string Unescape(const std::string& s)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user