• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

biojppm / rapidyaml / 18640334796

20 Oct 2025 02:34AM UTC coverage: 97.752% (+0.1%) from 97.65%
18640334796

Pull #550

github

web-flow
Merge 138b7f86b into 48acea949
Pull Request #550: Implement FLOW_ML style

823 of 856 new or added lines in 12 files covered. (96.14%)

160 existing lines in 15 files now uncovered.

13784 of 14101 relevant lines covered (97.75%)

543110.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.23
/src/c4/yml/filter_processor.hpp
1
#ifndef _C4_YML_FILTER_PROCESSOR_HPP_
2
#define _C4_YML_FILTER_PROCESSOR_HPP_
3

4
#ifndef _C4_YML_ERROR_HPP_
5
#include "./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
/** @defgroup doc_filter_processors Scalar filter processors
17
 *
18
 * These are internal utilities used by @ref ParseEngine to parse the
19
 * scalars; normally there is no reason for a user to be manually
20
 * using these classes.
21
 *
22
 * @ingroup doc_parse */
23
/** @{ */
24

25

26
//-----------------------------------------------------------------------------
27
//-----------------------------------------------------------------------------
28
//-----------------------------------------------------------------------------
29

30
/** Abstracts the fact that a scalar filter result may not fit in the
31
 * intended memory. */
32
struct FilterResult
33
{
34
    C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }
865,554✔
35
    C4_ALWAYS_INLINE size_t required_len() const noexcept { return str.len; }
34,180✔
36
    C4_ALWAYS_INLINE csubstr get() const { _RYML_ASSERT_BASIC(valid()); return str; }
505,728✔
37
    csubstr str;
38
};
39
/** Abstracts the fact that a scalar filter result may not fit in the
40
 * intended memory. */
41
struct FilterResultExtending
42
{
43
    C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }
226,804✔
44
    C4_ALWAYS_INLINE size_t required_len() const noexcept { return reqlen; }
22,200✔
45
    C4_ALWAYS_INLINE csubstr get() const { _RYML_ASSERT_BASIC(valid()); return str; }
128,236✔
46
    csubstr str;
47
    size_t reqlen;
48
};
49

50

51
//-----------------------------------------------------------------------------
52

53
/** Filters an input string into a different output string */
54
struct FilterProcessorSrcDst
55
{
56
    csubstr src;
57
    substr dst;
58
    size_t rpos; ///< read position
59
    size_t wpos; ///< write position
60

61
    C4_ALWAYS_INLINE FilterProcessorSrcDst(csubstr src_, substr dst_) noexcept
62
        : src(src_)
26,766✔
63
        , dst(dst_)
26,766✔
64
        , rpos(0)
26,766✔
65
        , wpos(0)
26,766✔
66
    {
67
        _RYML_ASSERT_BASIC(!dst.overlaps(src));
53,532✔
68
    }
26,766✔
69

70
    C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
71
    C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
72
    C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
588✔
73

74
    C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
2,121,390✔
75
    C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { _RYML_ASSERT_BASIC(maxpos <= src.len); return rpos < maxpos; }
50,010✔
76

77
    C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
18,144✔
78
    C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(dst.str, wpos <= dst.len ? wpos : dst.len); }
790✔
79
    C4_ALWAYS_INLINE FilterResult result() const noexcept
80
    {
81
        FilterResult ret;
26,868✔
82
        ret.str.str = wpos <= dst.len ? dst.str : nullptr;
26,868✔
83
        ret.str.len = wpos;
26,868✔
84
        return ret;
26,868✔
85
    }
86

87
    C4_ALWAYS_INLINE char curr() const noexcept { _RYML_ASSERT_BASIC(rpos < src.len); return src[rpos]; }
4,929,960✔
88
    C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
197,358✔
89
    C4_ALWAYS_INLINE bool skipped_chars() const noexcept { return wpos != rpos; }
90

91
    C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
62,484✔
92
    C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
20,928✔
93

94
    C4_ALWAYS_INLINE void set_at(size_t pos, char c) noexcept // NOLINT(readability-make-member-function-const)
