Code cleanup, replaced fisher-yates shuffle with worse, but much simpler
shuffle.
This commit is contained in:
parent
0a1258a747
commit
331a004dff
103
bb.c
103
bb.c
@ -58,7 +58,6 @@ typedef enum {
|
||||
SORT_CTIME = 'c',
|
||||
SORT_ATIME = 'a',
|
||||
SORT_RANDOM = 'r',
|
||||
|
||||
RSORT_NAME = 'N',
|
||||
RSORT_SIZE = 'S',
|
||||
RSORT_PERM = 'P',
|
||||
@ -77,12 +76,12 @@ typedef enum {
|
||||
typedef struct entry_s {
|
||||
struct entry_s *next, **atme;
|
||||
char *name, *linkname;
|
||||
// TODO: inline only the relevant fields:
|
||||
struct stat info;
|
||||
mode_t linkedmode;
|
||||
int refcount : 2; // Should only be between 0-2
|
||||
int no_esc : 1;
|
||||
int link_no_esc : 1;
|
||||
int shufflepos;
|
||||
char fullname[1]; // Must be last
|
||||
} entry_t;
|
||||
|
||||
@ -102,12 +101,12 @@ typedef enum { BB_NOP = 0, BB_INVALID, BB_REFRESH, BB_QUIT } bb_result_t;
|
||||
// Functions
|
||||
static void update_term_size(int sig);
|
||||
static void init_term(void);
|
||||
static void cleanup_and_exit(int sig);
|
||||
static void close_term(void);
|
||||
static void cleanup_and_exit(int sig);
|
||||
static void* memcheck(void *p);
|
||||
static int run_cmd_on_selection(bb_t *bb, const char *cmd);
|
||||
static int fputs_escaped(FILE *f, const char *str, const char *color);
|
||||
static const char *color_of(mode_t mode);
|
||||
static const char* color_of(mode_t mode);
|
||||
static void render(bb_t *bb, int lazy);
|
||||
static int compare_files(void *r, const void *v1, const void *v2);
|
||||
static int find_file(bb_t *bb, const char *name);
|
||||
@ -116,7 +115,7 @@ static int select_file(bb_t *bb, entry_t *e);
|
||||
static int deselect_file(bb_t *bb, entry_t *e);
|
||||
static void set_cursor(bb_t *bb, int i);
|
||||
static void set_scroll(bb_t *bb, int i);
|
||||
static entry_t *load_entry(const char *path);
|
||||
static entry_t* load_entry(const char *path);
|
||||
static void populate_files(bb_t *bb, const char *path);
|
||||
static void sort_files(bb_t *bb);
|
||||
static bb_result_t execute_cmd(bb_t *bb, const char *cmd);
|
||||
@ -170,14 +169,6 @@ void init_term(void)
|
||||
fputs(T_OFF(T_WRAP), tty_out);
|
||||
}
|
||||
|
||||
void cleanup_and_exit(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
close_term();
|
||||
unlink(cmdfilename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void close_term(void)
|
||||
{
|
||||
if (tty_out) {
|
||||
@ -197,6 +188,14 @@ void close_term(void)
|
||||
signal(SIGWINCH, SIG_DFL);
|
||||
}
|
||||
|
||||
void cleanup_and_exit(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
close_term();
|
||||
unlink(cmdfilename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void* memcheck(void *p)
|
||||
{
|
||||
if (!p) err("Allocation failure");
|
||||
@ -266,7 +265,7 @@ int fputs_escaped(FILE *f, const char *str, const char *color)
|
||||
return escaped;
|
||||
}
|
||||
|
||||
const char *color_of(mode_t mode)
|
||||
const char* color_of(mode_t mode)
|
||||
{
|
||||
if (S_ISDIR(mode))
|
||||
return DIR_COLOR;
|
||||
@ -532,30 +531,30 @@ int compare_files(void *v, const void *v1, const void *v2)
|
||||
int d2 = S_ISDIR(f2->info.st_mode) || (S_ISLNK(f2->info.st_mode) && S_ISDIR(f2->linkedmode));
|
||||
if (d1 != d2) return d2 - d1;
|
||||
}
|
||||
if (sort == SORT_NAME) {
|
||||
const char *p1 = f1->name, *p2 = f2->name;
|
||||
while (*p1 && *p2) {
|
||||
char c1 = *p1, c2 = *p2;
|
||||
if ('A' <= c1 && 'Z' <= c1) c1 = c1 - 'A' + 'a';
|
||||
if ('A' <= c2 && 'Z' <= c2) c2 = c2 - 'A' + 'a';
|
||||
diff = (c1 - c2);
|
||||
if ('0' <= c1 && c1 <= '9' && '0' <= c2 && c2 <= '9') {
|
||||
long n1 = strtol(p1, (char**)&p1, 10);
|
||||
long n2 = strtol(p2, (char**)&p2, 10);
|
||||
diff = (int)(p1 - f1->name) - (int)(p2 - f2->name);
|
||||
if (diff != 0)
|
||||
return diff*sign;
|
||||
if (n1 != n2)
|
||||
return (n1 > n2 ? 1 : -1)*sign;
|
||||
} else if (diff) {
|
||||
return diff*sign;
|
||||
} else {
|
||||
++p1; ++p2;
|
||||
}
|
||||
}
|
||||
return (*p1 - *p2)*sign;
|
||||
}
|
||||
switch (sort) {
|
||||
case SORT_NAME: {
|
||||
const char *p1 = f1->name, *p2 = f2->name;
|
||||
while (*p1 && *p2) {
|
||||
char c1 = *p1, c2 = *p2;
|
||||
if ('A' <= c1 && 'Z' <= c1) c1 = c1 - 'A' + 'a';
|
||||
if ('A' <= c2 && 'Z' <= c2) c2 = c2 - 'A' + 'a';
|
||||
diff = (c1 - c2);
|
||||
if ('0' <= c1 && c1 <= '9' && '0' <= c2 && c2 <= '9') {
|
||||
long n1 = strtol(p1, (char**)&p1, 10);
|
||||
long n2 = strtol(p2, (char**)&p2, 10);
|
||||
diff = (int)(p1 - f1->name) - (int)(p2 - f2->name);
|
||||
if (diff != 0)
|
||||
return diff*sign;
|
||||
if (n1 != n2)
|
||||
return (n1 > n2 ? 1 : -1)*sign;
|
||||
} else if (diff) {
|
||||
return diff*sign;
|
||||
} else {
|
||||
++p1; ++p2;
|
||||
}
|
||||
}
|
||||
return (*p1 - *p2)*sign;
|
||||
}
|
||||
case SORT_PERM:
|
||||
return -((f1->info.st_mode & 0x3FF) - (f2->info.st_mode & 0x3FF))*sign;
|
||||
case SORT_SIZE:
|
||||
@ -575,6 +574,8 @@ int compare_files(void *v, const void *v1, const void *v2)
|
||||
return f1->info.st_atimespec.tv_nsec > f2->info.st_atimespec.tv_nsec ? -sign : sign;
|
||||
else
|
||||
return f1->info.st_atimespec.tv_sec > f2->info.st_atimespec.tv_sec ? -sign : sign;
|
||||
case SORT_RANDOM:
|
||||
return f1->shufflepos - f2->shufflepos;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -666,7 +667,7 @@ void set_scroll(bb_t *bb, int newscroll)
|
||||
if (bb->cursor < 0) bb->cursor = 0;
|
||||
}
|
||||
|
||||
entry_t *load_entry(const char *path)
|
||||
entry_t* load_entry(const char *path)
|
||||
{
|
||||
ssize_t linkpathlen = -1;
|
||||
char linkbuf[PATH_MAX];
|
||||
@ -771,6 +772,9 @@ void populate_files(bb_t *bb, const char *path)
|
||||
closedir(dir);
|
||||
free(selecthash);
|
||||
if (bb->nfiles == 0) err("No files found (not even '..')");
|
||||
// TODO: this may have some weird aliasing issues, but eh, it's simple and effective
|
||||
for (int i = 0; i < bb->nfiles; i++)
|
||||
bb->files[i]->shufflepos = rand();
|
||||
|
||||
sort_files(bb);
|
||||
if (samedir) {
|
||||
@ -794,29 +798,6 @@ void sort_files(bb_t *bb)
|
||||
{
|
||||
ino_t cursor_inode = bb->files[bb->cursor]->info.st_ino;
|
||||
qsort_r(&bb->files[1], (size_t)(bb->nfiles-1), sizeof(entry_t*), bb, compare_files);
|
||||
if (bb->options['s'] == SORT_RANDOM) {
|
||||
entry_t **files = &bb->files[1];
|
||||
int ndirs = 0, nents = bb->nfiles - 1;
|
||||
if (!bb->options['i']) {
|
||||
for (int i = 0; i < nents; i++) {
|
||||
if (S_ISDIR(bb->files[i]->info.st_mode)
|
||||
|| (S_ISLNK(bb->files[i]->info.st_mode) && S_ISDIR(bb->files[i]->linkedmode)))
|
||||
++ndirs;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ndirs - 1; i++) {
|
||||
int j = i + rand() / (RAND_MAX / (ndirs - 1 - i));
|
||||
entry_t *tmp = files[j];
|
||||
files[j] = files[i];
|
||||
files[i] = tmp;
|
||||
}
|
||||
for (int i = ndirs; i < nents - 1; i++) {
|
||||
int j = i + rand() / (RAND_MAX / (nents - 1 - i));
|
||||
entry_t *tmp = files[j];
|
||||
files[j] = files[i];
|
||||
files[i] = tmp;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < bb->nfiles; i++) {
|
||||
if (bb->files[i]->info.st_ino == cursor_inode) {
|
||||
set_cursor(bb, i);
|
||||
|
Loading…
Reference in New Issue
Block a user