dte test coverage


Directory: ./
File: src/block-iter.h
Date: 2025-10-16 19:09:21
Exec Total Coverage
Lines: 27 37 73.0%
Functions: 8 9 88.9%
Branches: 10 16 62.5%

Line Branch Exec Source
1 #ifndef BLOCK_ITER_H
2 #define BLOCK_ITER_H
3
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include "block.h"
7 #include "util/list.h"
8 #include "util/macros.h"
9 #include "util/string-view.h"
10 #include "util/unicode.h"
11
12 // An iterator used to represent the cursor position for each View of a
13 // Buffer (see View::cursor) and also as a means for accessing/iterating
14 // the Blocks that make up the text contents of a Buffer (see Buffer::blocks).
15 typedef struct {
16 Block *blk; // The Block this iterator/cursor currently points to
17 const ListHead *head; // A pointer to the Buffer::blocks that owns `blk`
18 size_t offset; // The current position within `blk->data`
19 } BlockIter;
20
21 typedef struct {
22 StringView line;
23 size_t cursor_offset;
24 } CurrentLineRef;
25
26 10 static inline void block_iter_bof(BlockIter *bi)
27 {
28 10 bi->blk = BLOCK(bi->head->next);
29 10 bi->offset = 0;
30 10 }
31
32 8 static inline void block_iter_eof(BlockIter *bi)
33 {
34 8 bi->blk = BLOCK(bi->head->prev);
35 8 bi->offset = bi->blk->size;
36 8 }
37
38 321 static inline bool block_iter_is_eof(const BlockIter *bi)
39 {
40
3/4
✓ Branch 0 (2→3) taken 59 times.
✓ Branch 1 (2→4) taken 262 times.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 59 times.
321 return bi->offset == bi->blk->size && bi->blk->node.next == bi->head;
41 }
42
43 268 static inline bool block_iter_is_bol(const BlockIter *bi)
44 {
45 // See also: Block invariants mentioned in sanity_check_blocks()
46
4/4
✓ Branch 0 (2→3) taken 178 times.
✓ Branch 1 (2→5) taken 90 times.
✓ Branch 2 (3→4) taken 103 times.
✓ Branch 3 (3→5) taken 75 times.
268 return bi->offset == 0 || bi->blk->data[bi->offset - 1] == '\n';
47 }
48
49 static inline bool block_iter_is_eol(const BlockIter *bi)
50 {
51 const Block *blk = bi->blk;
52 size_t offset = bi->offset;
53 if (offset == blk->size) {
54 if (blk->node.next == bi->head) {
55 // EOF
56 return true;
57 }
58 // Normalize
59 blk = BLOCK(blk->node.next);
60 offset = 0;
61 }
62 return blk->data[offset] == '\n';
63 }
64
65 1290 static inline void block_iter_normalize(BlockIter *bi)
66 {
67 1290 const Block *blk = bi->blk;
68
3/4
✓ Branch 0 (2→3) taken 99 times.
✓ Branch 1 (2→5) taken 1191 times.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 99 times.
1290 if (bi->offset == blk->size && blk->node.next != bi->head) {
69 bi->blk = BLOCK(blk->node.next);
70 bi->offset = 0;
71 }
72 1290 }
73
74 size_t block_iter_eat_line(BlockIter *bi);
75 size_t block_iter_next_line(BlockIter *bi);
76 size_t block_iter_prev_line(BlockIter *bi);
77 size_t block_iter_next_char(BlockIter *bi, CodePoint *up);
78 size_t block_iter_prev_char(BlockIter *bi, CodePoint *up);
79 size_t block_iter_next_column(BlockIter *bi);
80 size_t block_iter_prev_column(BlockIter *bi);
81 size_t block_iter_bol(BlockIter *bi);
82 size_t block_iter_eol(BlockIter *bi);
83 size_t block_iter_skip_blanks_fwd(BlockIter *bi);
84 size_t block_iter_skip_blanks_bwd(BlockIter *bi);
85 bool block_iter_find_non_empty_line_bwd(BlockIter *bi);
86 void block_iter_back_bytes(BlockIter *bi, size_t count);
87 void block_iter_skip_bytes(BlockIter *bi, size_t count);
88 void block_iter_goto_offset(BlockIter *bi, size_t offset);
89 void block_iter_goto_line(BlockIter *bi, size_t line);
90 size_t block_iter_get_offset(const BlockIter *bi) WARN_UNUSED_RESULT;
91 size_t block_iter_get_char(const BlockIter *bi, CodePoint *up) WARN_UNUSED_RESULT;
92 char *block_iter_get_bytes(const BlockIter *bi, size_t len) WARN_UNUSED_RESULT;
93 StringView block_iter_get_line_with_nl(BlockIter *bi);
94
95 // Like block_iter_get_line_with_nl(), but excluding the newline
96 374 static inline StringView block_iter_get_line(BlockIter *bi)
97 {
98 374 StringView line = block_iter_get_line_with_nl(bi);
99 374 line.length -= (line.length > 0); // Trim the newline (if any)
100 374 return line;
101 }
102
103 // Like block_iter_get_line(), but always returning whole lines
104 14 static inline StringView get_current_line(BlockIter tmp)
105 {
106 14 block_iter_bol(&tmp);
107 14 return block_iter_get_line(&tmp);
108 }
109
110 // Like get_current_line(), but returning a struct that also includes the
111 // cursor offset (relative to BOL)
112 52 static inline CurrentLineRef get_current_line_and_offset(BlockIter tmp)
113 {
114 52 size_t offset = block_iter_bol(&tmp);
115 104 return (CurrentLineRef) {
116 52 .line = block_iter_get_line(&tmp),
117 .cursor_offset = offset,
118 };
119 }
120
121 #endif
122