Skip to content

Commit

Permalink
Merge pull request #39 from qpfiffer/sort_by_datetime
Browse files Browse the repository at this point in the history
Sort by datetime
  • Loading branch information
qpfiffer authored Nov 17, 2023
2 parents 46d8ca7 + 174b30b commit 8680c30
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ clean:
$(CC) $(CFLAGS) $(INCLUDES) -c -fPIC $<

lib: $(REALNAME)
$(REALNAME): shithouse.o
$(REALNAME): vector.o shithouse.o
$(CC) $(CFLAGS) $(LIB_INCLUDES) $(INCLUDES) -o $(REALNAME) -shared -Wl,-soname,${SONAME} $^ $(LIBFLAGS)

install: all
Expand Down
65 changes: 65 additions & 0 deletions c_include/vector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// vim: noet ts=4 sw=4
#pragma once
#include <stdlib.h>

/* xXx STRUCT=vector xXx
* xXx DESCRIPTION=A simple vector object. Auto-expands and whatever. xXx
* xXx item_size=The maximum size of each item. xXx
* xXx max_size=Used internally to track the current vector's maximum number of elements. xXx
* xXx count=Used internally to track the current vector's current count of items. xXx
* xXx *items=The actual memory used for the items stored. xXx
*/
typedef struct vector {
const size_t item_size;
size_t max_size;
size_t count;
void *items;
} vector;

/* xXx FUNCTION=vector_new xXx
* xXx DESCRIPTION=Creates a new vector object. xXx
* xXx RETURNS=A new vector object. xXx
* xXx item_size=The maximum size of each item. xXx
* xXx initial_element_count=If you know your amount of objects ahead of time, set this accordingly. Otherwise just guess. The closer you get the fewer mallocs will happen. xXx
*/
vector *vector_new(const size_t item_size, const size_t initial_element_count);

/* xXx FUNCTION=vector_append xXx
* xXx DESCRIPTION=Adds a new element to a vector. xXx
* xXx RETURNS=1 on success. xXx
* xXx *vec=The vector to add the new item to. xXx
* xXx *item=The item to add to the vector. xXx
* xXx item_size=The size of the item to be added. xXx
*/
int vector_append(vector *vec, const void *item, const size_t item_size);

/* xXx FUNCTION=vector_append_ptr xXx
* xXx DESCRIPTION=Similar to vector_append but copies just the pointer value, not what it points to. xXx
* xXx RETURNS=1 on success. xXx
* xXx *vec=The vector to add the pointer to. xXx
* xXx *pointer=The item to add to the vector. xXx
*/
int vector_append_ptr(vector *vec, const void *pointer);

/* xXx FUNCTION=vector_get xXx
* xXx DESCRIPTION=Gets the nth element of the given vector. xXx
* xXx RETURNS=A constant pointer to the nth item in the vector. xXx
* xXx *vec=The vector to get the item from. xXx
* xXx i=The item you want to retrieve. xXx
*/
const void *vector_get(const vector *vec, const unsigned int i);

/* xXx FUNCTION=vector_reverse xXx
* xXx DESCRIPTION=Reverses the vector, from beginning to end. xXx
* xXx RETURNS=1 on success. xXx
* xXx *vec=The vector to be reversed. xXx
*/
int vector_reverse(vector *vec);

/* xXx FUNCTION=vector_free xXx
* xXx DESCRIPTION=Cleans up and removes a vector's allocated memory. xXx
* xXx RETURNS=Nothing. xXx
* xXx *to_free=The vector to free. xXx
*/
void vector_free(vector *to_free);

89 changes: 68 additions & 21 deletions c_src/shithouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,103 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdint.h>

#include "shithouse.h"
#include "vector.h"

struct dir_iterator {
uint64_t iter;
char *path;
vector *files;
};

struct file {
struct stat sb;
char name[256];
};

static int ctime_compare(const void *item_a, const void *item_b) {
const struct file *file_a = (struct file *)item_a;
const struct file *file_b = (struct file *)item_b;

return file_a->sb.st_ctim.tv_sec < file_b->sb.st_ctim.tv_sec;
}

static int l_dir(lua_State *L) {
/* Straight out of the docs */
/* https://www.lua.org/pil/29.1.html */
const char *path = luaL_checkstring(L, 1);

/* create a userdatum to store a DIR address */
DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *));
struct dir_iterator *d = (struct dir_iterator *)lua_newuserdata(L,
sizeof(struct dir_iterator));
d->path = strdup(path);

d->iter = 0;
d->files = vector_new(sizeof(struct file), 2048);

/* set its metatable */
luaL_getmetatable(L, "LuaBook.dir");
lua_setmetatable(L, -2);

