- Implemented the OpenAI-compatible AI provider plugin, including configuration, chat, and chat_stream functionalities. - Added support for SSE streaming and tool calls. - Integrated Boost.JSON for JSON handling. - Created CMake configuration for the plugin. - Added error handling and logging throughout the plugin.
76 lines
2.9 KiB
C++
76 lines
2.9 KiB
C++
/*
|
||
* @file toml_parse.h
|
||
* @brief Lightweight single-header TOML parser (subset: flat key-value pairs).
|
||
* 轻量级单头文件 TOML 解析器(子集:扁平键值对)。
|
||
* Copyright (c) 2026 dstalk contributors. GPLv3.
|
||
*/
|
||
|
||
#pragma once
|
||
// 共享 TOML 解析器 —— 由 ConfigStore(核心)和 config 插件共同使用 / Shared TOML parser — used by both ConfigStore (core) and config plugin.
|
||
// W12.2: Extracted from config_store.cpp:23-61 and config_plugin.cpp:28-66
|
||
// to eliminate the 74-line code duplication (W11.2 audit Finding 1).
|
||
// Does NOT support: inline tables, arrays, multi-line strings, escape sequences.
|
||
// 不支持:内联表、数组、多行字符串、转义序列。
|
||
|
||
#include <string>
|
||
|
||
namespace dstalk {
|
||
namespace toml {
|
||
|
||
/// 解析 TOML 字符串,对每个键值对调用 on_kv(full_key, value) / Parse a TOML string, calling on_kv(full_key, value) for each key-value pair.
|
||
/// 支持 [section] 标题、key = "value" 键值对、# 注释、空行 / Supports [section] headers, key = "value" pairs, # comments, blank lines.
|
||
template<typename F>
|
||
inline void parse(const std::string& content, F&& on_kv)
|
||
{
|
||
std::string current_section;
|
||
size_t pos = 0;
|
||
|
||
while (pos < content.size()) {
|
||
// 去除左侧空白 / Trim left whitespace
|
||
while (pos < content.size() && (content[pos] == ' ' || content[pos] == '\t'))
|
||
pos++;
|
||
if (pos >= content.size()) break;
|
||
|
||
// 提取下一行 / Extract next line
|
||
size_t nl = content.find('\n', pos);
|
||
std::string line = (nl != std::string::npos)
|
||
? content.substr(pos, nl - pos) : content.substr(pos);
|
||
pos = (nl != std::string::npos) ? nl + 1 : content.size();
|
||
|
||
// 去除右侧空白(包括 \r) / Trim right whitespace (including \r)
|
||
while (!line.empty() && (line.back() == '\r' || line.back() == ' '))
|
||
line.pop_back();
|
||
|
||
// 跳过空行和注释 / Skip empty lines and comments
|
||
if (line.empty() || line[0] == '#') continue;
|
||
|
||
// 节标题: [section_name] / Section header: [section_name]
|
||
if (line[0] == '[' && line.back() == ']') {
|
||
current_section = line.substr(1, line.size() - 2);
|
||
continue;
|
||
}
|
||
|
||
// 键 = 值 / Key = value
|
||
size_t eq = line.find('=');
|
||
if (eq == std::string::npos) continue;
|
||
|
||
std::string key = line.substr(0, eq);
|
||
while (!key.empty() && key.back() == ' ') key.pop_back();
|
||
if (key.empty()) continue;
|
||
|
||
std::string val = line.substr(eq + 1);
|
||
while (!val.empty() && (val.front() == ' ' || val.front() == '\t'))
|
||
val.erase(0, 1);
|
||
if (val.size() >= 2 && val.front() == '"' && val.back() == '"')
|
||
val = val.substr(1, val.size() - 2);
|
||
|
||
std::string full_key = current_section.empty()
|
||
? key : current_section + "." + key;
|
||
|
||
on_kv(full_key, val);
|
||
}
|
||
}
|
||
|
||
} // namespace toml
|
||
} // namespace dstalk
|