-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathYAML.cpp
More file actions
90 lines (68 loc) · 2.76 KB
/
YAML.cpp
File metadata and controls
90 lines (68 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#include "YAML.h"
#if RYML_VERSION_MAJOR > 0 || RYML_VERSION_MINOR >= 11
#include "c4/yml/error.def.hpp" // for ryml::err_basic_format etc
#endif
#include <csetjmp>
struct RapidYAMLContext
{
std::jmp_buf env;
Error* error = nullptr;
};
std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr file_name, Error* error)
{
RapidYAMLContext context;
context.error = error;
ryml::Callbacks callbacks;
#if RYML_VERSION_MAJOR > 0 || RYML_VERSION_MINOR >= 11
callbacks.set_user_data(static_cast<void*>(&context));
callbacks.set_error_basic([](ryml::csubstr msg, const ryml::ErrorDataBasic& errdata, void* user_data) {
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
std::string description;
auto callback = [&description](ryml::csubstr string) {
description.append(string.str, string.len);
};
ryml::err_basic_format(std::move(callback), msg, errdata);
Error::SetString(context->error, std::move(description));
std::longjmp(context->env, 1);
});
callbacks.set_error_parse([](ryml::csubstr msg, const ryml::ErrorDataParse& errdata, void* user_data) {
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
std::string description;
auto callback = [&description](ryml::csubstr string) {
description.append(string.str, string.len);
};
ryml::err_parse_format(std::move(callback), msg, errdata);
Error::SetString(context->error, std::move(description));
std::longjmp(context->env, 1);
});
callbacks.set_error_visit([](ryml::csubstr msg, const ryml::ErrorDataVisit& errdata, void* user_data) {
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
std::string description;
auto callback = [&description](ryml::csubstr string) {
description.append(string.str, string.len);
};
ryml::err_visit_format(std::move(callback), msg, errdata);
Error::SetString(context->error, std::move(description));
std::longjmp(context->env, 1);
});
#else
callbacks.m_user_data = static_cast<void*>(&context);
callbacks.m_error = [](const char* msg, size_t msg_len, ryml::Location location, void* user_data) {
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
Error::SetString(context->error, std::string(msg, msg_len));
std::longjmp(context->env, 1);
};
#endif
ryml::EventHandlerTree event_handler(callbacks);
ryml::Parser parser(&event_handler);
ryml::Tree tree;
// The only options RapidYAML provides for recovering from errors are
// throwing an exception or using setjmp/longjmp. Since we have exceptions
// disabled we have to use the latter option.
if (setjmp(context.env))
return std::nullopt;
ryml::parse_in_arena(&parser, file_name, yaml, &tree);
return tree;
}