rapidyaml 0.14.0
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
common.cpp
Go to the documentation of this file.
1#include "c4/yml/common.hpp"
2#include "c4/yml/error.hpp"
4
5#ifndef RYML_NO_DEFAULT_CALLBACKS
6# include <stdlib.h>
7# include <stdio.h>
8#endif // RYML_NO_DEFAULT_CALLBACKS
9#ifdef _RYML_EXCEPTIONS
10# include <stdexcept>
11#endif
12
13
14namespace c4 {
15namespace yml {
16
17C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
18C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702/*unreachable code*/) // on the call to the unreachable macro
19
20namespace {
21Callbacks s_default_callbacks;
22
23#ifndef RYML_NO_DEFAULT_CALLBACKS
24
25C4_NO_INLINE void dump2stderr(csubstr s)
26{
27 // using fwrite() is more portable than using fprintf("%.*s") which
28 // is not available in some embedded platforms
29 if(s.len)
30 fwrite(s.str, 1, s.len, stderr); // NOLINT
31}
32C4_NO_INLINE void endmsg()
33{
34 fputc('\n', stderr); // NOLINT
35 fflush(stderr); // NOLINT
36}
37
38[[noreturn]] C4_NO_INLINE void error_basic_impl(csubstr msg, ErrorDataBasic const& errdata, void * /*user_data*/)
39{
40 err_basic_format(dump2stderr, msg, errdata);
41 endmsg();
42 #ifdef _RYML_WITH_EXCEPTIONS
43 throw ExceptionBasic(msg, errdata);
44 #else
45 abort(); // LCOV_EXCL_LINE
46 #endif
47}
48
49[[noreturn]] C4_NO_INLINE void error_parse_impl(csubstr msg, ErrorDataParse const& errdata, void * /*user_data*/)
50{
51 err_parse_format(dump2stderr, msg, errdata);
52 endmsg();
53 #ifdef _RYML_WITH_EXCEPTIONS
54 throw ExceptionParse(msg, errdata);
55 #else
56 abort(); // LCOV_EXCL_LINE
57 #endif
58}
59
60[[noreturn]] C4_NO_INLINE void error_visit_impl(csubstr msg, ErrorDataVisit const& errdata, void * /*user_data*/)
61{
62 err_visit_format(dump2stderr, msg, errdata);
63 endmsg();
64 #ifdef _RYML_WITH_EXCEPTIONS
65 throw ExceptionVisit(msg, errdata);
66 #else
67 abort(); // LCOV_EXCL_LINE
68 #endif
69}
70
71void* allocate_impl(size_t length, void * /*hint*/, void * /*user_data*/)
72{
73 void *mem = ::malloc(length);
74 if(mem == nullptr)
75 error_basic_impl("could not allocate memory", ErrorDataBasic{RYML_LOC_HERE()}, nullptr); // LCOV_EXCL_LINE
76 return mem;
77}
78
79void free_impl(void *mem, size_t /*length*/, void * /*user_data*/)
80{
81 ::free(mem);
82}
83
84#endif // RYML_NO_DEFAULT_CALLBACKS
85
86} // anon namespace
87
88
90{
91 s_default_callbacks = c;
92}
93
95{
96 return s_default_callbacks;
97}
98
100{
102}
103
104
106 :
107 m_user_data(nullptr),
108 #ifndef RYML_NO_DEFAULT_CALLBACKS
109 m_allocate(allocate_impl),
110 m_free(free_impl),
111 m_error_basic(error_basic_impl),
112 m_error_parse(error_parse_impl),
113 m_error_visit(error_visit_impl)
114 #else
115 m_allocate(nullptr),
116 m_free(nullptr),
117 m_error_basic(nullptr),
118 m_error_parse(nullptr),
119 m_error_visit(nullptr)
120 #endif
121{
122}
123
124Callbacks::Callbacks(void *user_data, pfn_allocate alloc_, pfn_free free_, pfn_error_basic error_basic_)
125 :
126 m_user_data(user_data),
128 m_allocate(alloc_ ? alloc_ : allocate_impl),
129 m_free(free_ ? free_ : free_impl),
130 m_error_basic(error_basic_ ? error_basic_ : error_basic_impl),
131 m_error_parse(error_parse_impl),
132 m_error_visit(error_visit_impl)
133 #else
134 m_allocate(alloc_),
135 m_free(free_),
136 m_error_basic(error_basic_),
137 m_error_parse(nullptr),
138 m_error_visit(nullptr)
139 #endif
140{
141}
142
143
145{
146 m_user_data = user_data;
147 return *this;
148}
149
151{
152 m_allocate = allocate;
153 #ifndef RYML_NO_DEFAULT_CALLBACKS
154 m_allocate = m_allocate ? m_allocate : allocate_impl;
155 #endif
156 return *this;
157}
158
160{
161 m_free = free;
162 #ifndef RYML_NO_DEFAULT_CALLBACKS
163 m_free = m_free ? m_free : free_impl;
164 #endif
165 return *this;
166}
167
169{
170 m_error_basic = error_basic;
171 #ifndef RYML_NO_DEFAULT_CALLBACKS
172 m_error_basic = m_error_basic ? m_error_basic : error_basic_impl;
173 #endif
174 return *this;
175}
176
178{
179 m_error_parse = error_parse;
180 #ifndef RYML_NO_DEFAULT_CALLBACKS
181 m_error_parse = m_error_parse ? m_error_parse : error_parse_impl;
182 #endif
183 return *this;
184}
185
187{
188 m_error_visit = error_visit;
189 #ifndef RYML_NO_DEFAULT_CALLBACKS
190 m_error_visit = m_error_visit ? m_error_visit : error_visit_impl;
191 #endif
192 return *this;
193}
194
195
196C4_NORETURN C4_NO_INLINE void err_basic(ErrorDataBasic const& errdata, const char* msg)
197{
198 err_basic(get_callbacks(), errdata, msg);
199 C4_UNREACHABLE_AFTER_ERR();
200}
201C4_NORETURN C4_NO_INLINE void err_basic(Callbacks const& callbacks, ErrorDataBasic const& errdata, const char* msg_)
202{
203 csubstr msg = to_csubstr(msg_);
204 callbacks.m_error_basic(msg, errdata, callbacks.m_user_data);
205 abort(); // the call above should not return, so force it here in case it does // LCOV_EXCL_LINE
206 C4_UNREACHABLE_AFTER_ERR();
207}
208
209
210C4_NORETURN C4_NO_INLINE void err_parse(ErrorDataParse const& errdata, const char *msg)
211{
212 err_parse(get_callbacks(), errdata, msg);
213 C4_UNREACHABLE_AFTER_ERR();
214}
215C4_NORETURN C4_NO_INLINE void err_parse(Callbacks const& callbacks, ErrorDataParse const& errdata, const char *msg_)
216{
217 csubstr msg = to_csubstr(msg_);
218 if(callbacks.m_error_parse)
219 callbacks.m_error_parse(msg, errdata, callbacks.m_user_data);
220 // fall to basic error if there is no parse handler set
221 else if(callbacks.m_error_basic)
222 callbacks.m_error_basic(msg, errdata.ymlloc, callbacks.m_user_data);
223 abort(); // the call above should not return, so force it here in case it does // LCOV_EXCL_LINE
224 C4_UNREACHABLE_AFTER_ERR();
225}
226
227
228C4_NORETURN C4_NO_INLINE void err_visit(ErrorDataVisit const& errdata, const char *msg)
229{
230 err_visit(get_callbacks(), errdata, msg);
231 C4_UNREACHABLE_AFTER_ERR();
232}
233C4_NORETURN C4_NO_INLINE void err_visit(Callbacks const& callbacks, ErrorDataVisit const& errdata, const char *msg_)
234{
235 csubstr msg = to_csubstr(msg_);
236 if(callbacks.m_error_visit)
237 callbacks.m_error_visit(msg, errdata, callbacks.m_user_data);
238 // fall to basic error if there is no visit handler set
239 else if(callbacks.m_error_basic)
240 callbacks.m_error_basic(msg, errdata.cpploc, callbacks.m_user_data);
241 abort(); // the call above should not return, so force it here in case it does // LCOV_EXCL_LINE
242 C4_UNREACHABLE_AFTER_ERR();
243}
244
245
246
247#ifdef _RYML_WITH_EXCEPTIONS
248ExceptionBasic::ExceptionBasic(csubstr msg_, ErrorDataBasic const& errdata_) noexcept
249 : errdata_basic(errdata_)
250 , msg()
251{
252 msg[0] = '\0';
253 if(msg_.len)
254 {
255 if(msg_.len >= sizeof(msg))
256 {
257 static_assert(sizeof(msg) > 6u, "message buffer too small");
258 msg_.len = sizeof(msg) - 6u;
259 msg[msg_.len ] = '[';
260 msg[msg_.len + 1u] = '.';
261 msg[msg_.len + 2u] = '.';
262 msg[msg_.len + 3u] = '.';
263 msg[msg_.len + 4u] = ']';
264 msg[msg_.len + 5u] = '\0';
265 }
266 memcpy(msg, msg_.str, msg_.len);
267 }
268}
269ExceptionParse::ExceptionParse(csubstr msg_, ErrorDataParse const& errdata_) noexcept
270 : ExceptionBasic(msg_, {errdata_.ymlloc})
271 , errdata_parse(errdata_)
272{
273}
274ExceptionVisit::ExceptionVisit(csubstr msg_, ErrorDataVisit const& errdata_) noexcept
275 : ExceptionBasic(msg_, {errdata_.cpploc})
276 , errdata_visit(errdata_)
277{
278}
279#endif // _RYML_WITH_EXCEPTIONS
280
281
282namespace detail {
283RYML_EXPORT csubstr _get_text_region(csubstr text, size_t pos, size_t num_lines_before, size_t num_lines_after)
284{
285 if(pos > text.len)
286 return text.last(0);
287 size_t before = text.first(pos).last_of('\n');
288 size_t before_count = 0;
289 while((before != npos) && (++before_count <= num_lines_before))
290 {
291 if(before == 0)
292 break;
293 before = text.first(--before).last_of('\n');
294 }
295 if(before < text.len || before == npos)
296 ++before;
297 size_t after = text.first_of('\n', pos);
298 size_t after_count = 0;
299 while((after != npos) && (++after_count <= num_lines_after))
300 {
301 ++after;
302 if(after >= text.len)
303 break;
304 after = text.first_of('\n', after);
305 }
306 return before <= after ? text.range(before, after) : text.first(0);
307}
308} // namespace detail
309
310C4_SUPPRESS_WARNING_MSVC_POP
311C4_SUPPRESS_WARNING_GCC_CLANG_POP
312
313} // namespace yml
314} // namespace c4
Common utilities and infrastructure used by ryml.
#define RYML_NO_DEFAULT_CALLBACKS
(Undefined by default) Define this macro to disable ryml's default implementation of the callback fun...
Definition common.hpp:188
Definitions of error utilities used by ryml.
Error utilities used by ryml.
#define RYML_EXPORT
Definition export.hpp:18
void *(*)(size_t len, void *hint, void *user_data) pfn_allocate
the type of the function used to allocate memory; ryml will only allocate memory through this callbac...
Definition common.hpp:495
void(*)(csubstr msg, ErrorDataVisit const &errdata, void *user_data) pfn_error_visit
the type of the function used to report visit errors.
Definition common.hpp:535
void reset_callbacks()
set the global callbacks back to their defaults.
Definition common.cpp:99
void(*)(void *mem, size_t size, void *user_data) pfn_free
the type of the function used to free memory; ryml will only free memory through this callback.
Definition common.hpp:500
void set_callbacks(Callbacks const &c)
set the global callbacks for the library; after a call to this function, these callbacks will be used...
Definition common.cpp:89
void(*)(csubstr msg, ErrorDataParse const &errdata, void *user_data) pfn_error_parse
the type of the function used to report parse errors.
Definition common.hpp:524
Callbacks const & get_callbacks()
get the global callbacks
Definition common.cpp:94
void(*)(csubstr msg, ErrorDataBasic const &errdata, void *user_data) pfn_error_basic
the type of the function used to report basic errors.
Definition common.hpp:513
void err_visit(ErrorDataVisit const &errdata, const char *msg)
trigger a visit error to its respective handler, with a non-formatted error message.
Definition common.cpp:228
void err_visit_format(DumpFn &&dumpfn, csubstr msg, ErrorDataVisit const &errdata)
Given an error message and associated visit error data, format it fully as a visit error message.
void err_basic(ErrorDataBasic const &errdata, const char *msg)
trigger a basic error to its respective handler, with a non-formatted error message.
Definition common.cpp:196
void err_basic_format(DumpFn &&dumpfn, csubstr msg, ErrorDataBasic const &errdata)
Given an error message and associated basic error data, format it fully as a basic error message.
void err_parse_format(DumpFn &&dumpfn, csubstr msg, ErrorDataParse const &errdata)
Given an error message and associated parse error data, format it fully as a parse error message.
void err_parse(ErrorDataParse const &errdata, const char *msg)
trigger a parse error to its respective handler, with a non-formatted error message.
Definition common.cpp:210
csubstr to_csubstr(const char(&s)[N]) noexcept
Definition substr.hpp:2381
basic_substring< const char > csubstr
an immutable string view
Definition substr.hpp:2357
a CRTP base providing read-only methods for ConstNodeRef and NodeRef
Definition common.cpp:282
csubstr _get_text_region(csubstr text, size_t pos, size_t num_lines_before, size_t num_lines_after)
Definition common.cpp:283
@ npos
a null string position
Definition common.hpp:263
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
Definition common.cpp:14
basic_substring range(size_t first, size_t last=npos) const noexcept
return [first,last[.
Definition substr.hpp:520
size_t last_of(const C c, size_t start=npos) const
Definition substr.hpp:947
size_t len
the length of the substring
Definition substr.hpp:218
basic_substring last(size_t num) const noexcept
return the last num elements: [len-num,len[
Definition substr.hpp:537
size_t first_of(const C c, size_t start=0) const
Definition substr.hpp:935
basic_substring first(size_t num) const noexcept
return the first num elements: [0,num[
Definition substr.hpp:530
C * str
a restricted pointer to the first character of the substring
Definition substr.hpp:216
A c-style callbacks class to customize behavior on errors or allocation.
Definition common.hpp:546
pfn_error_basic m_error_basic
a pointer to a basic error handler function
Definition common.hpp:550
pfn_error_parse m_error_parse
a pointer to a parse error handler function
Definition common.hpp:551
Callbacks & set_error_visit(pfn_error_visit error_visit=nullptr)
Set or reset the error_visit callback.
Definition common.cpp:186
Callbacks & set_free(pfn_free free=nullptr)
Set or reset the free callback.
Definition common.cpp:159
void * m_user_data
data to be forwarded in every call to a callback
Definition common.hpp:547
pfn_allocate m_allocate
a pointer to an allocate handler function
Definition common.hpp:548
Callbacks() noexcept
Construct an object with the default callbacks.
Definition common.cpp:105
Callbacks & set_error_parse(pfn_error_parse error_parse=nullptr)
Set or reset the error_parse callback.
Definition common.cpp:177
Callbacks & set_allocate(pfn_allocate allocate=nullptr)
Set or reset the allocate callback.
Definition common.cpp:150
Callbacks & set_error_basic(pfn_error_basic error_basic=nullptr)
Set or reset the error_basic callback.
Definition common.cpp:168
pfn_error_visit m_error_visit
a pointer to a visit error handler function
Definition common.hpp:552
pfn_free m_free
a pointer to a free handler function
Definition common.hpp:549
Callbacks & set_user_data(void *user_data)
Set the user data.
Definition common.cpp:144
Data for a basic error.
Definition common.hpp:320
Data for a parse error.
Definition common.hpp:329
Location ymlloc
location in the YAML source buffer where the error was detected.
Definition common.hpp:331
Data for a visit error.
Definition common.hpp:339
Location cpploc
location in the C++ source file where the error was detected.
Definition common.hpp:340
Exception thrown by the default basic error implementation.
Definition error.hpp:478
ExceptionBasic(csubstr msg, ErrorDataBasic const &errdata_) noexcept
Exception thrown by the default parse error implementation.
Definition error.hpp:497
ExceptionParse(csubstr msg, ErrorDataParse const &errdata_) noexcept
Exception thrown by the default visit error implementation.
Definition error.hpp:514
ExceptionVisit(csubstr msg, ErrorDataVisit const &errdata_) noexcept