diff options
-rw-r--r-- | bftw.c | 43 | ||||
-rw-r--r-- | color.c | 56 |
2 files changed, 60 insertions, 39 deletions
@@ -38,26 +38,28 @@ */ typedef struct { char *str; - size_t size; + size_t length; + size_t capacity; } dynstr; /** Initialize a dynstr. */ static void dynstr_init(dynstr *dstr) { dstr->str = NULL; - dstr->size = 0; + dstr->length = 0; + dstr->capacity = 0; } -/** Grow a dynstr to the gizen size if necessary. */ -static int dynstr_grow(dynstr *dstr, size_t size) { - if (size > dstr->size) { - size_t new_size = 3*(size + 1)/2; - char *new_str = realloc(dstr->str, new_size); +/** Grow a dynstr to the given capacity if necessary. */ +static int dynstr_grow(dynstr *dstr, size_t length) { + if (length >= dstr->capacity) { + size_t new_capacity = 3*(length + 1)/2; + char *new_str = realloc(dstr->str, new_capacity); if (!new_str) { return -1; } dstr->str = new_str; - dstr->size = new_size; + dstr->capacity = new_capacity; } return 0; @@ -66,12 +68,13 @@ static int dynstr_grow(dynstr *dstr, size_t size) { /** Concatenate a string to a dynstr at the given position. */ static int dynstr_concat(dynstr *dstr, size_t pos, const char *more) { size_t morelen = strlen(more); - size_t needed = pos + morelen + 1; - if (dynstr_grow(dstr, needed) != 0) { + size_t length = pos + morelen; + if (dynstr_grow(dstr, length) != 0) { return -1; } memcpy(dstr->str + pos, more, morelen + 1); + dstr->length = length; return 0; } @@ -100,6 +103,8 @@ struct dircache_entry { /** Reference count. */ size_t refcount; + /** The length of the directory's name. */ + size_t namelen; /** The directory's name. */ char name[]; }; @@ -132,6 +137,7 @@ static dircache_entry *dircache_add(dircache *cache, dircache_entry *parent, con entry->lru_prev = entry->lru_next = NULL; entry->dir = NULL; entry->refcount = 1; + entry->namelen = pathsize - 1; memcpy(entry->name, path, pathsize); while (parent) { @@ -222,26 +228,27 @@ static DIR *dircache_entry_open(dircache *cache, dircache_entry *entry, dynstr * } // First, reserve enough space for the path - size_t pathsize = 1; // Terminating '\0' + size_t pathlen = 0; dircache_entry *parent = entry; do { - size_t namelen = strlen(parent->name); - pathsize += namelen; + size_t namelen = parent->namelen; + pathlen += namelen; if (namelen > 0 && parent->name[namelen - 1] != '/') { - ++pathsize; + ++pathlen; } parent = parent->parent; } while (parent); - if (dynstr_grow(path, pathsize) != 0) { + if (dynstr_grow(path, pathlen) != 0) { return NULL; } + path->length = pathlen; // Now, build the path backwards while looking for a parent - char *segment = path->str + pathsize - 1; + char *segment = path->str + pathlen; *segment = '\0'; int fd = AT_FDCWD; @@ -249,7 +256,7 @@ static DIR *dircache_entry_open(dircache *cache, dircache_entry *entry, dynstr * parent = entry; while (true) { - size_t namelen = strlen(parent->name); + size_t namelen = parent->namelen; bool needs_slash = namelen > 0 && parent->name[namelen - 1] != '/'; segment -= namelen; @@ -407,7 +414,7 @@ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, int flags, void *ptr) { goto done; } - size_t pathlen = strlen(path.str); + size_t pathlen = path.length; struct dirent *de; while ((de = readdir(dir)) != NULL) { @@ -20,7 +20,10 @@ typedef struct ext_color ext_color; struct ext_color { const char *ext; + size_t len; + const char *color; + ext_color *next; }; @@ -184,6 +187,7 @@ color_table *parse_colors(char *ls_colors) { ext = malloc(sizeof(ext_color)); if (ext) { ext->ext = key + 1; + ext->len = strlen(ext->ext); ext->color = value; ext->next = colors->ext_list; colors->ext_list = ext; @@ -216,8 +220,7 @@ static const char *file_color(const color_table *colors, const char *filename, c size_t namelen = strlen(filename); for (ext_color *ext = colors->ext_list; ext; ext = ext->next) { - size_t extlen = strlen(ext->ext); - if (namelen >= extlen && strncmp(filename + namelen - extlen, ext->ext, extlen) == 0) { + if (namelen >= ext->len && memcmp(filename + namelen - ext->len, ext->ext, ext->len) == 0) { color = ext->color; break; } @@ -271,24 +274,15 @@ static const char *file_color(const color_table *colors, const char *filename, c return color; } -static void printf_color(const color_table *colors, const char *color, const char *format, ...) { - if (color) { - printf("\033[%sm", color); - } - - va_list args; - va_start(args, format); - vprintf(format, args); - va_end(args); - - if (color) { - printf("\033[%sm", colors->reset); - } +static void print_esc(const char *esc) { + fputs("\033[", stdout); + fputs(esc, stdout); + fputs("m", stdout); } void pretty_print(const color_table *colors, const char *fpath, const struct stat *sb) { if (!colors) { - printf("%s\n", fpath); + puts(fpath); return; } @@ -299,14 +293,34 @@ void pretty_print(const color_table *colors, const char *fpath, const struct sta filename = fpath + strlen(fpath); } - int dirlen = filename - fpath; - printf_color(colors, colors->dir, "%.*s", dirlen, fpath); + if (colors->dir) { + print_esc(colors->dir); + } + fwrite(fpath, 1, filename - fpath, stdout); + if (colors->dir) { + print_esc(colors->reset); + } const char *color = file_color(colors, filename, sb); - printf_color(colors, color, "%s", filename); - printf("\n"); + if (color) { + print_esc(color); + } + fputs(filename, stdout); + if (color) { + print_esc(colors->reset); + } + fputs("\n", stdout); } void free_colors(color_table *colors) { - free(colors); + if (colors) { + ext_color *ext = colors->ext_list; + while (ext) { + ext_color *saved = ext; + ext = ext->next; + free(saved); + } + + free(colors); + } } |