mirror of
https://github.com/jarun/nnn.git
synced 2024-11-28 05:41:31 +00:00
An optimized dirname()
This commit is contained in:
parent
7be7a6d215
commit
8f18c4049c
10
README.md
10
README.md
|
@ -72,9 +72,15 @@ I chose to fork because:
|
||||||
- Associate PDF files with [zathura](https://pwmt.org/projects/zathura/)
|
- Associate PDF files with [zathura](https://pwmt.org/projects/zathura/)
|
||||||
- Use environment variable `NNN_FALLBACK_OPENER` to open other non-associated files
|
- 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)
|
- Removed `less` as default file opener (there is no universal standalone opener utility)
|
||||||
- Compilation
|
- Optimizations
|
||||||
- Use `-O3` for compilation, fixed warnings
|
- 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`
|
- Added compilation flag `-march=native`
|
||||||
|
- Massive binary size optimization
|
||||||
- Remove generated config.h on `make clean`
|
- Remove generated config.h on `make clean`
|
||||||
- strip the final binary
|
- strip the final binary
|
||||||
|
|
||||||
|
|
95
nnn.c
95
nnn.c
|
@ -7,7 +7,6 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
@ -93,9 +92,9 @@ typedef struct entry {
|
||||||
static struct entry *dents;
|
static struct entry *dents;
|
||||||
static int ndents, cur;
|
static int ndents, cur;
|
||||||
static int idle;
|
static int idle;
|
||||||
static char *opener = NULL;
|
static char *opener;
|
||||||
static char *fallback_opener = NULL;
|
static char *fallback_opener;
|
||||||
static char *copier = NULL;
|
static char *copier;
|
||||||
static const char* size_units[] = {"B", "K", "M", "G", "T", "P", "E", "Z", "Y"};
|
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;
|
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
|
/* Some implementations of dirname(3) may modify `path' and some
|
||||||
* return a pointer inside `path'. */
|
* return a pointer inside `path'. */
|
||||||
static char *
|
static char *
|
||||||
|
@ -159,6 +181,71 @@ xdirname(const char *path)
|
||||||
strlcpy(out, p, sizeof(out));
|
strlcpy(out, p, sizeof(out));
|
||||||
return 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
|
static void
|
||||||
spawn(char *file, char *arg, char *dir)
|
spawn(char *file, char *arg, char *dir)
|
||||||
|
|
Loading…
Reference in a new issue