diff options
author | Arun Prakash Jana <engineerarun@gmail.com> | 2017-04-01 17:32:58 +0530 |
---|---|---|
committer | Arun Prakash Jana <engineerarun@gmail.com> | 2017-04-01 17:32:58 +0530 |
commit | 8f18c4049cccd4a01353e5a5c09ea05061c8d0a3 (patch) | |
tree | 3354d6043933670c198ae411e9cc0e1ccca02d83 | |
parent | 7be7a6d215e861ebec0cae2334b4b4b86d3742da (diff) | |
download | nnn-8f18c4049cccd4a01353e5a5c09ea05061c8d0a3.tar.gz |
An optimized dirname()
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | nnn.c | 95 |
2 files changed, 99 insertions, 6 deletions
@@ -72,9 +72,15 @@ I chose to fork because: - Associate PDF files with [zathura](https://pwmt.org/projects/zathura/) - Use environment variable `NNN_FALLBACK_OPENER` to open other non-associated files - Removed `less` as default file opener (there is no universal standalone opener utility) -- Compilation - - Use `-O3` for compilation, fixed warnings +- Optimizations + - Efficient memory usage, 0 malloc() + - Complete redundant buffer removal + - All frequently used local chunks now static + - Removed some redundant string allocation and manipulation + - Simplified some roundabout procedures + - `-O3` level optimization, warning fixes - Added compilation flag `-march=native` + - Massive binary size optimization - Remove generated config.h on `make clean` - strip the final binary @@ -7,7 +7,6 @@ #include <dirent.h> #include <errno.h> #include <fcntl.h> -#include <libgen.h> #include <limits.h> #include <locale.h> #include <regex.h> @@ -93,9 +92,9 @@ typedef struct entry { static struct entry *dents; static int ndents, cur; static int idle; -static char *opener = NULL; -static char *fallback_opener = NULL; -static char *copier = NULL; +static char *opener; +static char *fallback_opener; +static char *copier; static const char* size_units[] = {"B", "K", "M", "G", "T", "P", "E", "Z", "Y"}; /* @@ -144,6 +143,29 @@ xrealloc(void *p, size_t size) return p; } +/* + * The poor man's implementation of memrchr(). + * We are only looking for '/' in this program. + */ +static void * +xmemrchr(const void *s, int c, size_t n) +{ + unsigned char *p; + unsigned char ch = (unsigned char)c; + + if (!s || !n) + return NULL; + + p = (unsigned char *)s + n - 1; + + while(n--) + if ((*p--) == ch) + return ++p; + + return NULL; +} + +#if 0 /* Some implementations of dirname(3) may modify `path' and some * return a pointer inside `path'. */ static char * @@ -159,6 +181,71 @@ xdirname(const char *path) strlcpy(out, p, sizeof(out)); return out; } +#endif + +/* + * The following dirname() implementation does not + * change the input. We use a copy of the original. + * + * Modified from the glibc (GNU LGPL) version. + */ +static char * +xdirname(const char *path) +{ + static char name[PATH_MAX]; + char *last_slash; + + strlcpy(name, path, PATH_MAX); + + /* Find last '/'. */ + last_slash = name != NULL ? strrchr(name, '/') : NULL; + + if (last_slash != NULL && last_slash != name && last_slash[1] == '\0') { + /* Determine whether all remaining characters are slashes. */ + char *runp; + + for (runp = last_slash; runp != name; --runp) + if (runp[-1] != '/') + break; + + /* The '/' is the last character, we have to look further. */ + if (runp != name) + last_slash = xmemrchr(name, '/', runp - name); + } + + if (last_slash != NULL) { + /* Determine whether all remaining characters are slashes. */ + char *runp; + + for (runp = last_slash; runp != name; --runp) + if (runp[-1] != '/') + break; + + /* Terminate the name. */ + if (runp == name) { + /* The last slash is the first character in the string. + We have to return "/". As a special case we have to + return "//" if there are exactly two slashes at the + beginning of the string. See XBD 4.10 Path Name + Resolution for more information. */ + if (last_slash == name + 1) + ++last_slash; + else + last_slash = name + 1; + } else + last_slash = runp; + + last_slash[0] = '\0'; + } else { + /* This assignment is ill-designed but the XPG specs require to + return a string containing "." in any case no directory part + is found and so a static and constant string is required. */ + name[0] = '.'; + name[1] = '\0'; + } + + return name; +} static void spawn(char *file, char *arg, char *dir) |