|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
A text file in memory for the viewer and the editor: a gap buffer over the caller's bytes and an index of its lines. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>Go to the source code of this file.
Data Structures | |
| struct | text_buf_t |
| The buffer. Read it through the functions; the fields are open only so the caller can place it. More... | |
Enumerations | |
| enum | text_buf_err_t { TEXT_BUF_OK = 0 , TEXT_BUF_ARG = 1 , TEXT_BUF_TOO_LARGE = 2 , TEXT_BUF_TOO_MANY = 3 , TEXT_BUF_NOT_TEXT = 4 , TEXT_BUF_FULL = 5 } |
| What a load or an edit answers. The numbers are stable. More... | |
| enum | text_eol_t { TEXT_EOL_LF = 0 , TEXT_EOL_CRLF = 1 , TEXT_EOL_CR = 2 , TEXT_EOL_KINDS = 3 } |
| A kind of line end. The numbers are stable. More... | |
Functions | |
| 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. | |
| 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. | |
| size_t | text_buf_prev (const text_buf_t *tb, size_t pos) |
The start of the unit before 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_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. | |
A text file in memory for the viewer and the editor: a gap buffer over the caller's bytes and an index of its lines.
The buffer holds the file's bytes as they are. Nothing is converted: a line end stays LF, CR LF or CR as the file has it, a code point the text faces do not draw stays as its bytes, and a NUL after the first TEXT_BUF_PROBE bytes stays a NUL. A leading UTF-8 BOM (byte order mark, EF BB BF) is taken off at load, remembered, and written back in front by text_buf_read(); it is no cell and no cursor position. Serialising an unchanged buffer gives the loaded file byte for byte.
Limits:
A unit is what the cursor steps over and DEL removes: one well-formed UTF-8 sequence, one byte that starts none (drawn as one '?' cell, as gfx_utf8_next() reads it), or one line end, CR LF included. Every unit of a line is one cell, except a tab, which reaches to the next multiple of TEXT_BUF_TAB cells. A line is drawn wrapped at a width in cells: a unit that does not fit the row starts the next one, and a tab that does not fit ends at the row's last cell. A cell number is row * width + column, so it counts along the wrapped line.
Line ends: the file's kind is that of its first line end, LF for a file without one. ENTER inserts that kind. Where it would join a neighbouring lone CR or LF into one CR LF, ENTER inserts CR LF instead, so it always adds one line. A text with two kinds is mixed (text_buf_mixed()); it is saved as it is.
Every edit moves the revision on, and it wraps after 2^32 edits: compare it for equality only. The dirty flag is set by an edit and cleared by a load and by text_buf_saved().
Every buffer comes from the caller: no heap, no stdio. Pure C.
SPDX-License-Identifier: MIT
| enum text_buf_err_t |
What a load or an edit answers. The numbers are stable.
| Enumerator | |
|---|---|
| TEXT_BUF_OK | done |
| TEXT_BUF_ARG | a NULL, or a code point no text holds |
| TEXT_BUF_TOO_LARGE | a file over the room text_buf_room() gives |
| TEXT_BUF_TOO_MANY | more line ends than the index holds |
| TEXT_BUF_NOT_TEXT | a NUL in the first TEXT_BUF_PROBE bytes |
| TEXT_BUF_FULL | the text is at its most bytes |
| enum text_eol_t |
| 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. |