summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bftw.c43
-rw-r--r--color.c56
2 files changed, 60 insertions, 39 deletions
diff --git a/bftw.c b/bftw.c
index 47ab8b5..d310263 100644
--- a/bftw.c
+++ b/bftw.c
@@ -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) {
diff --git a/color.c b/color.c
index b1d430e..6dda4cd 100644
--- a/color.c
+++ b/color.c
@@ -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);
+ }
}