rapidyaml  0.16.0
parseandemitYAML,anddoitfast
filter_processor.hpp
Go to the documentation of this file.
1 #ifndef C4_YML_FILTER_PROCESSOR_HPP_
2 #define C4_YML_FILTER_PROCESSOR_HPP_
3 
4 #ifndef C4_YML_ERROR_HPP_
5 #include "c4/yml/error.hpp"
6 #endif
7 
8 #ifdef RYML_DBG
9 #include "c4/charconv.hpp"
10 #include "c4/yml/detail/dbgprint.hpp"
11 #endif
12 
13 namespace c4 {
14 namespace yml {
15 
16 /** @addtogroup doc_scalar_filter */
17 /** @{ */
18 
19 
20 //-----------------------------------------------------------------------------
21 //-----------------------------------------------------------------------------
22 //-----------------------------------------------------------------------------
23 
24 /** Result for filtering a scalar which not fit in the intended
25  * memory. */
27 {
28  C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }
29  C4_ALWAYS_INLINE size_t required_len() const noexcept { return str.len; }
30  C4_ALWAYS_INLINE csubstr get() const { RYML_ASSERT_BASIC_(valid()); return str; }
32 };
33 /** Result for filtering a scalar which not fit in the intended
34  * memory. */
36 {
37  C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }
38  C4_ALWAYS_INLINE size_t required_len() const noexcept { return reqlen; }
39  C4_ALWAYS_INLINE csubstr get() const { RYML_ASSERT_BASIC_(valid()); return str; }
41  size_t reqlen;
42 };
43 
44 
45 //-----------------------------------------------------------------------------
46 
47 /** Filters an input string into a different output string */
49 {
52  size_t rpos; ///< read position
53  size_t wpos; ///< write position
54 
55  C4_ALWAYS_INLINE FilterProcessorSrcDst(csubstr src_, substr dst_) noexcept
56  : src(src_)
57  , dst(dst_)
58  , rpos(0)
59  , wpos(0)
60  {
61  RYML_ASSERT_BASIC_(!dst.overlaps(src));
62  }
63 
64  C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
65  C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
66  C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
67 
68  C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
69  C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT_BASIC_(maxpos <= src.len); return rpos < maxpos; }
70 
71  C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
72  C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(dst.str, wpos <= dst.len ? wpos : dst.len); }
73  C4_ALWAYS_INLINE FilterResult result() const noexcept
74  {
75  FilterResult ret;
76  ret.str.str = wpos <= dst.len ? dst.str : nullptr;
77  ret.str.len = wpos;
78  return ret;
79  }
80 
81  C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT_BASIC_(rpos < src.len); return src[rpos]; }
82  C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
83  C4_ALWAYS_INLINE bool skipped_chars() const noexcept { return wpos != rpos; }
84 
85  C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
86  C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
87 
88  C4_ALWAYS_INLINE void set_at(size_t pos, char c) noexcept // NOLINT(readability-make-member-function-const)
89  {
90  RYML_ASSERT_BASIC_(pos < wpos);
91  dst.str[pos] = c;
92  }
93  C4_ALWAYS_INLINE void set(char c) noexcept
94  {
95  if(wpos < dst.len)
96  dst.str[wpos] = c;
97  ++wpos;
98  }
99  C4_ALWAYS_INLINE void set(char c, size_t num) noexcept
100  {
101  RYML_ASSERT_BASIC_(num > 0);
102  if(wpos + num <= dst.len)
103  memset(dst.str + wpos, c, num);
104  wpos += num;
105  }
106 
107  C4_ALWAYS_INLINE void copy() noexcept
108  {
109  RYML_ASSERT_BASIC_(rpos < src.len);
110  if(wpos < dst.len)
111  dst.str[wpos] = src.str[rpos];
112  ++wpos;
113  ++rpos;
114  }
115  C4_ALWAYS_INLINE void copy(size_t num) noexcept
116  {
117  RYML_ASSERT_BASIC_(num);
118  RYML_ASSERT_BASIC_(rpos+num <= src.len);
119  if(wpos + num <= dst.len)
120  memcpy(dst.str + wpos, src.str + rpos, num);
121  wpos += num;
122  rpos += num;
123  }
124 
125  C4_ALWAYS_INLINE void translate_esc(char c) noexcept
126  {
127  if(wpos < dst.len)
128  dst.str[wpos] = c;
129  ++wpos;
130  rpos += 2;
131  }
132  C4_ALWAYS_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
133  {
134  RYML_ASSERT_BASIC_(nw > 0);
135  RYML_ASSERT_BASIC_(nr > 0);
136  RYML_ASSERT_BASIC_(rpos+nr <= src.len);
137  if(wpos+nw <= dst.len)
138  memcpy(dst.str + wpos, s, nw);
139  wpos += nw;
140  rpos += 1 + nr;
141  }
142  C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
143  {
144  translate_esc_bulk(s, nw, nr);
145  }
146 };
147 
148 
149 //-----------------------------------------------------------------------------
150 // filter in place
151 
152 // debugging scaffold
153 /** @cond dev */
154 #if defined(RYML_DBG) && 0
155 #define _c4dbgip(...) _c4dbgpf(__VA_ARGS__)
156 #else
157 #define _c4dbgip(...)
158 #endif
159 /** @endcond */
160 
161 /** Filters in place. While the result may be larger than the source,
162  * any extending happens only at the end of the string. Consequently,
163  * it's impossible for characters to be left unfiltered.
164  *
165  * @see FilterProcessorInplaceMidExtending */
167 {
168  substr src; ///< the subject string
169  size_t wcap; ///< write capacity - the capacity of the subject string's buffer
170  size_t rpos; ///< read position
171  size_t wpos; ///< write position
172 
173  C4_ALWAYS_INLINE FilterProcessorInplaceEndExtending(substr src_, size_t wcap_) noexcept
174  : src(src_)
175  , wcap(wcap_)
176  , rpos(0)
177  , wpos(0)
178  {
179  RYML_ASSERT_BASIC_(wcap >= src.len);
180  }
181 
182  C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
183  C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
184  C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
185 
186  C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
187  C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT_BASIC_(maxpos <= src.len); return rpos < maxpos; }
188 
189  C4_ALWAYS_INLINE FilterResult result() const noexcept
190  {
191  _c4dbgip("inplace: wpos={} wcap={} small={}", wpos, wcap, wpos > rpos);
192  FilterResult ret;
193  ret.str.str = (wpos <= wcap) ? src.str : nullptr;
194  ret.str.len = wpos;
195  return ret;
196  }
197  C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }
198  C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
199 
200  C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT_BASIC_(rpos < src.len); return src[rpos]; }
201  C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
202 
203  C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
204  C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
205 
206  void set_at(size_t pos, char c) noexcept
207  {
208  RYML_ASSERT_BASIC_(pos < wpos);
209  const size_t save = wpos;
210  wpos = pos;
211  set(c);
212  wpos = save;
213  }
214  void set(char c) noexcept
215  {
216  if(wpos < wcap) // respect write-capacity
217  src.str[wpos] = c;
218  ++wpos;
219  }
220  void set(char c, size_t num) noexcept
221  {
222  RYML_ASSERT_BASIC_(num);
223  if(wpos + num <= wcap) // respect write-capacity
224  memset(src.str + wpos, c, num);
225  wpos += num;
226  }
227 
228  void copy() noexcept
229  {
230  RYML_ASSERT_BASIC_(wpos <= rpos);
231  RYML_ASSERT_BASIC_(rpos < src.len);
232  if(wpos < wcap) // respect write-capacity
233  src.str[wpos] = src.str[rpos];
234  ++rpos;
235  ++wpos;
236  }
237  void copy(size_t num) noexcept
238  {
239  RYML_ASSERT_BASIC_(num);
240  RYML_ASSERT_BASIC_(rpos+num <= src.len);
241  RYML_ASSERT_BASIC_(wpos <= rpos);
242  if(wpos + num <= wcap) // respect write-capacity
243  {
244  if(wpos + num <= rpos) // there is no overlap
245  memcpy(src.str + wpos, src.str + rpos, num);
246  else // there is overlap
247  memmove(src.str + wpos, src.str + rpos, num);
248  }
249  rpos += num;
250  wpos += num;
251  }
252 
253  void translate_esc(char c) noexcept
254  {
255  RYML_ASSERT_BASIC_(rpos + 2 <= src.len);
256  RYML_ASSERT_BASIC_(wpos <= rpos);
257  if(wpos < wcap) // respect write-capacity
258  src.str[wpos] = c;
259  rpos += 2; // add 1u to account for the escape character
260  ++wpos;
261  }
262 
263  void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
264  {
265  RYML_ASSERT_BASIC_(nw > 0);
266  RYML_ASSERT_BASIC_(nr > 0);
267  RYML_ASSERT_BASIC_(nw <= nr + 1u);
268  RYML_ASSERT_BASIC_(rpos+nr <= src.len);
269  RYML_ASSERT_BASIC_(wpos <= rpos);
270  const size_t wpos_next = wpos + nw;
271  const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
272  RYML_ASSERT_BASIC_(wpos_next <= rpos_next);
273  if(wpos_next <= wcap)
274  memcpy(src.str + wpos, s, nw);
275  rpos = rpos_next;
276  wpos = wpos_next;
277  }
278 
279  C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
280  {
281  translate_esc_bulk(s, nw, nr);
282  }
283 };
284 
285 
286 //-----------------------------------------------------------------------------
287 //-----------------------------------------------------------------------------
288 //-----------------------------------------------------------------------------
289 
290 /** Filters in place. The result may be larger than the source, and
291  * extending may happen anywhere. As a result some characters may be
292  * left unfiltered when there is no slack in the buffer and the
293  * write-position would overlap the read-position. Consequently, it's
294  * possible for characters to be left unfiltered. In YAML, this
295  * happens only with double-quoted strings, and only with a small
296  * number of escape sequences such as `\L` which is substituted by three
297  * bytes. These escape sequences cause a call to translate_esc_extending()
298  * which is the only entry point to this unfiltered situation.
299  *
300  * @see FilterProcessorInplaceEndExtending */
302 {
303  substr src; ///< the subject string
304  size_t wcap; ///< write capacity - the capacity of the subject string's buffer
305  size_t rpos; ///< read position
306  size_t wpos; ///< write position
307  size_t maxcap; ///< the max capacity needed for filtering the string. This may be larger than the final string size.
308  bool unfiltered_chars; ///< number of characters that were not added to wpos from lack of capacity
309 
310  C4_ALWAYS_INLINE FilterProcessorInplaceMidExtending(substr src_, size_t wcap_) noexcept
311  : src(src_)
312  , wcap(wcap_)
313  , rpos(0)
314  , wpos(0)
315  , maxcap(src.len)
316  , unfiltered_chars(false)
317  {
318  RYML_ASSERT_BASIC_(wcap >= src.len);
319  }
320 
321  C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
322  C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
323  C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
324 
325  C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
326  C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT_BASIC_(maxpos <= src.len); return rpos < maxpos; }
327 
328  C4_ALWAYS_INLINE FilterResultExtending result() const noexcept
329  {
330  _c4dbgip("inplace: wpos={} wcap={} unfiltered={} maxcap={}", this->wpos, this->wcap, this->unfiltered_chars, this->maxcap);
332  ret.str.str = (wpos <= wcap && !unfiltered_chars) ? src.str : nullptr;
333  ret.str.len = wpos;
334  ret.reqlen = maxcap;
335  return ret;
336  }
337  C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }
338  C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
339 
340  C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT_BASIC_(rpos < src.len); return src[rpos]; }
341  C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
342 
343  C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
344  C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
345 
346  void set_at(size_t pos, char c) noexcept
347  {
348  RYML_ASSERT_BASIC_(pos < wpos);
349  const size_t save = wpos;
350  wpos = pos;
351  set(c);
352  wpos = save;
353  }
354  void set(char c) noexcept
355  {
356  if(wpos < wcap) // respect write-capacity
357  {
358  if((wpos <= rpos) && !unfiltered_chars)
359  src.str[wpos] = c;
360  }
361  else
362  {
363  _c4dbgip("inplace: add unwritten {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
364  unfiltered_chars = true;
365  }
366  ++wpos;
367  maxcap = wpos > maxcap ? wpos : maxcap;
368  }
369  void set(char c, size_t num) noexcept
370  {
371  RYML_ASSERT_BASIC_(num);
372  if(wpos + num <= wcap) // respect write-capacity
373  {
374  if((wpos <= rpos) && !unfiltered_chars)
375  memset(src.str + wpos, c, num);
376  }
377  else
378  {
379  _c4dbgip("inplace: add unwritten {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+num > maxcap ? wpos+num : maxcap));
380  unfiltered_chars = true;
381  }
382  wpos += num;
383  maxcap = wpos > maxcap ? wpos : maxcap;
384  }
385 
386  void copy() noexcept
387  {
388  RYML_ASSERT_BASIC_(rpos < src.len);
389  if(wpos < wcap) // respect write-capacity
390  {
391  if((wpos < rpos) && !unfiltered_chars) // write only if wpos is behind rpos
392  src.str[wpos] = src.str[rpos];
393  }
394  else
395  {
396  _c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={} (wpos={}<wcap={}) maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
397  unfiltered_chars = true;
398  }
399  ++rpos;
400  ++wpos;
401  maxcap = wpos > maxcap ? wpos : maxcap;
402  }
403  void copy(size_t num) noexcept
404  {
405  RYML_ASSERT_BASIC_(num);
406  RYML_ASSERT_BASIC_(rpos+num <= src.len);
407  if(wpos + num <= wcap) // respect write-capacity
408  {
409  if((wpos < rpos) && !unfiltered_chars) // write only if wpos is behind rpos
410  {
411  if(wpos + num <= rpos) // there is no overlap
412  memcpy(src.str + wpos, src.str + rpos, num);
413  else // there is overlap
414  memmove(src.str + wpos, src.str + rpos, num);
415  }
416  }
417  else
418  {
419  _c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={} (wpos={}<wcap={}) maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);
420  unfiltered_chars = true;
421  }
422  rpos += num;
423  wpos += num;
424  maxcap = wpos > maxcap ? wpos : maxcap;
425  }
426 
427  void translate_esc(char c) noexcept
428  {
429  RYML_ASSERT_BASIC_(rpos + 2 <= src.len);
430  if(wpos < wcap) // respect write-capacity
431  {
432  if((wpos <= rpos) && !unfiltered_chars)
433  src.str[wpos] = c;
434  }
435  else
436  {
437  _c4dbgip("inplace: add unfiltered {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
438  unfiltered_chars = true;
439  }
440  rpos += 2;
441  ++wpos;
442  maxcap = wpos > maxcap ? wpos : maxcap;
443  }
444 
445  C4_NO_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
446  {
447  RYML_ASSERT_BASIC_(nw > 0);
448  RYML_ASSERT_BASIC_(nr > 0);
449  RYML_ASSERT_BASIC_(nr+1u >= nw);
450  const size_t wpos_next = wpos + nw;
451  const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
452  if(wpos_next <= wcap) // respect write-capacity
453  {
454  if((wpos <= rpos) && !unfiltered_chars) // write only if wpos is behind rpos
455  memcpy(src.str + wpos, s, nw);
456  }
457  else
458  {
459  _c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={} (wpos={}<wcap={}) maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);
460  unfiltered_chars = true;
461  }
462  rpos = rpos_next;
463  wpos = wpos_next;
464  maxcap = wpos > maxcap ? wpos : maxcap;
465  }
466 
467  C4_NO_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
468  {
469  RYML_ASSERT_BASIC_(nw > 0);
470  RYML_ASSERT_BASIC_(nr > 0);
471  RYML_ASSERT_BASIC_(rpos+nr <= src.len);
472  const size_t wpos_next = wpos + nw;
473  const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
474  if(wpos_next <= rpos_next) // read and write do not overlap. just do a vanilla copy.
475  {
476  if((wpos_next <= wcap) && !unfiltered_chars)
477  memcpy(src.str + wpos, s, nw);
478  rpos = rpos_next;
479  wpos = wpos_next;
480  maxcap = wpos > maxcap ? wpos : maxcap;
481  }
482  else // there is overlap. move the (to-be-read) string to the right.
483  {
484  const size_t excess = wpos_next - rpos_next;
485  RYML_ASSERT_BASIC_(wpos_next > rpos_next);
486  if(src.len + excess <= wcap) // ensure we do not go past the end
487  {
488  RYML_ASSERT_BASIC_(rpos+nr+excess <= src.len);
489  if(wpos_next <= wcap)
490  {
491  if(!unfiltered_chars)
492  {
493  memmove(src.str + wpos_next, src.str + rpos_next, src.len - rpos_next);
494  memcpy(src.str + wpos, s, nw);
495  }
496  rpos = wpos_next; // wpos, not rpos
497  }
498  else
499  {
500  rpos = rpos_next;
501  //const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;
502  _c4dbgip("inplace: add unfiltered {}->{} maxcap={}->{}!", unfiltered_chars, true);
503  unfiltered_chars = true;
504  }
505  wpos = wpos_next;
506  // extend the string up to capacity
507  src.len += excess;
508  maxcap = wpos > maxcap ? wpos : maxcap;
509  }
510  else
511  {
512  //const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;
513  RYML_ASSERT_BASIC_(rpos_next <= src.len);
514  const size_t required_size = wpos_next + (src.len - rpos_next);
515  _c4dbgip("inplace: add unfiltered {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, required_size > maxcap ? required_size : maxcap);
516  RYML_ASSERT_BASIC_(required_size > wcap);
517  unfiltered_chars = true;
518  maxcap = required_size > maxcap ? required_size : maxcap;
519  wpos = wpos_next;
520  rpos = rpos_next;
521  }
522  }
523  }
524 };
525 
526 #undef _c4dbgip
527 
528 
529 /** @} */
530 
531 } // namespace yml
532 } // namespace c4
533 
534 #endif /* C4_YML_FILTER_PROCESSOR_HPP_ */
void set_at(size_t pos, char c) noexcept
void translate_esc_extending(const char *s, size_t nw, size_t nr) noexcept
FilterResultExtending result() const noexcept
bool overlaps(ro_substr const that) const noexcept
true if there is overlap of at least one element between that and *this
Definition: substr.hpp:493
size_t wcap
write capacity - the capacity of the subject string's buffer
void translate_esc_extending(const char *s, size_t nw, size_t nr) noexcept
void translate_esc_bulk(const char *s, size_t nw, size_t nr) noexcept
void translate_esc_bulk(const char *s, size_t nw, size_t nr) noexcept
void set(char c, size_t num) noexcept
FilterResult result() const noexcept
void set_at(size_t pos, char c) noexcept
C * str
a restricted pointer to the first character of the substring
Definition: substr.hpp:216
size_t required_len() const noexcept
void setpos(size_t rpos_, size_t wpos_) noexcept
bool skipped_chars() const noexcept
void set(char c, size_t num) noexcept
void set(char c, size_t num) noexcept
void setpos(size_t rpos_, size_t wpos_) noexcept
bool has_more_chars(size_t maxpos) const noexcept
size_t required_len() const noexcept
FilterProcessorInplaceEndExtending(substr src_, size_t wcap_) noexcept
bool has_more_chars() const noexcept
FilterProcessorInplaceMidExtending(substr src_, size_t wcap_) noexcept
size_t maxcap
the max capacity needed for filtering the string. This may be larger than the final string size...
void setwpos(size_t wpos_) noexcept
FilterProcessorSrcDst(csubstr src_, substr dst_) noexcept
void copy(size_t num) noexcept
basic_substring sub(size_t first) const noexcept
return [first,len[
Definition: substr.hpp:502
Lightweight generic type-safe wrappers for converting individual values to/from strings.
void set_at(size_t pos, char c) noexcept
basic_substring< const char > csubstr
an immutable string view
Definition: substr.hpp:2356
void setpos(size_t rpos_, size_t wpos_) noexcept
size_t len
the length of the substring
Definition: substr.hpp:218
Error utilities used by ryml.
bool unfiltered_chars
number of characters that were not added to wpos from lack of capacity
csubstr sofar() const noexcept
size_t wcap
write capacity - the capacity of the subject string's buffer
Filters an input string into a different output string.
void translate_esc_bulk(const char *s, size_t nw, size_t nr) noexcept
bool has_more_chars(size_t maxpos) const noexcept
csubstr rem() const noexcept
Result for filtering a scalar which not fit in the intended memory.
bool has_more_chars(size_t maxpos) const noexcept
Result for filtering a scalar which not fit in the intended memory.
void skip(size_t num) noexcept
void translate_esc(char c) noexcept
bool valid() const noexcept
void translate_esc_extending(const char *s, size_t nw, size_t nr) noexcept