95
    {
96
        _RYML_ASSERT_BASIC(pos < wpos);
444✔
97
        dst.str[pos] = c;
444✔
98
    }
444✔
99
    C4_ALWAYS_INLINE void set(char c) noexcept
100
    {
101
        if(wpos < dst.len)
90,516✔
102
            dst.str[wpos] = c;
90,078✔
103
        ++wpos;
90,516✔
104
    }
90,516✔
105
    C4_ALWAYS_INLINE void set(char c, size_t num) noexcept
106
    {
107
        _RYML_ASSERT_BASIC(num > 0);
6,732✔
108
        if(wpos + num <= dst.len)
6,732✔
109
            memset(dst.str + wpos, c, num);
6,204✔
110
        wpos += num;
6,732✔
111
    }
6,732✔
112

113
    C4_ALWAYS_INLINE void copy() noexcept
114
    {
115
        _RYML_ASSERT_BASIC(rpos < src.len);
1,880,880✔
116
        if(wpos < dst.len)
1,880,880✔
117
            dst.str[wpos] = src.str[rpos];
1,873,062✔
118
        ++wpos;
1,880,880✔
119
        ++rpos;
1,880,880✔
120
    }
1,880,880✔
121
    C4_ALWAYS_INLINE void copy(size_t num) noexcept
122
    {
123
        _RYML_ASSERT_BASIC(num);
1,308✔
124
        _RYML_ASSERT_BASIC(rpos+num <= src.len);
1,308✔
125
        if(wpos + num <= dst.len)
1,308✔
126
            memcpy(dst.str + wpos, src.str + rpos, num);
1,200✔
127
        wpos += num;
1,308✔
128
        rpos += num;
1,308✔
129
    }
1,308✔
130

131
    C4_ALWAYS_INLINE void translate_esc(char c) noexcept
132
    {
133
        if(wpos < dst.len)
32,346✔
134
            dst.str[wpos] = c;
31,848✔
135
        ++wpos;
32,346✔
136
        rpos += 2;
32,346✔
137
    }
32,346✔
138
    C4_ALWAYS_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
139
    {
140
        _RYML_ASSERT_BASIC(nw > 0);
52,668✔
141
        _RYML_ASSERT_BASIC(nr > 0);
52,668✔
142
        _RYML_ASSERT_BASIC(rpos+nr <= src.len);
52,668✔
143
        if(wpos+nw <= dst.len)
52,668✔
144
            memcpy(dst.str + wpos, s, nw);
51,900✔
145
        wpos += nw;
52,668✔
146
        rpos += 1 + nr;
52,668✔
147
    }
52,668✔
148
    C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
149
    {
150
        translate_esc_bulk(s, nw, nr);
151
    }
46,050✔
152
};
153

154

155
//-----------------------------------------------------------------------------
156
// filter in place
157

158
// debugging scaffold
159
/** @cond dev */
160
#if defined(RYML_DBG) && 0
161
#define _c4dbgip(...) _c4dbgpf(__VA_ARGS__)
162
#else
163
#define _c4dbgip(...)
164
#endif
165
/** @endcond */
166

167
/** Filters in place. While the result may be larger than the source,
168
 * any extending happens only at the end of the string. Consequently,
169
 * it's impossible for characters to be left unfiltered.
170
 *
171
 * @see FilterProcessorInplaceMidExtending */
172
struct FilterProcessorInplaceEndExtending
173
{
174
    substr src;  ///< the subject string
175
    size_t wcap; ///< write capacity - the capacity of the subject string's buffer
176
    size_t rpos; ///< read position
177
    size_t wpos; ///< write position
178

179
    C4_ALWAYS_INLINE FilterProcessorInplaceEndExtending(substr src_, size_t wcap_) noexcept
180
        : src(src_)
333,174✔
181
        , wcap(wcap_)
333,174✔
182
        , rpos(0)
333,174✔
183
        , wpos(0)
333,174✔
184
    {
185
        _RYML_ASSERT_BASIC(wcap >= src.len);
333,174✔
186
    }
333,174✔
187

188
    C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
189
    C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
190
    C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
91,860✔
191

192
    C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
2,125,008✔
193
    C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { _RYML_ASSERT_BASIC(maxpos <= src.len); return rpos < maxpos; }
2,323,914✔
194

195
    C4_ALWAYS_INLINE FilterResult result() const noexcept
196
    {
197
        _c4dbgip("inplace: wpos={} wcap={} small={}", wpos, wcap, wpos > rpos);
198
        FilterResult ret;
333,270✔
199
        ret.str.str = (wpos <= wcap) ? src.str : nullptr;
333,270✔
200
        ret.str.len = wpos;
333,270✔
201
        return ret;
333,270✔
202
    }
203
    C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }
