From 0d6dbfe292c61b935edd3e367c9032b27c850efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Sun, 19 Jul 2015 12:37:52 +0200 Subject: text: slight cleanup, add a few comments --- text.c | 39 ++++++++++++++++++++++----------------- text.h | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/text.c b/text.c index 520211e..fee7aef 100644 --- a/text.c +++ b/text.c @@ -34,6 +34,7 @@ #include "text.h" #include "util.h" +/* Allocate buffers holding the actual file content in junks of size: */ #define BUFFER_SIZE (1 << 20) /* Files smaller than this value are copied on load, larger ones are mmap(2)-ed * directely. Hence the former can be truncated, while doing so on the latter @@ -50,18 +51,19 @@ struct Regex { */ typedef struct Buffer Buffer; struct Buffer { - size_t size; /* maximal capacity */ - size_t len; /* current used length / insertion position */ - char *data; /* actual data */ + size_t size; /* maximal capacity */ + size_t len; /* current used length / insertion position */ + char *data; /* actual data */ enum { MMAP, MALLOC} type; /* type of allocation */ - Buffer *next; /* next junk */ + Buffer *next; /* next junk */ }; /* A piece holds a reference (but doesn't itself store) a certain amount of data. * All active pieces chained together form the whole content of the document. * At the beginning there exists only one piece, spanning the whole document. - * Upon insertion/delition new pieces will be created to represent the changes. - * Generally pieces are never destroytxt, but kept around to peform undo/redo operations. + * Upon insertion/deletion new pieces will be created to represent the changes. + * Generally pieces are never destroyed, but kept around to peform undo/redo + * operations. */ struct Piece { Text *text; /* text to which this piece belongs */ @@ -69,11 +71,11 @@ struct Piece { Piece *global_prev; /* double linked list in order of allocation, */ Piece *global_next; /* used to free individual pieces */ const char *data; /* pointer into a Buffer holding the data */ - size_t len; /* the lenght in number of bytes starting from content */ + size_t len; /* the length in number of bytes of the data */ }; -/* used to transform a global position (byte offset starting from the begining - * of the text) into an offset relative to piece. +/* used to transform a global position (byte offset starting from the beginning + * of the text) into an offset relative to a piece. */ typedef struct { Piece *piece; /* piece holding the location */ @@ -129,7 +131,7 @@ struct Text { Action *last_action; /* the last action added to the tree, chronologically */ Action *saved_action; /* the last action at the time of the save operation */ size_t size; /* current file content size in bytes */ - struct stat info; /* stat as proped on load time */ + struct stat info; /* stat as probed at load time */ LineCache lines; /* mapping between absolute pos in bytes and logical line breaks */ enum TextNewLine newlines; /* which type of new lines does the file use */ }; @@ -1081,13 +1083,15 @@ bool text_delete(Text *txt, size_t pos, size_t len) { size_t off = loc.off; if (cache_delete(txt, p, off, len)) return true; - size_t cur; // how much has already been deleted - bool midway_start = false, midway_end = false; Change *c = change_alloc(txt, pos); if (!c) return false; - Piece *before, *after; // unmodified pieces before / after deletion point - Piece *start, *end; // span which is removed + + bool midway_start = false, midway_end = false; /* split pieces? */ + Piece *before, *after; /* unmodified pieces before/after deletion point */ + Piece *start, *end; /* span which is removed */ + size_t cur; /* how much has already been deleted */ + if (off == p->len) { /* deletion starts at a piece boundry */ cur = 0; @@ -1102,6 +1106,7 @@ bool text_delete(Text *txt, size_t pos, size_t len) { if (!before) return false; } + /* skip all pieces which fall into deletion range */ while (cur < len) { p = p->next; @@ -1112,8 +1117,8 @@ bool text_delete(Text *txt, size_t pos, size_t len) { /* deletion stops at a piece boundry */ end = p; after = p->next; - } else { // cur > len - /* deletion stops midway through a piece */ + } else { + /* cur > len: deletion stops midway through a piece */ midway_end = true; end = p; after = piece_alloc(txt); @@ -1527,7 +1532,7 @@ bool text_range_valid(Filerange *r) { } size_t text_range_size(Filerange *r) { - return text_range_valid(r) ? r-> end - r->start : 0; + return text_range_valid(r) ? r->end - r->start : 0; } Filerange text_range_empty(void) { diff --git a/text.h b/text.h index 16b4a45..3b6344b 100644 --- a/text.h +++ b/text.h @@ -15,9 +15,13 @@ typedef struct { size_t start, end; /* range in bytes from start of the file */ } Filerange; +/* test whether the given range is valid (start <= end) */ bool text_range_valid(Filerange*); +/* get the size of the range (end-start) or zero if invalid */ size_t text_range_size(Filerange*); +/* create an empty / invalid range of size zero */ Filerange text_range_empty(void); +/* merge two ranges into a new one which contains both of them */ Filerange text_range_union(Filerange*, Filerange*); typedef struct Text Text; @@ -36,17 +40,23 @@ typedef struct { text_iterator_valid(&it); \ text_iterator_next(&it)) -Text *text_load(const char *file); +/* create a text instance populated with the given file content, if `filename' + * is NULL the text starts out empty */ +Text *text_load(const char *filename); /* file information at time of load or last save */ struct stat text_stat(Text*); +/* insert `len' bytes starting from `data' at `pos' which has to be + * in the interval [0, text_size(txt)] */ bool text_insert(Text*, size_t pos, const char *data, size_t len); +/* delete `len' bytes starting from `pos' */ bool text_delete(Text*, size_t pos, size_t len); +/* mark the current text state, such that it can be {un,re}done */ void text_snapshot(Text*); -/* undo/redos to the last snapshoted state. returns the position where - * the change occured or EPOS if nothing could be undo/redo. */ +/* undo/redo to the last snapshotted state. returns the position where + * the change occured or EPOS if nothing could be {un,re}done. */ size_t text_undo(Text*); size_t text_redo(Text*); -/* move chronlogically to the count earlier/later revision */ +/* move chronlogically to the `count' earlier/later revision */ size_t text_earlier(Text*, int count); size_t text_later(Text*, int count); /* restore the text to the state closest to the time given */ @@ -57,7 +67,12 @@ time_t text_state(Text*); size_t text_pos_by_lineno(Text*, size_t lineno); size_t text_lineno_by_pos(Text*, size_t pos); +/* set `buf' to the byte found at `pos' and return true, if `pos' is invalid + * false is returned and `buf' is left unmodified */ bool text_byte_get(Text*, size_t pos, char *buf); +/* store at most `len' bytes starting from `pos' into `buf', the return value + * indicates how many bytes were copied into `buf'. WARNING buf will not be + * NUL terminated. */ size_t text_bytes_get(Text*, size_t pos, size_t len, char *buf); Iterator text_iterator_get(Text*, size_t pos); @@ -78,13 +93,20 @@ bool text_iterator_char_next(Iterator*, char *c); bool text_iterator_char_prev(Iterator*, char *c); typedef const char* Mark; +/* mark position `pos', the returned mark can be used to later retrieve + * the same text segment */ Mark text_mark_set(Text*, size_t pos); +/* get position of mark in bytes from start of the file or EPOS if + * the mark is not/no longer valid e.g. if the corresponding text was + * deleted. If the change is later restored the mark will once again be + * valid. */ size_t text_mark_get(Text*, Mark); /* get position of change denoted by index, where 0 indicates the most recent */ size_t text_history_get(Text*, size_t index); - +/* return the size in bytes of the whole text */ size_t text_size(Text*); +/* query whether the text contains any unsaved modifications */ bool text_modified(Text*); /* which type of new lines does the text use? */ @@ -95,10 +117,16 @@ enum TextNewLine { enum TextNewLine text_newline_type(Text*); -bool text_save(Text*, const char *file); +/* save the whole text to the given `filename'. Return true if succesful. + * In which case an implicit snapshot is taken. The save might associate a + * new inode to file. */ +bool text_save(Text*, const char *filename); bool text_range_save(Text*, Filerange*, const char *file); +/* write the text content to the given file descriptor `fd'. Return the + * number of bytes written or -1 in case there was an error. */ ssize_t text_write(Text*, int fd); ssize_t text_range_write(Text*, Filerange*, int fd); +/* release all ressources associated with this text instance */ void text_free(Text*); typedef struct Regex Regex; -- cgit v1.2.3