Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort by datetime #39

Merged
merged 2 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}

Loading