46,200✔
204
    C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
1,399,600✔
205

206
    C4_ALWAYS_INLINE char curr() const noexcept { _RYML_ASSERT_BASIC(rpos < src.len); return src[rpos]; }
8,481,036✔
207
    C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
12,996✔
208

209
    C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
95,568✔
210
    C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
339,678✔
211

212
    void set_at(size_t pos, char c) noexcept
18,432✔
213
    {
214
        _RYML_ASSERT_BASIC(pos < wpos);
18,432✔
215
        const size_t save = wpos;
18,432✔
216
        wpos = pos;
18,432✔
217
        set(c);
18,432✔
218
        wpos = save;
18,432✔
219
    }
18,432✔
220
    void set(char c) noexcept
60,264✔
221
    {
222
        if(wpos < wcap)  // respect write-capacity
60,264✔
223
            src.str[wpos] = c;
60,102✔
224
        ++wpos;
60,264✔
225
    }
60,264✔
226
    void set(char c, size_t num) noexcept
17,904✔
227
    {
228
        _RYML_ASSERT_BASIC(num);
17,904✔
229
        if(wpos + num <= wcap)  // respect write-capacity
17,904✔
230
            memset(src.str + wpos, c, num);
17,904✔
231
        wpos += num;
17,904✔
232
    }
17,904✔
233

234
    void copy() noexcept
3,785,688✔
235
    {
236
        _RYML_ASSERT_BASIC(wpos <= rpos);
3,785,688✔
237
        _RYML_ASSERT_BASIC(rpos < src.len);
3,785,688✔
238
        if(wpos < wcap)  // respect write-capacity
3,785,688✔
239
            src.str[wpos] = src.str[rpos];
3,785,688✔
240
        ++rpos;
3,785,688✔
241
        ++wpos;
3,785,688✔
242
    }
3,785,688✔
243
    void copy(size_t num) noexcept
27,876✔
244
    {
245
        _RYML_ASSERT_BASIC(num);
27,876✔
246
        _RYML_ASSERT_BASIC(rpos+num <= src.len);
27,876✔
247
        _RYML_ASSERT_BASIC(wpos <= rpos);
27,876✔
248
        if(wpos + num <= wcap)  // respect write-capacity
27,876✔
249
        {
250
            if(wpos + num <= rpos) // there is no overlap
27,876✔
251
                memcpy(src.str + wpos, src.str + rpos, num);
24,894✔
252
            else                   // there is overlap
253
                memmove(src.str + wpos, src.str + rpos, num);
2,982✔
254
        }
255
        rpos += num;
27,876✔
256
        wpos += num;
27,876✔
257
    }
27,876✔
258

259
    void translate_esc(char c) noexcept
30✔
260
    {
261
        _RYML_ASSERT_BASIC(rpos + 2 <= src.len);
30✔
262
        _RYML_ASSERT_BASIC(wpos <= rpos);
30✔
263
        if(wpos < wcap) // respect write-capacity
30✔
264
            src.str[wpos] = c;
30✔
265
        rpos += 2; // add 1u to account for the escape character
30✔
266
        ++wpos;
30✔
267
    }
30✔
268

269
    void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
