13 typedef uintptr_t Mark
;
15 /** An invalid mark, lookup of which will yield ``EPOS``. */
16 #define EMARK ((Mark)0)
17 /** An invalid position. */
18 #define EPOS ((size_t)-1)
22 size_t start
; /**< Absolute byte position. */
23 size_t end
; /**< Absolute byte position. */
27 * Text object storing the buffer content being edited.
29 typedef struct Text Text
;
30 typedef struct Piece Piece
;
31 typedef struct TextSave TextSave
;
33 /** A contiguous part of the text. */
35 const char *data
; /**< Content, might not be NUL-terminated. */
36 size_t len
; /**< Length in bytes. */
40 * Iterator used to navigate the buffer content.
42 * Captures the position within a Piece.
45 * .. warning:: Any change to the Text will invalidate the iterator state.
46 * .. note:: Should be treated as an opaque type.
50 const char *start
; /**< Start of the piece data. */
51 const char *end
; /**< End of piece data. Addressable range is ``[start, end)``. */
52 const char *text
; /**< Current position within piece. Invariant ``start <= text < end`` holds. */
53 const Piece
*piece
; /**< Internal state of current piece. */
54 size_t pos
; /**< Absolute position in bytes from start of buffer. */
62 * Method used to load existing file content.
65 /** Automatically chose best option. */
68 * Read file content and copy it to an in-memory buffer.
69 * Subsequent changes to the underlying file will have no
70 * effect on this text instance.
73 * .. note:: Load time is linear in the file size.
78 * Memory map the the file from disk. Use file system / virtual memory
79 * subsystem as a caching layer.
81 * .. note:: Load time is (almost) independent of the file size.
82 * .. warning:: Inplace modifications of the underlying file
83 * will be reflected in the current text content.
84 * In particular, truncatenation will raise ``SIGBUS``
85 * and result in data loss.
91 * Create a text instance populated with the given file content.
94 * .. note:: Equivalent to ``text_load_method(filename, TEXT_LOAD_AUTO)``.
97 Text
*text_load(const char *filename
);
98 Text
*text_loadat(int dirfd
, const char *filename
);
100 * Create a text instance populated with the given file content.
102 * @param filename The name of the file to load, if ``NULL`` an empty text is created.
103 * @param method How the file content should be loaded.
104 * @return The new Text object or ``NULL`` in case of an error.
106 * .. note:: When attempting to load a non-regular file, ``errno`` will be set to:
108 * - ``EISDIR`` for a directory.
109 * - ``ENOTSUP`` otherwise.
112 Text
*text_load_method(const char *filename
, enum TextLoadMethod
);
113 Text
*text_loadat_method(int dirfd
, const char *filename
, enum TextLoadMethod
);
114 /** Release all ressources associated with this text instance. */
115 void text_free(Text
*);
121 /** Return the size in bytes of the whole text. */
122 size_t text_size(const Text
*);
124 * Get file information at time of load or last save, whichever happened more
127 * .. note:: If an empty text instance was created using ``text_load(NULL)``
128 * and it has not yet been saved, an all zero ``struct stat`` will
131 * @return See ``stat(2)`` for details.
133 struct stat
text_stat(const Text
*);
134 /** Query whether the text contains any unsaved modifications. */
135 bool text_modified(const Text
*);
142 * Insert data at the given byte position.
144 * @param pos The absolute byte position.
145 * @param data The data to insert.
146 * @param len The length of the data in bytes.
147 * @return Whether the insertion succeeded.
149 bool text_insert(Text
*, size_t pos
, const char *data
, size_t len
);
151 * Delete data at given byte position.
153 * @param pos The absolute byte position.
154 * @param len The number of bytes to delete, starting from ``pos``.
155 * @return Whether the deletion succeeded.
157 bool text_delete(Text
*, size_t pos
, size_t len
);
158 bool text_delete_range(Text
*, const Filerange
*);
159 bool text_printf(Text
*, size_t pos
, const char *format
, ...) __attribute__((format(printf
, 3, 4)));
160 bool text_appendf(Text
*, const char *format
, ...) __attribute__((format(printf
, 2, 3)));
167 * Create a text snapshot, that is a vertice in the history graph.
169 bool text_snapshot(Text
*);
171 * Revert to previous snapshot along the main branch.
173 * .. note:: Takes an implicit snapshot.
175 * @return The position of the first change or ``EPOS``, if already at the
176 * oldest state i.e. there was nothing to undo.
178 size_t text_undo(Text
*);
180 * Reapply an older change along the main brach.
182 * .. note:: Takes an implicit snapshot.
184 * @return The position of the first change or ``EPOS``, if already at the
185 * newest state i.e. there was nothing to redo.
187 size_t text_redo(Text
*);
188 size_t text_earlier(Text
*);
189 size_t text_later(Text
*);
191 * Restore the text to the state closest to the time given
193 size_t text_restore(Text
*, time_t);
195 * Get creation time of current state.
197 * .. note:: TODO: This is currently not the same as the time of the last snapshot.
200 time_t text_state(const Text
*);
206 size_t text_pos_by_lineno(Text
*, size_t lineno
);
207 size_t text_lineno_by_pos(Text
*, size_t pos
);
215 * Get byte stored at ``pos``.
216 * @param pos The absolute position.
217 * @param byte Destination address to store the byte.
218 * @return Whether ``pos`` was valid and ``byte`` updated accordingly.
220 * .. note:: Unlike :c:func:`text_iterator_byte_get()` this function does not
221 * return an artificial NUL byte at EOF.
224 bool text_byte_get(const Text
*, size_t pos
, char *byte
);
226 * Store at most ``len`` bytes starting from ``pos`` into ``buf``.
227 * @param pos The absolute starting position.
228 * @param len The length in bytes.
229 * @param buf The destination buffer.
230 * @return The number of bytes (``<= len``) stored at ``buf``.
232 * .. warning:: ``buf`` will not be NUL terminated.
235 size_t text_bytes_get(const Text
*, size_t pos
, size_t len
, char *buf
);
237 * Fetch text range into newly allocate memory region.
238 * @param pos The absolute starting position.
239 * @param len The length in bytes.
240 * @return A contigious NUL terminated buffer holding the requested range, or
241 * ``NULL`` in error case.
243 * .. warning:: The returned pointer must be freed by the caller.
246 char *text_bytes_alloc0(const Text
*, size_t pos
, size_t len
);
252 Iterator
text_iterator_get(const Text
*, size_t pos
);
253 bool text_iterator_init(const Text
*, Iterator
*, size_t pos
);
254 const Text
*text_iterator_text(const Iterator
*);
255 bool text_iterator_valid(const Iterator
*);
256 bool text_iterator_has_next(const Iterator
*);
257 bool text_iterator_has_prev(const Iterator
*);
258 bool text_iterator_next(Iterator
*);
259 bool text_iterator_prev(Iterator
*);
262 * @defgroup iterator_byte
265 bool text_iterator_byte_get(const Iterator
*, char *b
);
266 bool text_iterator_byte_prev(Iterator
*, char *b
);
267 bool text_iterator_byte_next(Iterator
*, char *b
);
268 bool text_iterator_byte_find_prev(Iterator
*, char b
);
269 bool text_iterator_byte_find_next(Iterator
*, char b
);
272 * @defgroup iterator_code
275 bool text_iterator_codepoint_next(Iterator
*it
, char *c
);
276 bool text_iterator_codepoint_prev(Iterator
*it
, char *c
);
279 * @defgroup iterator_char
282 bool text_iterator_char_next(Iterator
*, char *c
);
283 bool text_iterator_char_prev(Iterator
*, char *c
);
292 * .. note:: Setting a mark to ``text_size`` will always return the
293 * current text size upon lookup.
295 * @param pos The position at which to store the mark.
296 * @return The mark or ``EMARK`` if an invalid position was given.
298 Mark
text_mark_set(Text
*, size_t pos
);
301 * @param mark The mark to look up.
302 * @return The byte position or ``EPOS`` for an invalid mark.
304 size_t text_mark_get(const Text
*, Mark
);
311 * Method used to save the text.
313 enum TextSaveMethod
{
314 /** Automatically chose best option. */
317 * Save file atomically using ``rename(2)``.
319 * Creates a temporary file, restores all important meta data,
320 * before moving it atomically to its final (possibly already
321 * existing) destination using ``rename(2)``. For new files,
322 * permissions are set to ``0666 & ~umask``.
325 * .. warning:: This approach does not work if:
327 * - The file is a symbolic link.
328 * - The file is a hard link.
329 * - File ownership can not be preserved.
330 * - File group can not be preserved.
331 * - Directory permissions do not allow creation of a new file.
332 * - POSXI ACL can not be preserved (if enabled).
333 * - SELinux security context can not be preserved (if enabled).
338 * Overwrite file in place.
340 * .. warning:: I/O failure might cause data loss.
347 * Save the whole text to the given file name.
350 * .. note:: Equivalent to ``text_save_method(filename, TEXT_SAVE_AUTO)``.
353 bool text_save(Text
*, const char *filename
);
354 bool text_saveat(Text
*, int dirfd
, const char *filename
);
356 * Save the whole text to the given file name, using the specified method.
358 bool text_save_method(Text
*, const char *filename
, enum TextSaveMethod
);
359 bool text_saveat_method(Text
*, int dirfd
, const char *filename
, enum TextSaveMethod
);
362 * Setup a sequence of write operations.
364 * The returned ``TextSave`` pointer can be used to write multiple, possibly
365 * non-contigious, file ranges.
367 * .. warning:: For every call to ``text_save_begin`` there must be exactly
368 * one matching call to either ``text_save_commit`` or
369 * ``text_save_cancel`` to release the underlying resources.
372 TextSave
*text_save_begin(Text
*, int dirfd
, const char *filename
, enum TextSaveMethod
);
375 * @return The number of bytes written or ``-1`` in case of an error.
377 ssize_t
text_save_write_range(TextSave
*, const Filerange
*);
379 * Commit changes to disk.
380 * @return Whether changes have been saved.
382 * .. note:: Releases the underlying resources and frees the given ``TextSave``
383 * pointer which must no longer be used.
386 bool text_save_commit(TextSave
*);
388 * Abort a save operation.
390 * .. note:: Does not guarantee to undo the previous writes (they might have been
391 * performed in-place). However, it releases the underlying resources and
392 * frees the given ``TextSave`` pointer which must no longer be used.
395 void text_save_cancel(TextSave
*);
397 * Write whole text content to file descriptor.
398 * @return The number of bytes written or ``-1`` in case of an error.
400 ssize_t
text_write(const Text
*, int fd
);
402 * Write file range to file descriptor.
403 * @return The number of bytes written or ``-1`` in case of an error.
405 ssize_t
text_write_range(const Text
*, const Filerange
*, int fd
);
412 * Check whether ``ptr`` is part of a memory mapped region associated with
413 * this text instance.
415 bool text_mmaped(const Text
*, const char *ptr
);