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