30✔
270
    {
271
        _RYML_ASSERT_BASIC(nw > 0);
30✔
272
        _RYML_ASSERT_BASIC(nr > 0);
30✔
273
        _RYML_ASSERT_BASIC(nw <= nr + 1u);
30✔
274
        _RYML_ASSERT_BASIC(rpos+nr <= src.len);
30✔
275
        _RYML_ASSERT_BASIC(wpos <= rpos);
30✔
276
        const size_t wpos_next = wpos + nw;
30✔
277
        const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
30✔
278
        _RYML_ASSERT_BASIC(wpos_next <= rpos_next);
30✔
279
        if(wpos_next <= wcap)
30✔
280
            memcpy(src.str + wpos, s, nw);
30✔
281
        rpos = rpos_next;
30✔
282
        wpos = wpos_next;
30✔
283
    }
30✔
284

285
    C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
286
    {
287
        translate_esc_bulk(s, nw, nr);
288
    }
289
};
290

291

292
//-----------------------------------------------------------------------------
293
//-----------------------------------------------------------------------------
294
//-----------------------------------------------------------------------------
295

296
/** Filters in place. The result may be larger than the source, and
297
 * extending may happen anywhere. As a result some characters may be
298
 * left unfiltered when there is no slack in the buffer and the
299
 * write-position would overlap the read-position. Consequently, it's
300
 * possible for characters to be left unfiltered. In YAML, this
301
 * happens only with double-quoted strings, and only with a small
302
 * number of escape sequences such as `\L` which is substituted by three
303
 * bytes. These escape sequences cause a call to translate_esc_extending()
304
 * which is the only entry point to this unfiltered situation.
305
 *
306
 * @see FilterProcessorInplaceMidExtending */
307
struct FilterProcessorInplaceMidExtending
308
{
309
    substr src;  ///< the subject string
310
    size_t wcap; ///< write capacity - the capacity of the subject string's buffer
311
    size_t rpos; ///< read position
312
    size_t wpos; ///< write position
313
    size_t maxcap; ///< the max capacity needed for filtering the string. This may be larger than the final string size.
314
    bool unfiltered_chars; ///< number of characters that were not added to wpos from lack of capacity
315

316
    C4_ALWAYS_INLINE FilterProcessorInplaceMidExtending(substr src_, size_t wcap_) noexcept
317
        : src(src_)
99,114✔
318
        , wcap(wcap_)
99,114✔
319
        , rpos(0)
99,114✔
320
        , wpos(0)
99,114✔
321
        , maxcap(src.len)
99,114✔
322
        , unfiltered_chars(false)
99,114✔
323
    {
324
        _RYML_ASSERT_BASIC(wcap >= src.len);
99,114✔
325
    }
99,114✔
326

327
    C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
328
    C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
329
    C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
330

331
    C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
3,866,868✔
332
    C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { _RYML_ASSERT_BASIC(maxpos <= src.len); return rpos < maxpos; }
333

334
    C4_ALWAYS_INLINE FilterResultExtending result() const noexcept
335
    {
336
        _c4dbgip("inplace: wpos={} wcap={} unfiltered={} maxcap={}", this->wpos, this->wcap, this->unfiltered_chars, this->maxcap);
337
        FilterResultExtending ret;
99,132✔
338
        ret.str.str = (wpos <= wcap && !unfiltered_chars) ? src.str : nullptr;
99,132✔
339
        ret.str.len = wpos;
99,132✔
340
        ret.reqlen = maxcap;
99,132✔
341
        return ret;
99,132✔
342
    }
343
    C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }
850✔
344
    C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
345

346
    C4_ALWAYS_INLINE char curr() const noexcept { _RYML_ASSERT_BASIC(rpos < src.len); return src[rpos]; }
8,625,216✔
347
    C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
504,564✔
348

349
    C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
70,602✔
350
    C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
19,644✔
351

352
    void set_at(size_t pos, char c) noexcept
353
    {
354
        _RYML_ASSERT_BASIC(pos < wpos);
355
        const size_t save = wpos;
356
        wpos = pos;
357
        set(c);
358
        wpos = save;
359
    }
360
    void set(char c) noexcept
