rapidyaml 0.14.0
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
error.def.hpp
Go to the documentation of this file.
1#ifndef _C4_YML_ERROR_DEF_HPP_
2#define _C4_YML_ERROR_DEF_HPP_
3
4/** @file error.def.hpp Definitions of error utilities used by ryml. */
5
6#ifndef _C4_YML_ERROR_HPP_
7#include <c4/yml/error.hpp>
8#endif
9
10#include <cassert>
11
12// NOLINTBEGIN(bugprone-use-after-move,hicpp-invalid-access-moved)
13
14namespace c4 {
15namespace yml {
16
17template<class DumpFn>
18C4_NO_INLINE size_t location_format(DumpFn &&dumpfn, Location const& loc)
19{
20 if(!loc)
21 return 0;
22 char buf_[32];
23 substr buf(buf_);
24 size_t count = 0;
25 if(!loc.name.empty())
26 {
27 std::forward<DumpFn>(dumpfn)(loc.name);
28 std::forward<DumpFn>(dumpfn)(":");
29 count += loc.name.len + 1;
30 }
31 if(loc.line != npos)
32 {
33 csubstr val = detail::_to_chars_limited(buf, loc.line);
34 if(loc.name.empty())
35 {
36 std::forward<DumpFn>(dumpfn)("line=");
37 std::forward<DumpFn>(dumpfn)(val);
38 if(loc.col == npos)
39 {
40 std::forward<DumpFn>(dumpfn)(":");
41 ++count;
42 }
43 count += val.len + 5;
44 }
45 else
46 {
47 std::forward<DumpFn>(dumpfn)(val);
48 std::forward<DumpFn>(dumpfn)(":");
49 count += val.len + 1;
50 }
51 }
52 if(loc.col != npos)
53 {
54 csubstr val = detail::_to_chars_limited(buf, loc.col);
55 if(loc.line != npos || !loc.name.empty())
56 {
57 std::forward<DumpFn>(dumpfn)(" ");
58 ++count;
59 }
60 std::forward<DumpFn>(dumpfn)("col=");
61 std::forward<DumpFn>(dumpfn)(val);
62 count += val.len + 4;
63 if(loc.offset == npos)
64 {
65 std::forward<DumpFn>(dumpfn)(":");
66 ++count;
67 }
68 }
69 if(loc.offset != npos)
70 {
71 csubstr val = detail::_to_chars_limited(buf, loc.offset);
72 if(loc.line != npos || loc.col != npos || !loc.name.empty())
73 {
74 std::forward<DumpFn>(dumpfn)(" ");
75 ++count;
76 }
77 std::forward<DumpFn>(dumpfn)("(");
78 std::forward<DumpFn>(dumpfn)(val);
79 std::forward<DumpFn>(dumpfn)("B):");
80 count += val.len + 5;
81 }
82 return count;
83}
84
85template<class DumpFn>
86C4_NO_INLINE void location_format_with_context(DumpFn &&dumpfn,
87 Location const &location,
88 csubstr source_buffer,
89 csubstr call,
90 size_t num_lines_before,
91 size_t num_lines_after,
92 size_t first_col_highlight,
93 size_t last_col_highlight,
94 size_t maxlen)
95{
96 if(!location)
97 return;
98 char buf_[32];
99 substr buf(buf_);
100 auto pr = [&](csubstr s){ std::forward<DumpFn>(dumpfn)(s); };
101 auto prn = [&](csubstr s, size_t num_times){
102 for(size_t i = 0; i < num_times; ++i)
103 std::forward<DumpFn>(dumpfn)(s);
104 };
105 csubstr line = detail::_get_text_region(source_buffer, location.offset, 0, 0);
106 size_t target_col = location.col != npos ? location.col : (last_col_highlight > first_col_highlight ? first_col_highlight : npos);
107 size_t first_col_to_show = 0;
108 if(target_col != npos && target_col > maxlen)
109 first_col_to_show = target_col - maxlen + 1;
110 auto print_line_maybe_truncated = [&](csubstr contents){
111 if(contents.len <= maxlen)
112 {
113 if(first_col_to_show == 0)
114 {
115 pr(contents);
116 }
117 else if(first_col_to_show < contents.len)
118 {
119 csubstr show = contents.sub(first_col_to_show);
120 pr("[...]");
121 pr(show);
122 if(maxlen > show.len)
123 prn(" ", maxlen - show.len + 5);
124 pr(" (showing columns ");
125 pr(detail::_to_chars_limited(buf, first_col_to_show));
126 pr("-");
127 pr(detail::_to_chars_limited(buf, contents.len));
128 pr("/");
129 pr(detail::_to_chars_limited(buf, contents.len));
130 pr(")");
131 }
132 else
133 {
134 pr("[...]");
135 prn(" ", maxlen + 5);
136 pr(" (not showing, columns=");
137 pr(detail::_to_chars_limited(buf, contents.len));
138 pr(")");
139 }
140 }
141 else
142 {
143 if(first_col_to_show == 0)
144 {
145 csubstr show = contents.first(maxlen);
146 pr(show);
147 pr("[...] (showing columns 0-");
148 pr(detail::_to_chars_limited(buf, show.len));
149 pr("/");
150 pr(detail::_to_chars_limited(buf, contents.len));
151 pr(")");
152 }
153 else if(first_col_to_show < contents.len && first_col_to_show + maxlen <= contents.len)
154 {
155 csubstr show = contents.sub(first_col_to_show, maxlen);
156 pr("[...]");
157 pr(show);
158 pr("[...] (showing columns ");
159 pr(detail::_to_chars_limited(buf, first_col_to_show));
160 pr("-");
161 pr(detail::_to_chars_limited(buf, first_col_to_show + maxlen));
162 pr("/");
163 pr(detail::_to_chars_limited(buf, contents.len));
164 pr(")");
165 }
166 else if(first_col_to_show < contents.len)
167 {
168 csubstr show = contents.sub(first_col_to_show);
169 pr("[...]");
170 pr(show);
171 if(maxlen > show.len)
172 prn(" ", maxlen - show.len + 5);
173 pr(" (showing columns ");
174 pr(detail::_to_chars_limited(buf, first_col_to_show));
175 pr("-");
176 pr(detail::_to_chars_limited(buf, contents.len));
177 pr("/");
178 pr(detail::_to_chars_limited(buf, contents.len));
179 pr(")");
180 }
181 else
182 {
183 pr("[...]");
184 prn(" ", maxlen + 5);
185 pr(" (not showing, columns=");
186 pr(detail::_to_chars_limited(buf, contents.len));
187 pr(")");
188 }
189 }
190 };
191 // print the location, and compute how many cols it took
192 size_t locsize = location_format(pr, location);
193 // print line
194 if(locsize)
195 {
196 pr(" ");
197 //++locsize;
198 }
199 auto print_call = [&](csubstr after){
200 pr(call);
201 pr(":");
202 if(after.len)
203 pr(after);
204 };
205 size_t jump;
206 if(call.empty())
207 {
208 print_line_maybe_truncated(line);
209 pr("\n");
210 jump = locsize + location.col - first_col_to_show;
211 }
212 else
213 {
214 print_call("\n");
215 print_call("\n");
216 print_call(" ");
217 pr(" ");
218 print_line_maybe_truncated(line);
219 pr("\n");
220 jump = call.len + 2;
221 }
222 // when skipping to the first col, add 5 to adjust for the [...]
223 // leading the line as shown
224 const size_t first_col_jump = first_col_to_show == 0 ? 0 : 5;
225 // print a cursor pointing at the column on the previous printed line
226 auto print_cursor = [&](size_t nocall_jump){
227 if(location.offset == npos)
228 return;
229 if(call.empty())
230 {
231 if(nocall_jump != npos)
232 {
233 prn(" ", nocall_jump + first_col_jump);
234 pr("|\n");
235 prn(" ", nocall_jump + first_col_jump);
236 pr("(here)\n");
237 }
238 }
239 else if(location.col != npos)
240 {
241 print_call(" ");
242 pr(" ");
243 prn(" ", location.col - first_col_to_show + first_col_jump);
244 pr("|\n");
245 print_call(" ");
246 pr(" ");
247 prn(" ", location.col - first_col_to_show + first_col_jump);
248 pr("(here)\n");
249 }
250 };
251 // maybe highlighted zone
252 size_t firstcol = first_col_highlight < line.len ? first_col_highlight : line.len;
253 size_t lastcol = last_col_highlight < line.len ? last_col_highlight : line.len;
254 firstcol = firstcol < maxlen ? firstcol : maxlen;
255 lastcol = lastcol < maxlen ? lastcol : maxlen;
256 if(firstcol < lastcol)
257 {
258 if(!call.empty())
259 {
260 print_call(" ");
261 pr(" ");
262 }
263 else
264 {
265 for(size_t i = 0; i < locsize + firstcol; ++i)
266 pr(" ");
267 }
268 for(size_t i = locsize + firstcol; i < locsize + lastcol; ++i)
269 pr("~");
270 pr(" (cols ");
271 pr(detail::_to_chars_limited(buf, firstcol));
272 pr("-");
273 pr(detail::_to_chars_limited(buf, lastcol));
274 pr("/");
275 pr(detail::_to_chars_limited(buf, line.len));
276 pr(")\n");
277 }
278 if(location.col != npos)
279 {
280 print_cursor(jump);
281 }
282 // maybe print the region
283 if(num_lines_before || num_lines_after)
284 {
285 if(!call.empty())
286 {
287 print_call("\n");
288 print_call(" ");
289 pr("see region:\n");
290 print_call("\n");
291 }
292 else
293 {
294 if(location)
295 {
296 location_format(pr, location);
297 pr(" ");
298 }
299 pr("see region:\n");
300 }
301 csubstr region = detail::_get_text_region(source_buffer, location.offset, num_lines_before, num_lines_after);
302 for(csubstr contents : region.split('\n'))
303 {
304 if(!call.empty())
305 {
306 print_call(" ");
307 }
308 print_line_maybe_truncated(contents);
309 pr("\n");
310 }
311 assert(location.col == npos || location.col >= first_col_to_show);
312 print_cursor(location.col - first_col_to_show);
313 }
314}
315
316
317template<class DumpFn>
318C4_NO_INLINE void err_basic_format(DumpFn &&dumpfn, csubstr msg, ErrorDataBasic const& errdata)
319{
320 if(errdata.location)
321 {
322 location_format(dumpfn, errdata.location);
323 std::forward<DumpFn>(dumpfn)(" ");
324 }
325 std::forward<DumpFn>(dumpfn)("ERROR: [basic] ");
326 std::forward<DumpFn>(dumpfn)(msg);
327}
328
329
330template<class DumpFn>
331C4_NO_INLINE void err_parse_format(DumpFn &&dumpfn, csubstr msg, ErrorDataParse const& errdata)
332{
333 if(errdata.ymlloc)
334 {
335 location_format(std::forward<DumpFn>(dumpfn), errdata.ymlloc);
336 std::forward<DumpFn>(dumpfn)(" ");
337 }
338 std::forward<DumpFn>(dumpfn)("ERROR: [parse] ");
339 std::forward<DumpFn>(dumpfn)(msg);
340 if(errdata.cpploc)
341 {
342 std::forward<DumpFn>(dumpfn)("\n");
343 location_format(std::forward<DumpFn>(dumpfn), errdata.cpploc);
344 std::forward<DumpFn>(dumpfn)(" (detected here)");
345 }
346}
347
348
349template<class DumpFn>
350C4_NO_INLINE void err_visit_format(DumpFn &&dumpfn, csubstr msg, ErrorDataVisit const& errdata)
351{
352 char buf_[32];
353 substr buf(buf_);
354 if(errdata.cpploc)
355 {
356 location_format(dumpfn, errdata.cpploc);
357 std::forward<DumpFn>(dumpfn)(" ");
358 }
359 std::forward<DumpFn>(dumpfn)("ERROR: [visit] ");
360 std::forward<DumpFn>(dumpfn)(msg);
361 if(errdata.node != NONE && errdata.tree != nullptr)
362 {
363 if(errdata.cpploc)
364 {
365 std::forward<DumpFn>(dumpfn)("\n");
366 location_format(dumpfn, errdata.cpploc);
367 std::forward<DumpFn>(dumpfn)(" ");
368 }
369 std::forward<DumpFn>(dumpfn)("ERROR: (");
370 if(errdata.node != NONE)
371 {
372 std::forward<DumpFn>(dumpfn)("node=");
373 std::forward<DumpFn>(dumpfn)(detail::_to_chars_limited(buf, errdata.node));
374 if(errdata.tree != nullptr)
375 std::forward<DumpFn>(dumpfn)(" ");
376 }
377 if(errdata.tree != nullptr)
378 {
379 std::forward<DumpFn>(dumpfn)("tree=");
380 std::forward<DumpFn>(dumpfn)(detail::_to_chars_limited(buf, static_cast<void const*>(errdata.tree)));
381 }
382 std::forward<DumpFn>(dumpfn)(")");
383 }
384}
385
386} // namespace yml
387} // namespace c4
388
389// NOLINTEND(bugprone-use-after-move,hicpp-invalid-access-moved)
390
391#endif /* _C4_YML_ERROR_HPP_ */
Error utilities used by ryml.
size_t location_format(DumpFn &&dumpfn, Location const &loc)
generic formatting of a location
Definition error.def.hpp:18
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 location_format_with_context(DumpFn &&dumpfn, Location const &location, csubstr source_buffer, csubstr call, size_t num_lines_before, size_t num_lines_after, size_t first_col_highlight, size_t last_col_highlight, size_t maxlen)
Generic formatting of a location, printing the source code buffer region around the location.
Definition error.def.hpp:86
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.
basic_substring< char > substr
a mutable string view
Definition substr.hpp:2356
basic_substring< const char > csubstr
an immutable string view
Definition substr.hpp:2357
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
@ NONE
an index to none
Definition common.hpp:256
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
Definition common.cpp:14
split_proxy split(C sep, size_t start_pos=0) const
a view into the splits
Definition substr.hpp:1913
size_t len
the length of the substring
Definition substr.hpp:218
bool empty() const noexcept
Definition substr.hpp:356
Data for a basic error.
Definition common.hpp:320
Location location
location where the error was detected (may be from YAML or C++ source code)
Definition common.hpp:321
Data for a parse error.
Definition common.hpp:329
Location cpploc
location in the C++ source file where the error was detected.
Definition common.hpp:330
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
Tree const * tree
tree where the error was detected
Definition common.hpp:341
id_type node
node where the error was detected
Definition common.hpp:342
holds a source or yaml file position, for example when an error is detected; See also location_format...
Definition common.hpp:289
size_t col
column
Definition common.hpp:292
size_t line
line
Definition common.hpp:291
size_t offset
number of bytes from the beginning of the source buffer
Definition common.hpp:290
csubstr name
name of the file
Definition common.hpp:293