/* try to open the given directory */
*d = opendir(path);
if (*d == NULL) /* error opening the directory? */
luaL_error(L, "cannot open %s: %s", path, strerror(errno));
DIR *dir = opendir(path);
if (!dir) {
luaL_error(L, "Cannot open dir %s: %s", path, strerror(errno));
}

struct dirent *entry = NULL;
while ((entry = readdir(dir))) {
char pathname[1024] = {0};
int ret = 0;
struct file fil = {0};

if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
continue;
}

strncpy(fil.name, entry->d_name, sizeof(fil.name));
snprintf(pathname, sizeof(pathname), "%s/%s", path, entry->d_name);

ret = stat(pathname, &fil.sb);
if (ret) {
/* TODO: Clear out buffers, manage memory, return nothing. */
luaL_error(L, "Cannot stat %s: %s", pathname, strerror(errno));
}

vector_append(d->files, &fil, sizeof(struct file));
}

qsort(d->files->items, d->files->count, d->files->item_size, &(ctime_compare));

closedir(dir);

/* creates and returns the iterator function
(its sole upvalue, the directory userdatum,
is already on the stack top */
lua_pushcclosure(L, dir_iter, 1);
return 1;
}

static int dir_iter(lua_State *L) {
DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex(1));
struct dirent *entry;
while ((entry = readdir(d)) != NULL) {
if (entry->d_name[0] != '.')
break;
}

if (entry) {
lua_pushstring(L, entry->d_name);
struct dir_iterator *dirs = (struct dir_iterator *)lua_touserdata(L, lua_upvalueindex(1));
if (dirs->iter < dirs->files->count) {
const struct file *fil = vector_get(dirs->files, dirs->iter);
lua_pushstring(L, fil->name);
dirs->iter++;
return 1;
}
else return 0; /* no more values to return */

return 0;
}

static int dir_gc(lua_State *L) {
DIR *d = *(DIR **)lua_touserdata(L, 1);
if (d) closedir(d);
struct dir_iterator *d = (struct dir_iterator *)lua_touserdata(L, 1);
if (d->files)
vector_free(d->files);
if (d->path)
free(d->path);
return 0;
}

Expand Down
110 changes: 110 additions & 0 deletions c_src/vector.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// vim: noet ts=4 sw=4
#include <assert.h>
#include <string.h>
#include "vector.h"

#define nth(I) (void *)(vec->items + (I * vec->item_size))

vector *vector_new(const size_t item_size, const size_t initial_element_count) {
vector _vec = {
.item_size = item_size,
.max_size = initial_element_count,
.count = 0,
.items = calloc(1, initial_element_count * item_size + 1)
};

vector *to_return = calloc(1, sizeof(vector));
memcpy(to_return, &_vec, sizeof(vector));

return to_return;
}

inline int vector_append(vector *vec, const void *item, const size_t item_size) {
if (vec == NULL)
return 0;

if (item_size > vec->item_size)
return 0;

if (vec->count == vec->max_size) {
vec->max_size *= 2;
void *array = realloc(vec->items, vec->max_size * vec->item_size + 1);
if (!array)
return 0;
vec->items = array;
}

if (item_size != 0 && item != NULL) {
memcpy(nth(vec->count), item, item_size);
memset(nth(vec->count) + item_size, '\0', sizeof(char));
} else {
/* Just zero out the memory so we can check for NULLs. */
memset(nth(vec->count), 0, vec->item_size);
}
vec->count++;
return 1;
}

inline int vector_append_ptr(vector *vec, const void *pointer) {
if (vec == NULL)
return 0;

if (vec->item_size != sizeof(pointer))
return 0;

if (vec->count == vec->max_size) {
vec->max_size *= 2;
void *array = realloc(vec->items, (vec->max_size * vec->item_size));
if (!array)
return 0;
vec->items = array;
}

memcpy(nth(vec->count), &pointer, sizeof(void *));
vec->count++;
return 1;
}

inline const void *vector_get(const vector *vec, const unsigned int i) {
if (vec == NULL)
return NULL;
if (i > vec->max_size)
return NULL;
return nth(i);
}

int vector_reverse(vector *vec) {
if (vec == NULL)
return 0;

const size_t item_size = vec->item_size;
unsigned int i = 0;

unsigned char *buf = malloc(item_size);
if (!buf)
return 0;

for (;i < (unsigned int)(vec->count / 2); i++) {
const void *item = vector_get(vec, i);
const unsigned int offset = vec->count - i - 1;
if (!memcpy(buf, vector_get(vec, offset), item_size))
return 0;

if (!memcpy(nth(offset), item, item_size))
return 0;

if (!memcpy(nth(i), buf, item_size))
return 0;
}
free(buf);

return 1;
}

void vector_free(vector *vec) {
if (vec == NULL)
return;
free(vec->items);
free(vec);
}

0 comments on commit 8680c30

Please sign in to comment.