Entropic 2.11.1
Local-first agentic inference engine
Loading...
Searching...
No Matches
yaml_util.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
9#include "yaml_util.h"
10
12#include <cstdlib>
13#include <fstream>
14#include <sstream>
15
16static auto s_log = entropic::log::get("config");
17
18namespace entropic::config {
19
27std::string to_string(c4::csubstr s)
28{
29 return std::string(s.str, s.len);
30}
31
39std::string read_file(const std::filesystem::path& path)
40{
41 std::ifstream ifs(path);
42 if (!ifs.is_open()) {
43 s_log->error("Cannot open file: {}", path.string());
44 return "";
45 }
46 std::ostringstream ss;
47 ss << ifs.rdbuf();
48 auto content = ss.str();
49 s_log->info("Read file: {}, {} bytes", path.string(),
50 content.size());
51 return content;
52}
53
61std::filesystem::path expand_home(const std::filesystem::path& p)
62{
63 auto str = p.string();
64 const char* home = std::getenv("HOME");
65 bool needs_expansion = !str.empty() && str[0] == '~' && home != nullptr;
66
67 if (!needs_expansion) {
68 return p;
69 }
70
71 return (str.size() == 1)
72 ? std::filesystem::path(home)
73 : std::filesystem::path(home) / str.substr(2);
74}
75
85bool extract(ryml::ConstNodeRef node, c4::csubstr key, std::string& out)
86{
87 if (!node.is_map() || !node.has_child(key)) {
88 return false;
89 }
90 auto child = node[key];
91 if (!child.has_val() || child.val_is_null()) {
92 return false;
93 }
94 out = to_string(child.val());
95 return true;
96}
97
107bool extract(ryml::ConstNodeRef node, c4::csubstr key, int& out)
108{
109 if (!node.is_map() || !node.has_child(key)) {
110 return false;
111 }
112 auto child = node[key];
113 if (!child.has_val() || child.val_is_null()) {
114 return false;
115 }
116 auto val = to_string(child.val());
117 out = std::stoi(val);
118 return true;
119}
120
130bool extract(ryml::ConstNodeRef node, c4::csubstr key, float& out)
131{
132 if (!node.is_map() || !node.has_child(key)) {
133 return false;
134 }
135 auto child = node[key];
136 if (!child.has_val() || child.val_is_null()) {
137 return false;
138 }
139 auto val = to_string(child.val());
140 out = std::stof(val);
141 return true;
142}
143
153bool extract(ryml::ConstNodeRef node, c4::csubstr key, double& out)
154{
155 if (!node.is_map() || !node.has_child(key)) {
156 return false;
157 }
158 auto child = node[key];
159 if (!child.has_val() || child.val_is_null()) {
160 return false;
161 }
162 auto val = to_string(child.val());
163 out = std::stod(val);
164 return true;
165}
166
176bool extract(ryml::ConstNodeRef node, c4::csubstr key, bool& out)
177{
178 if (!node.is_map() || !node.has_child(key)) {
179 return false;
180 }
181 auto child = node[key];
182 if (!child.has_val() || child.val_is_null()) {
183 return false;
184 }
185 auto val = to_string(child.val());
186 out = (val == "true" || val == "True" || val == "TRUE"
187 || val == "yes" || val == "Yes" || val == "YES"
188 || val == "on" || val == "On" || val == "ON"
189 || val == "1");
190 return true;
191}
192
202bool extract_path(ryml::ConstNodeRef node, c4::csubstr key,
203 std::filesystem::path& out)
204{
205 std::string val;
206 if (!extract(node, key, val)) {
207 return false;
208 }
209 out = expand_home(std::filesystem::path(val));
210 return true;
211}
212
224 ryml::ConstNodeRef node, c4::csubstr key,
225 std::optional<std::filesystem::path>& out, bool& disabled)
226{
227 if (!node.is_map() || !node.has_child(key)) {
228 return false;
229 }
230 auto child = node[key];
231 bool is_null = !child.has_val() || child.val_is_null();
232 auto val = is_null ? std::string{} : to_string(child.val());
233 bool is_false = (val == "false" || val == "False" || val == "FALSE");
234
235 disabled = is_false;
236 out = (is_null || is_false)
237 ? std::nullopt
238 : std::optional{expand_home(std::filesystem::path(val))};
239 return true;
240}
241
258 ryml::ConstNodeRef node, c4::csubstr key, std::optional<std::string>& out)
259{
260 bool matched = false;
261 if (node.is_map() && node.has_child(key)) {
262 auto child = node[key];
263 if (child.is_map() && child.has_child("content")) {
264 auto content = child["content"];
265 if (content.has_val()) {
266 out = to_string(content.val());
267 matched = true;
268 }
269 }
270 }
271 return matched;
272}
273
283bool extract_string_list(ryml::ConstNodeRef node, c4::csubstr key,
284 std::vector<std::string>& out)
285{
286 if (!node.is_map() || !node.has_child(key)) {
287 return false;
288 }
289 auto child = node[key];
290 if (!child.is_seq()) {
291 return false;
292 }
293 out.clear();
294 for (auto item : child) {
295 out.push_back(to_string(item.val()));
296 }
297 return true;
298}
299
309bool extract_string_list_opt(ryml::ConstNodeRef node, c4::csubstr key,
310 std::optional<std::vector<std::string>>& out)
311{
312 if (!node.is_map() || !node.has_child(key)) {
313 return false;
314 }
315 auto child = node[key];
316 if (!child.is_seq()) {
317 bool is_null = !child.has_val() || child.val_is_null();
318 out = is_null ? std::nullopt : out;
319 return is_null;
320 }
321 std::vector<std::string> vec;
322 for (auto item : child) {
323 vec.push_back(to_string(item.val()));
324 }
325 out = std::move(vec);
326 return true;
327}
328
338bool extract_string_map(ryml::ConstNodeRef node, c4::csubstr key,
339 std::unordered_map<std::string, std::string>& out)
340{
341 if (!node.is_map() || !node.has_child(key)) {
342 return false;
343 }
344 auto child = node[key];
345 if (!child.is_map()) {
346 return false;
347 }
348 out.clear();
349 for (auto item : child) {
350 out[to_string(item.key())] = to_string(item.val());
351 }
352 return true;
353}
354
365 ryml::ConstNodeRef node, c4::csubstr key,
366 std::unordered_map<std::string, std::vector<std::string>>& out)
367{
368 if (!node.is_map() || !node.has_child(key)) {
369 return false;
370 }
371 auto child = node[key];
372 if (!child.is_map()) {
373 return false;
374 }
375 out.clear();
376 for (auto item : child) {
377 std::vector<std::string> vec;
378 if (item.is_seq()) {
379 for (auto elem : item) {
380 vec.push_back(to_string(elem.val()));
381 }
382 }
383 out[to_string(item.key())] = std::move(vec);
384 }
385 return true;
386}
387
388} // namespace entropic::config
spdlog initialization and logger access.
ENTROPIC_EXPORT std::shared_ptr< spdlog::logger > get(const std::string &name)
Get or create a named logger.
Definition logging.cpp:211
std::filesystem::path expand_home(const std::filesystem::path &p)
Expand ~ to home directory in a path.
Definition yaml_util.cpp:61
bool extract_string_list_map(ryml::ConstNodeRef node, c4::csubstr key, std::unordered_map< std::string, std::vector< std::string > > &out)
Extract a map of string to list of strings from a YAML mapping.
bool extract_inline_content(ryml::ConstNodeRef node, c4::csubstr key, std::optional< std::string > &out)
Extract inline text from an object-form value (gh#141).
std::string read_file(const std::filesystem::path &path)
Read a file into a string.
Definition yaml_util.cpp:39
bool extract_path(ryml::ConstNodeRef node, c4::csubstr key, std::filesystem::path &out)
Extract a filesystem path with ~ expansion.
bool extract_string_list(ryml::ConstNodeRef node, c4::csubstr key, std::vector< std::string > &out)
Extract a vector of strings from a YAML sequence node.
bool extract_string_map(ryml::ConstNodeRef node, c4::csubstr key, std::unordered_map< std::string, std::string > &out)
Extract a map of string to string from a YAML mapping node.
bool extract_string_list_opt(ryml::ConstNodeRef node, c4::csubstr key, std::optional< std::vector< std::string > > &out)
Extract an optional vector of strings.
bool extract_tri_state_path(ryml::ConstNodeRef node, c4::csubstr key, std::optional< std::filesystem::path > &out, bool &disabled)
Extract a tri-state path (null = default, false = disabled, string = path).
std::string to_string(c4::csubstr s)
Convert ryml csubstr to std::string.
Definition yaml_util.cpp:27
bool extract(ryml::ConstNodeRef node, c4::csubstr key, std::string &out)
Extract a string value from a YAML node.
Definition yaml_util.cpp:85
ryml extraction helpers for config parsing.