]> Sergey Matveev's repositories - nnn.git/commitdiff
An optimized dirname()
authorArun Prakash Jana <engineerarun@gmail.com>
Sat, 1 Apr 2017 12:02:58 +0000 (17:32 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sat, 1 Apr 2017 12:02:58 +0000 (17:32 +0530)
README.md
nnn.c

index 8be8d230f24b458bb6815a5dd3733f65126b2188..20a9f113dc423b043f03a142de61e3bd6186c28a 100644 (file)
--- 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 a6a377767654d45ab43e04331378e10972750e11..81652a76f549c5ca4712a2926364ddef158d8902 100644 (file)
--- 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)