|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
A text file in memory: the gap buffer, the line index, the units and the cells (text_buf.h). More...
Data Structures | |
| struct | cells_t |
| Where a walk along a line's cells is. More... | |
Functions | |
| static uint8_t | at (const text_buf_t *tb, size_t i) |
Byte i of the text, read across the gap. | |
| static size_t | decode (const text_buf_t *tb, size_t i, uint32_t *cp) |
Decode the UTF-8 sequence at i, as gfx_utf8_next() does. | |
| static size_t | encode (uint32_t cp, uint8_t *out) |
Encode cp as UTF-8. | |
| static void | move_gap (text_buf_t *tb, size_t p) |
Move the gap to text offset p. | |
| static size_t | entry_pos (uint32_t e) |
| The text offset an index entry holds. | |
| static text_eol_t | entry_kind (uint32_t e) |
| The kind of line end an index entry holds. | |
| static uint32_t | entry (size_t pos, text_eol_t kind) |
| An index entry. | |
| static size_t | eol_bytes (text_eol_t kind) |
| The bytes of a kind of line end. | |
| static bool | ends_at (const text_buf_t *tb, size_t i, text_eol_t *kind) |
Whether a line ends at the byte at i, and of which kind. | |
| static bool | index_all (text_buf_t *tb) |
| Count the line ends of the whole text into the index. | |
| static void | edit (text_buf_t *tb, size_t p, size_t d, const uint8_t *ins, size_t s) |
Take d bytes at p and put the s bytes of ins there, keeping the index. | |
| static void | empty (text_buf_t *tb) |
| Empty the text and set the most bytes it may take. | |
| text_buf_err_t | text_buf_init (text_buf_t *tb, uint8_t *mem, size_t cap, uint32_t *ends, size_t ends_cap) |
An empty text over mem, LF line ends, no BOM. | |
| size_t | text_buf_room (const text_buf_t *tb) |
| The largest file text_buf_load() and text_buf_load_done() take. | |
| uint8_t * | text_buf_load_area (text_buf_t *tb) |
| Where a loader puts a file's bytes in place, text_buf_room() of them at most, before text_buf_load_done(). The text held is lost. | |
| text_buf_err_t | text_buf_load_done (text_buf_t *tb, size_t len) |
Take the len bytes a loader put at text_buf_load_area() as the text: the BOM, the line ends and their kind, the NUL test. | |
| text_buf_err_t | text_buf_load (text_buf_t *tb, const void *bytes, size_t len) |
| Copy a file into the buffer and take it, as text_buf_load_done(). | |
| size_t | text_buf_size (const text_buf_t *tb) |
| Bytes text_buf_read() gives: the text and the BOM. | |
| size_t | text_buf_read (const text_buf_t *tb, size_t at_, void *out, size_t n) |
Serialised bytes at to at + n of the file, the BOM in front: a save writes the file in pieces with this. | |
| size_t | text_buf_len (const text_buf_t *tb) |
| Text bytes, the BOM not counted. | |
| uint8_t | text_buf_byte (const text_buf_t *tb, size_t pos) |
Byte pos of the text. | |
| size_t | text_buf_lines (const text_buf_t *tb) |
| Lines of the text: its line ends and one. | |
| size_t | text_buf_line_start (const text_buf_t *tb, size_t line) |
Where line line starts. | |
| static size_t | line_end (const text_buf_t *tb, size_t line) |
Where line line's text ends, before its line end. | |
| size_t | text_buf_line_len (const text_buf_t *tb, size_t line) |
Bytes of line line without its line end. | |
| const char * | text_buf_line (text_buf_t *tb, size_t line, size_t *len) |
Line line as one run of bytes, without its line end. Moves the gap out of the line when it is in it; the text is unchanged. | |
| size_t | text_buf_line_of (const text_buf_t *tb, size_t pos) |
The line text offset pos is on. | |
| uint32_t | text_buf_cp (const text_buf_t *tb, size_t pos, size_t *bytes) |
The code point of the unit at pos. | |
| size_t | text_buf_next (const text_buf_t *tb, size_t pos) |
The start of the unit after the one at pos. | |
| bool | text_buf_is_unit (const text_buf_t *tb, size_t pos) |
Whether a unit starts at pos: not inside a UTF-8 sequence and not between the CR and the LF of a CR LF. | |
| size_t | text_buf_prev (const text_buf_t *tb, size_t pos) |
The start of the unit before pos. | |
| static void | cells_start (const text_buf_t *tb, size_t line, cells_t *w) |
Start a walk over line line. | |
| static void | cells_place (const text_buf_t *tb, cells_t *w, unsigned width) |
| Place the unit at w->pos: its first cell and the one after it, starting a row where it does not fit. | |
| static void | cells_step (const text_buf_t *tb, cells_t *w) |
| Step the walk past the unit cells_place() placed. | |
| static size_t | cells_end (const cells_t *w, unsigned width) |
| The cell after a walk's last unit. | |
| size_t | text_buf_rows (const text_buf_t *tb, size_t line, unsigned width) |
Rows line line takes, wrapped at width cells. | |
| void | text_buf_cell_of (const text_buf_t *tb, size_t pos, unsigned width, size_t *line, size_t *cell) |
The line and the cell at which the unit at pos is drawn. | |
| size_t | text_buf_pos_at (const text_buf_t *tb, size_t line, size_t cell, unsigned width) |
The unit drawn over cell cell of line line: the cursor position a tap there gives. | |
| size_t | text_buf_cursor (const text_buf_t *tb) |
| The cursor, a text offset at a unit's start. | |
| void | text_buf_set_cursor (text_buf_t *tb, size_t pos) |
Put the cursor at pos, moved back to the start of the unit it is in; past the end, at the end. | |
| bool | text_buf_left (text_buf_t *tb) |
| Move the cursor one unit left. | |
| bool | text_buf_right (text_buf_t *tb) |
| Move the cursor one unit right. | |
| text_buf_err_t | text_buf_insert (text_buf_t *tb, uint32_t cp) |
Insert code point cp at the cursor, which goes after it. | |
| text_buf_err_t | text_buf_insert_eol (text_buf_t *tb) |
| Insert a line end at the cursor, which goes to the new line. | |
| bool | text_buf_delete_before (text_buf_t *tb) |
| Remove the unit before the cursor (backspace). | |
| bool | text_buf_delete_after (text_buf_t *tb) |
| Remove the unit at the cursor (delete). | |
| text_eol_t | text_buf_eol (const text_buf_t *tb) |
| The file's kind of line end, which ENTER inserts. | |
| bool | text_buf_mixed (const text_buf_t *tb) |
| Whether the text holds line ends of two kinds or three. | |
| bool | text_buf_bom (const text_buf_t *tb) |
| Whether the file starts with a BOM. | |
| bool | text_buf_dirty (const text_buf_t *tb) |
| Whether the text was edited since the load or text_buf_saved(). | |
| void | text_buf_saved (text_buf_t *tb) |
| Note that the text as it is now is on the card. | |
| uint32_t | text_buf_revision (const text_buf_t *tb) |
| The revision: moves on with each edit and load; compare it for equality only. | |
Variables | |
| static const uint8_t | k_bom [TEXT_BUF_BOM_LEN] = {0xEFu, 0xBBu, 0xBFu} |
| The UTF-8 BOM. | |
A text file in memory: the gap buffer, the line index, the units and the cells (text_buf.h).
The text is mem[0, gap_at) and mem[gap_at + gap_len, cap): the gap sits where the last edit was, so typing at one place moves no byte, and a cursor that goes elsewhere moves the gap with the next edit.
The index holds, per line end, the text offset of the line after it. An edit at offset p that takes d bytes and puts s in their place can change the line ends at the bytes p - 1 to p + s only: a CR at p - 1 may meet an LF that comes to p, the LF at p + s may lose or gain the CR in front of it, and every other line end depends on bytes the edit did not touch. So an edit scans those bytes again, replaces their entries, and moves every later entry by s - d. An edit is at most 4 bytes each way, so the stretch holds at most 6 line ends; the cost of an edit is one pass over the later entries, 65,536 at most.
SPDX-License-Identifier: MIT
|
static |
Byte i of the text, read across the gap.
| tb | The buffer. |
| i | Text offset under tb->len. |
|
static |
The cell after a walk's last unit.
| w | The walk at the line's end. |
| width | Cells of a row. |
|
static |
Place the unit at w->pos: its first cell and the one after it, starting a row where it does not fit.
| tb | The buffer. |
| w | The walk; w->pos under w->end. |
| width | Cells of a row; 0 does not wrap. |
|
static |
Start a walk over line line.
| tb | The buffer. |
| line | Line index up to tb->n_ends. |
| w | Out: the walk. |
|
static |
Step the walk past the unit cells_place() placed.
| tb | The buffer. |
| w | The walk. |
|
static |
Decode the UTF-8 sequence at i, as gfx_utf8_next() does.
| tb | The buffer. |
| i | Text offset under tb->len. |
| cp | Out: the code point, '?' for a byte that starts no sequence. |
|
static |
Take d bytes at p and put the s bytes of ins there, keeping the index.
The caller has checked the room and the index: a line end comes in only through text_buf_insert_eol(), which checks for one more entry, and no other edit adds one.
| tb | The buffer. |
| p | Text offset of a unit's start. |
| d | Bytes to take, EDIT_MAX at most. |
| ins | Bytes to put; NULL with s 0. |
| s | Their count, EDIT_MAX at most. |
|
static |
Empty the text and set the most bytes it may take.
| tb | The buffer, its memory and index set. |
|
static |
Encode cp as UTF-8.
| cp | A code point up to U+10FFFF. |
| out | Out: 4 bytes of room. |
|
static |
Whether a line ends at the byte at i, and of which kind.
The LF of a CR LF ends it; the CR in front does not.
| tb | The buffer. |
| i | Text offset under tb->len. |
| kind | Out: the kind when a line ends there. |
i.
|
static |
An index entry.
| pos | The offset of the line after the line end. |
| kind | The kind of line end. |
|
static |
The kind of line end an index entry holds.
| e | The entry. |
|
static |
The text offset an index entry holds.
| e | The entry. |
|
static |
The bytes of a kind of line end.
| kind | The kind. |
|
static |
Count the line ends of the whole text into the index.
| tb | The buffer. |
|
static |
Where line line's text ends, before its line end.
| tb | The buffer. |
| line | Line index up to tb->n_ends. |
|
static |
Move the gap to text offset p.
| tb | The buffer. |
| p | Text offset up to tb->len. |
| bool text_buf_bom | ( | const text_buf_t * | tb | ) |
Whether the file starts with a BOM.
| tb | The buffer. |
| uint8_t text_buf_byte | ( | const text_buf_t * | tb, |
| size_t | pos ) |
Byte pos of the text.
| tb | The buffer. |
| pos | Text offset. |
| void text_buf_cell_of | ( | const text_buf_t * | tb, |
| size_t | pos, | ||
| unsigned | width, | ||
| size_t * | line, | ||
| size_t * | cell ) |
The line and the cell at which the unit at pos is drawn.
At a line's end that is the cell after its last unit, on the last row (column width when that row is full).
| tb | The buffer. |
| pos | Text offset of a unit's start. |
| width | Cells of a row; 0 does not wrap. |
| line | Out: line index; or NULL. |
| cell | Out: row * width + column; or NULL. |
| uint32_t text_buf_cp | ( | const text_buf_t * | tb, |
| size_t | pos, | ||
| size_t * | bytes ) |
The code point of the unit at pos.
| tb | The buffer. |
| pos | Text offset of a unit's start. |
| bytes | Out: the unit's bytes, 0 at the end; or NULL. |
| size_t text_buf_cursor | ( | const text_buf_t * | tb | ) |
The cursor, a text offset at a unit's start.
| tb | The buffer. |
| bool text_buf_delete_after | ( | text_buf_t * | tb | ) |
Remove the unit at the cursor (delete).
| tb | The buffer. |
| bool text_buf_delete_before | ( | text_buf_t * | tb | ) |
Remove the unit before the cursor (backspace).
| tb | The buffer. |
| bool text_buf_dirty | ( | const text_buf_t * | tb | ) |
Whether the text was edited since the load or text_buf_saved().
| tb | The buffer. |
| text_eol_t text_buf_eol | ( | const text_buf_t * | tb | ) |
The file's kind of line end, which ENTER inserts.
| tb | The buffer. |
| text_buf_err_t text_buf_init | ( | text_buf_t * | tb, |
| uint8_t * | mem, | ||
| size_t | cap, | ||
| uint32_t * | ends, | ||
| size_t | ends_cap ) |
An empty text over mem, LF line ends, no BOM.
| tb | The buffer. |
| mem | Bytes for the text; their count is the most it holds, up to TEXT_BUF_FILE_MAX. |
| cap | Count of mem. |
| ends | The line index, one entry per line end. |
| ends_cap | Count of ends; above TEXT_BUF_ENDS_MAX counts as that. |
| text_buf_err_t text_buf_insert | ( | text_buf_t * | tb, |
| uint32_t | cp ) |
Insert code point cp at the cursor, which goes after it.
| tb | The buffer. |
| cp | A tab, or U+0020 and above but U+007F to U+009F, the surrogates and above U+10FFFF. |
| text_buf_err_t text_buf_insert_eol | ( | text_buf_t * | tb | ) |
Insert a line end at the cursor, which goes to the new line.
| tb | The buffer. |
| bool text_buf_is_unit | ( | const text_buf_t * | tb, |
| size_t | pos ) |
Whether a unit starts at pos: not inside a UTF-8 sequence and not between the CR and the LF of a CR LF.
| tb | The buffer. |
| pos | Text offset. |
| bool text_buf_left | ( | text_buf_t * | tb | ) |
Move the cursor one unit left.
| tb | The buffer. |
| size_t text_buf_len | ( | const text_buf_t * | tb | ) |
Text bytes, the BOM not counted.
| tb | The buffer. |
| const char * text_buf_line | ( | text_buf_t * | tb, |
| size_t | line, | ||
| size_t * | len ) |
Line line as one run of bytes, without its line end. Moves the gap out of the line when it is in it; the text is unchanged.
| tb | The buffer. |
| line | Line index, from 0. |
| len | Out: bytes of the line. |
tb; NULL past the last line or for a NULL. | size_t text_buf_line_len | ( | const text_buf_t * | tb, |
| size_t | line ) |
Bytes of line line without its line end.
| tb | The buffer. |
| line | Line index, from 0. |
| size_t text_buf_line_of | ( | const text_buf_t * | tb, |
| size_t | pos ) |
The line text offset pos is on.
| tb | The buffer. |
| pos | Text offset. |
| size_t text_buf_line_start | ( | const text_buf_t * | tb, |
| size_t | line ) |
Where line line starts.
| tb | The buffer. |
| line | Line index, from 0. |
| size_t text_buf_lines | ( | const text_buf_t * | tb | ) |
Lines of the text: its line ends and one.
| tb | The buffer. |
| text_buf_err_t text_buf_load | ( | text_buf_t * | tb, |
| const void * | bytes, | ||
| size_t | len ) |
Copy a file into the buffer and take it, as text_buf_load_done().
| tb | The buffer. |
| bytes | The file; NULL with len 0 is an empty file. |
| len | Its bytes. |
| uint8_t * text_buf_load_area | ( | text_buf_t * | tb | ) |
Where a loader puts a file's bytes in place, text_buf_room() of them at most, before text_buf_load_done(). The text held is lost.
| tb | The buffer. |
| text_buf_err_t text_buf_load_done | ( | text_buf_t * | tb, |
| size_t | len ) |
Take the len bytes a loader put at text_buf_load_area() as the text: the BOM, the line ends and their kind, the NUL test.
Refused, the buffer is empty as text_buf_init() leaves it. The revision moves on either way.
| tb | The buffer. |
| len | Bytes of the file. |
| bool text_buf_mixed | ( | const text_buf_t * | tb | ) |
Whether the text holds line ends of two kinds or three.
| tb | The buffer. |
| size_t text_buf_next | ( | const text_buf_t * | tb, |
| size_t | pos ) |
The start of the unit after the one at pos.
| tb | The buffer. |
| pos | Text offset of a unit's start. |
| size_t text_buf_pos_at | ( | const text_buf_t * | tb, |
| size_t | line, | ||
| size_t | cell, | ||
| unsigned | width ) |
The unit drawn over cell cell of line line: the cursor position a tap there gives.
| tb | The buffer. |
| line | Line index, from 0; past the last line, the last. |
| cell | row * width + column. |
| width | Cells of a row; 0 does not wrap. |
| size_t text_buf_prev | ( | const text_buf_t * | tb, |
| size_t | pos ) |
The start of the unit before pos.
| tb | The buffer. |
| pos | Text offset of a unit's start. |
| size_t text_buf_read | ( | const text_buf_t * | tb, |
| size_t | at, | ||
| void * | out, | ||
| size_t | n ) |
Serialised bytes at to at + n of the file, the BOM in front: a save writes the file in pieces with this.
| tb | The buffer. |
| at | Offset in the file. |
| out | Out: the bytes. |
| n | Room in out. |
out: fewer than n at the end, 0 past it. | uint32_t text_buf_revision | ( | const text_buf_t * | tb | ) |
The revision: moves on with each edit and load; compare it for equality only.
| tb | The buffer. |
| bool text_buf_right | ( | text_buf_t * | tb | ) |
Move the cursor one unit right.
| tb | The buffer. |
| size_t text_buf_room | ( | const text_buf_t * | tb | ) |
The largest file text_buf_load() and text_buf_load_done() take.
| tb | The buffer. |
| size_t text_buf_rows | ( | const text_buf_t * | tb, |
| size_t | line, | ||
| unsigned | width ) |
Rows line line takes, wrapped at width cells.
| tb | The buffer. |
| line | Line index, from 0. |
| width | Cells of a row; 0 does not wrap. |
| void text_buf_saved | ( | text_buf_t * | tb | ) |
Note that the text as it is now is on the card.
| tb | The buffer. |
| void text_buf_set_cursor | ( | text_buf_t * | tb, |
| size_t | pos ) |
Put the cursor at pos, moved back to the start of the unit it is in; past the end, at the end.
| tb | The buffer. |
| pos | Text offset. |
| size_t text_buf_size | ( | const text_buf_t * | tb | ) |
Bytes text_buf_read() gives: the text and the BOM.
| tb | The buffer. |