initial add
This commit is contained in:
2
.cell/cell.toml
Normal file
2
.cell/cell.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[compilation.macOS]
|
||||
LDFLAGS = "-framework CoreFoundation -framework CoreServices"
|
||||
132
dmon.c
Normal file
132
dmon.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "cell.h"
|
||||
|
||||
#define DMON_IMPL
|
||||
#include "dmon.h"
|
||||
|
||||
// Define the file event structure and completion queue
|
||||
typedef struct {
|
||||
dmon_action action;
|
||||
char rootdir[256];
|
||||
char filepath[256];
|
||||
char oldfilepath[256];
|
||||
} FileEvent;
|
||||
|
||||
typedef struct EventNode {
|
||||
FileEvent event;
|
||||
struct EventNode *next;
|
||||
} EventNode;
|
||||
|
||||
typedef struct {
|
||||
EventNode *head;
|
||||
EventNode *tail;
|
||||
} CompletionQueue;
|
||||
|
||||
CompletionQueue completionQueue = { NULL, NULL };
|
||||
|
||||
// Helper functions for the completion queue
|
||||
void enqueue_event(FileEvent event) {
|
||||
EventNode *node = malloc(sizeof(EventNode));
|
||||
node->event = event;
|
||||
node->next = NULL;
|
||||
|
||||
if (completionQueue.tail) {
|
||||
completionQueue.tail->next = node;
|
||||
} else {
|
||||
completionQueue.head = node;
|
||||
}
|
||||
completionQueue.tail = node;
|
||||
}
|
||||
|
||||
int dequeue_event(FileEvent *event) {
|
||||
if (!completionQueue.head) {
|
||||
return 0; // No event
|
||||
}
|
||||
EventNode *node = completionQueue.head;
|
||||
*event = node->event;
|
||||
completionQueue.head = node->next;
|
||||
if (!completionQueue.head) {
|
||||
completionQueue.tail = NULL;
|
||||
}
|
||||
free(node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void watch_cb(dmon_watch_id id, dmon_action action, const char *rootdir, const char *filepath, const char *oldfilepath, void *user)
|
||||
{
|
||||
FileEvent event;
|
||||
event.action = action;
|
||||
strncpy(event.rootdir, rootdir, sizeof(event.rootdir) - 1);
|
||||
strncpy(event.filepath, filepath, sizeof(event.filepath) - 1);
|
||||
if (oldfilepath) {
|
||||
strncpy(event.oldfilepath, oldfilepath, sizeof(event.oldfilepath) - 1);
|
||||
} else {
|
||||
event.oldfilepath[0] = '\0';
|
||||
}
|
||||
enqueue_event(event); // Add event to completion queue
|
||||
}
|
||||
|
||||
static dmon_watch_id watched = {0};
|
||||
|
||||
JSValue js_dmon_watch(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
if (watched.id)
|
||||
return JS_ThrowReferenceError(js, "Already watching a directory.");
|
||||
|
||||
watched = dmon_watch(".", watch_cb, DMON_WATCHFLAGS_RECURSIVE, NULL);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_dmon_unwatch(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
if (!watched.id)
|
||||
return JS_ThrowReferenceError(js, "Not watching a directory.");
|
||||
|
||||
dmon_unwatch(watched);
|
||||
watched.id = 0;
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
JSValue js_dmon_poll(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) {
|
||||
FileEvent event;
|
||||
while (dequeue_event(&event)) {
|
||||
if (!JS_IsFunction(js, argv[0])) continue;
|
||||
JSValue jsevent = JS_NewObject(js);
|
||||
JSValue action;
|
||||
switch(event.action) {
|
||||
case DMON_ACTION_CREATE:
|
||||
action = JS_NewAtomString(js, "create");
|
||||
break;
|
||||
case DMON_ACTION_DELETE:
|
||||
action = JS_NewAtomString(js, "delete");
|
||||
break;
|
||||
case DMON_ACTION_MODIFY:
|
||||
action = JS_NewAtomString(js, "modify");
|
||||
break;
|
||||
case DMON_ACTION_MOVE:
|
||||
action = JS_NewAtomString(js, "move");
|
||||
break;
|
||||
}
|
||||
JS_SetPropertyStr(js, jsevent, "action", action);
|
||||
JS_SetPropertyStr(js, jsevent, "root", JS_NewString(js, event.rootdir));
|
||||
JS_SetPropertyStr(js, jsevent, "file", JS_NewString(js, event.filepath));
|
||||
JS_SetPropertyStr(js, jsevent, "old", JS_NewString(js, event.oldfilepath));
|
||||
JS_Call(js, argv[0], JS_NULL, 1, &jsevent);
|
||||
JS_FreeValue(js, jsevent);
|
||||
}
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_dmon_funcs[] = {
|
||||
JS_CFUNC_DEF("watch", 0, js_dmon_watch),
|
||||
JS_CFUNC_DEF("unwatch", 0, js_dmon_unwatch),
|
||||
JS_CFUNC_DEF("poll", 1, js_dmon_poll)
|
||||
};
|
||||
|
||||
CELL_USE_INIT(
|
||||
JSValue export = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js, export, js_dmon_funcs, sizeof(js_dmon_funcs)/sizeof(JSCFunctionListEntry));
|
||||
|
||||
dmon_init();
|
||||
|
||||
return export;
|
||||
)
|
||||
Reference in New Issue
Block a user