aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Arun Prakash Jana <engineerarun@gmail.com>2017-04-01 17:32:58 +0530
committerGravatar Arun Prakash Jana <engineerarun@gmail.com>2017-04-01 17:32:58 +0530
commit8f18c4049cccd4a01353e5a5c09ea05061c8d0a3 (patch)
tree3354d6043933670c198ae411e9cc0e1ccca02d83
parent7be7a6d215e861ebec0cae2334b4b4b86d3742da (diff)
downloadnnn-8f18c4049cccd4a01353e5a5c09ea05061c8d0a3.tar.gz
An optimized dirname()
-rw-r--r--README.md10
-rw-r--r--nnn.c95
2 files changed, 99 insertions, 6 deletions
diff --git a/README.md b/README.md
index 8be8d23..20a9f11 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/nnn.c b/nnn.c
index a6a3777..81652a7 100644
--- a/nnn.c
+++ b/nnn.c
@@ -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)