File Coverage

src/mds_buf.h
Criterion Covered Total %
statement 4 4 100.0
branch 155 284 54.5
condition n/a
subroutine n/a
pod n/a
total 159 288 55.2


line stmt bran cond sub pod time code
1             /* mds_buf.h — output buffer wrapping a Perl SV.
2             *
3             * Owns a cursor into SvPV so we avoid SvCUR/SvLEN roundtrips per write.
4             * Caller must call mds_buf_finalize() before the SV is consumed by Perl.
5             */
6             #ifndef MDS_BUF_H
7             #define MDS_BUF_H
8              
9             #include
10             #include "EXTERN.h"
11             #include "perl.h"
12             #include "mds_compiler.h"
13              
14             typedef struct mds_buf {
15             SV* sv;
16             char* base; /* SvPVX(sv) */
17             char* cur; /* write cursor */
18             char* end; /* base + SvLEN(sv) - 1 (room for trailing NUL) */
19             } mds_buf;
20              
21             /* Attach to an existing SV, predict initial capacity. */
22             void mds_buf_init(pTHX_ mds_buf* b, SV* sv, size_t hint);
23              
24             /* Input-aware initial capacity. Samples the head of
25             * `input` for pipe density and picks 2.25\u00d7 for table-heavy inputs,
26             * 1.50\u00d7 for everything else. Falls back to mds_buf_init's prose
27             * default when input is NULL. */
28             void mds_buf_init_for_input(pTHX_ mds_buf* b, SV* sv,
29             const char* input, size_t hint);
30              
31             /* Ensure at least `need` bytes free; grows SV and refreshes cursor. */
32             void mds_buf_reserve(pTHX_ mds_buf* b, size_t need);
33              
34             /* Append n bytes. The grow check is the only branch; the common case
35             * (n bytes fit) compiles to a 2-instruction cursor bump + memcpy that
36             * the optimiser turns into a register store when n is a compile-time
37             * constant under 8. Marked always-inline so the constant-n cases at
38             * call sites (HTML tags via MDS_BUF_LIT) really do specialise. */
39             MDS_ALWAYS_INLINE static void mds_buf_write(pTHX_ mds_buf* b, const char* s, size_t n) {
40 30839 100         if (MDS_UNLIKELY(b->cur + n > b->end)) mds_buf_reserve(aTHX_ b, n);
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    0          
    0          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
41 30839           memcpy(b->cur, s, n);
42 30839           b->cur += n;
43 30839           }
44              
45             MDS_ALWAYS_INLINE static void mds_buf_putc(pTHX_ mds_buf* b, char c) {
46             if (MDS_UNLIKELY(b->cur + 1 > b->end)) mds_buf_reserve(aTHX_ b, 1);
47             *b->cur++ = c;
48             }
49              
50             /* Write a compile-time literal. */
51             #define MDS_BUF_LIT(b, lit) mds_buf_write(aTHX_ (b), "" lit, sizeof(lit) - 1)
52              
53             /* Commit cursor to SvCUR, NUL-terminate. */
54             void mds_buf_finalize(pTHX_ mds_buf* b);
55              
56             #endif