104,994✔
361
    {
362
        if(wpos < wcap)  // respect write-capacity
104,994✔
363
        {
364
            if((wpos <= rpos) && !unfiltered_chars)
103,620✔
365
                src.str[wpos] = c;
11,118✔
366
        }
367
        else
368
        {
369
            _c4dbgip("inplace: add unwritten {}->{}   maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
370
            unfiltered_chars = true;
1,374✔
371
        }
372
        ++wpos;
104,994✔
373
        maxcap = wpos > maxcap ? wpos : maxcap;
104,994✔
374
    }
104,994✔
375
    void set(char c, size_t num) noexcept
8,166✔
376
    {
377
        _RYML_ASSERT_BASIC(num);
8,166✔
378
        if(wpos + num <= wcap)  // respect write-capacity
8,166✔
379
        {
380
            if((wpos <= rpos) && !unfiltered_chars)
8,094✔
381
                memset(src.str + wpos, c, num);
2,868✔
382
        }
383
        else
384
        {
385
            _c4dbgip("inplace: add unwritten {}->{}   maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+num > maxcap ? wpos+num : maxcap));
386
            unfiltered_chars = true;
72✔
387
        }
388
        wpos += num;
8,166✔
389
        maxcap = wpos > maxcap ? wpos : maxcap;
8,166✔
390
    }
8,166✔
391

392
    void copy() noexcept
3,318,744✔
393
    {
394
        _RYML_ASSERT_BASIC(rpos < src.len);
3,318,744✔
395
        if(wpos < wcap)  // respect write-capacity
3,318,744✔
396
        {
397
            if((wpos < rpos) && !unfiltered_chars)  // write only if wpos is behind rpos
3,296,622✔
398
                src.str[wpos] = src.str[rpos];
857,640✔
399
        }
400
        else
401
        {
402
            _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));
403
            unfiltered_chars = true;
22,122✔
404
        }
405
        ++rpos;
3,318,744✔
406
        ++wpos;
3,318,744✔
407
        maxcap = wpos > maxcap ? wpos : maxcap;
3,318,744✔
408
    }
3,318,744✔
409
    void copy(size_t num) noexcept
9,588✔
410
    {
411
        _RYML_ASSERT_BASIC(num);
9,588✔
412
        _RYML_ASSERT_BASIC(rpos+num <= src.len);
9,588✔
413
        if(wpos + num <= wcap)  // respect write-capacity
9,588✔
414
        {
415
            if((wpos < rpos) && !unfiltered_chars)  // write only if wpos is behind rpos
9,498✔
416
            {
417
                if(wpos + num <= rpos) // there is no overlap
9,252✔
418
                    memcpy(src.str + wpos, src.str + rpos, num);
9,246✔
419
                else                   // there is overlap
420
                    memmove(src.str + wpos, src.str + rpos, num);
6✔
421
            }
422
        }
423
        else
424
        {
425
            _c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={}  (wpos={}<wcap={})  maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);
426
            unfiltered_chars = true;
90✔
427
        }
428
        rpos += num;
9,588✔
429
        wpos += num;
9,588✔
430
        maxcap = wpos > maxcap ? wpos : maxcap;
9,588✔
431
    }
9,588✔
432

433
    void translate_esc(char c) noexcept
172,110✔
434
    {
435
        _RYML_ASSERT_BASIC(rpos + 2 <= src.len);
172,110✔
436
        if(wpos < wcap) // respect write-capacity
172,110✔
437
        {
438
            if((wpos <= rpos) && !unfiltered_chars)
170,796✔
439
                src.str[wpos] = c;
140,454✔
440
        }
441
        else
442
        {
443
            _c4dbgip("inplace: add unfiltered {}->{}  maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
444
            unfiltered_chars = true;
1,314✔
445
        }
446
        rpos += 2;
172,110✔
447
        ++wpos;
172,110✔
448
        maxcap = wpos > maxcap ? wpos : maxcap;
172,110✔
449
    }
172,110✔
450

451
    C4_NO_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
7,488✔
452
    {
453
        _RYML_ASSERT_BASIC(nw > 0);
7,488✔
454
        _RYML_ASSERT_BASIC(nr > 0);
7,488✔
455
        _RYML_ASSERT_BASIC(nr+1u >= nw);
7,488✔
456
        const size_t wpos_next = wpos + nw;
7,488✔
457
        const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
7,488✔
458
        if(wpos_next <= wcap)  // respect write-capacity
7,488✔
459
        {
460
            if((wpos <= rpos) && !unfiltered_chars)  // write only if wpos is behind rpos
7,074✔
461
                memcpy(src.str + wpos, s, nw);
2,160✔
462
        }
463
        else
464
        {
465
            _c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={}  (wpos={}<wcap={})  maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);
466
            unfiltered_chars = true;
414✔
467
        }
468
        rpos = rpos_next;
7,488✔
469
        wpos = wpos_next;
7,488✔
470
        maxcap = wpos > maxcap ? wpos : maxcap;
7,488✔
471
    }
7,488✔
472

473
    C4_NO_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
57,594✔
474
    {
475
        _RYML_ASSERT_BASIC(nw > 0);
57,594✔
476
        _RYML_ASSERT_BASIC(nr > 0);
57,594✔
477
        _RYML_ASSERT_BASIC(rpos+nr <= src.len);
57,594✔
478
        const size_t wpos_next = wpos + nw;
57,594✔
479
        const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
57,594✔
480
        if(wpos_next <= rpos_next) // read and write do not overlap. just do a vanilla copy.
57,594✔
481
        {
482
            if((wpos_next <= wcap) && !unfiltered_chars)
4,992✔
483
                memcpy(src.str + wpos, s, nw);
2,202✔
484
            rpos = rpos_next;
4,992✔
485
            wpos = wpos_next;
4,992✔
486
            maxcap = wpos > maxcap ? wpos : maxcap;
4,992✔
487
        }
488
        else // there is overlap. move the (to-be-read) string to the right.
489
        {
490
            const size_t excess = wpos_next - rpos_next;
52,602✔
491
            _RYML_ASSERT_BASIC(wpos_next > rpos_next);
52,602✔
492
            if(src.len + excess <= wcap) // ensure we do not go past the end
52,602✔
493
            {
494
                _RYML_ASSERT_BASIC(rpos+nr+excess <= src.len);
1,284✔
495
                if(wpos_next <= wcap)
1,284✔
496
                {
497
                    if(!unfiltered_chars)
1,284✔
498
                    {
499
                        memmove(src.str + wpos_next, src.str + rpos_next, src.len - rpos_next);
1,284✔
500
                        memcpy(src.str + wpos, s, nw);
1,284✔
501
                    }
502
                    rpos = wpos_next; // wpos, not rpos
1,284✔
503
                }
504
                else
505
                {
UNCOV
506
                    rpos = rpos_next;
×
507
                    //const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;
508
                    _c4dbgip("inplace: add unfiltered {}->{}   maxcap={}->{}!", unfiltered_chars, true);
UNCOV
509
                    unfiltered_chars = true;
×
510
                }
511
                wpos = wpos_next;
1,284✔
512
                // extend the string up to capacity
513
                src.len += excess;
1,284✔
514
                maxcap = wpos > maxcap ? wpos : maxcap;
1,284✔
515
            }
516
            else
517
            {
518
                //const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;
519
                _RYML_ASSERT_BASIC(rpos_next <= src.len);
51,318✔
520
                const size_t required_size = wpos_next + (src.len - rpos_next);
51,318✔
521
                _c4dbgip("inplace: add unfiltered {}->{}   maxcap={}->{}!", unfiltered_chars, true, maxcap, required_size > maxcap ? required_size : maxcap);
522
                _RYML_ASSERT_BASIC(required_size > wcap);
51,318✔
523
                unfiltered_chars = true;
51,318✔
524
                maxcap = required_size > maxcap ? required_size : maxcap;
51,318✔
525
                wpos = wpos_next;
51,318✔
526
                rpos = rpos_next;
51,318✔
527
            }
528
        }
529
    }
57,594✔
530
};
531

532
#undef _c4dbgip
533

534

535
/** @} */
536

537
} // namespace yml
538
} // namespace c4
539

540
#endif /* _C4_YML_FILTER_PROCESSOR_HPP_ */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc