twn_filewatch.c: file and directory change api, initial support for texture reload
This commit is contained in:
parent
630c6fb5d4
commit
4b2a22bf3c
@ -104,6 +104,7 @@ set(TWN_NONOPT_SOURCE_FILES
|
|||||||
src/twn_input.c include/twn_input.h
|
src/twn_input.c include/twn_input.h
|
||||||
src/twn_camera.c src/twn_camera_c.h
|
src/twn_camera.c src/twn_camera_c.h
|
||||||
src/twn_textures.c src/twn_textures_c.h
|
src/twn_textures.c src/twn_textures_c.h
|
||||||
|
src/twn_filewatch.c src/twn_filewatch_c.h
|
||||||
|
|
||||||
src/rendering/twn_draw.c src/rendering/twn_draw_c.h
|
src/rendering/twn_draw.c src/rendering/twn_draw_c.h
|
||||||
src/rendering/twn_quads.c
|
src/rendering/twn_quads.c
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "twn_main.c"
|
#include "twn_main.c"
|
||||||
#include "twn_textures.c"
|
#include "twn_textures.c"
|
||||||
#include "twn_util.c"
|
#include "twn_util.c"
|
||||||
|
#include "twn_filewatch.c"
|
||||||
|
|
||||||
#include "rendering/twn_circles.c"
|
#include "rendering/twn_circles.c"
|
||||||
#include "rendering/twn_draw.c"
|
#include "rendering/twn_draw.c"
|
||||||
|
171
src/twn_filewatch.c
Normal file
171
src/twn_filewatch.c
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#include "twn_filewatch_c.h"
|
||||||
|
#include "twn_util.h"
|
||||||
|
#include "twn_engine_context_c.h"
|
||||||
|
|
||||||
|
#include <x-watcher.h>
|
||||||
|
#include <stb_ds.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct FilewatchPathToCallback {
|
||||||
|
char *path;
|
||||||
|
FileatchCallback callback;
|
||||||
|
float tick_last_reported;
|
||||||
|
enum FilewatchAction action_pending : 3;
|
||||||
|
bool action_processed : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct FilewatchPathToCallback *filewatch_directories;
|
||||||
|
static struct FilewatchPathToCallback *filewatch_files;
|
||||||
|
/* note: it gets rebuilt on every addition, as api is such */
|
||||||
|
/* TODO: test whether it's possible to miss on update while watcher is being rebuilt */
|
||||||
|
/* we might have to enumerate things, just to make sure */
|
||||||
|
static x_watcher *filewatcher;
|
||||||
|
static SDL_mutex *filewatcher_lock;
|
||||||
|
|
||||||
|
/* TODO: check whether path and p->path match? */
|
||||||
|
static void filewatch_dispatch(XWATCHER_FILE_EVENT event,
|
||||||
|
const char *path,
|
||||||
|
int context,
|
||||||
|
void *additional_data
|
||||||
|
) {
|
||||||
|
(void)additional_data; (void)path;
|
||||||
|
|
||||||
|
enum FilewatchAction action;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case XWATCHER_FILE_CREATED:
|
||||||
|
action = FILEWATCH_ACTION_FILE_CREATED;
|
||||||
|
break;
|
||||||
|
case XWATCHER_FILE_REMOVED:
|
||||||
|
action = FILEWATCH_ACTION_FILE_DELETED;
|
||||||
|
break;
|
||||||
|
case XWATCHER_FILE_MODIFIED:
|
||||||
|
action = FILEWATCH_ACTION_FILE_MODIFIED;
|
||||||
|
break;
|
||||||
|
case XWATCHER_FILE_NONE:
|
||||||
|
case XWATCHER_FILE_OPENED:
|
||||||
|
case XWATCHER_FILE_RENAMED:
|
||||||
|
case XWATCHER_FILE_UNSPECIFIED:
|
||||||
|
case XWATCHER_FILE_ATTRIBUTES_CHANGED:
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LockMutex(filewatcher_lock);
|
||||||
|
|
||||||
|
struct FilewatchPathToCallback *p;
|
||||||
|
|
||||||
|
if (context < 0)
|
||||||
|
p = &filewatch_files[-context - 1];
|
||||||
|
else
|
||||||
|
p = &filewatch_directories[context];
|
||||||
|
|
||||||
|
p->tick_last_reported = ctx.game.frame_number;
|
||||||
|
p->action_processed = false;
|
||||||
|
p->action_pending = action;
|
||||||
|
|
||||||
|
SDL_UnlockMutex(filewatcher_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool filewatcher_rebuild(void) {
|
||||||
|
if (filewatcher)
|
||||||
|
xWatcher_destroy(filewatcher);
|
||||||
|
|
||||||
|
filewatcher = xWatcher_create();
|
||||||
|
if (!filewatcher) {
|
||||||
|
log_warn("Error creating xWatcher instance, no file watching is done");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int const filewatch_directories_len = arrlen(filewatch_directories);
|
||||||
|
for (int i = 0; i < filewatch_directories_len; ++i) {
|
||||||
|
xWatcher_reference ref = {
|
||||||
|
.path = filewatch_directories[i].path,
|
||||||
|
.callback_func = filewatch_dispatch,
|
||||||
|
.context = i,
|
||||||
|
};
|
||||||
|
if (!xWatcher_appendDir(filewatcher, &ref))
|
||||||
|
log_warn("Error watching dir contents: %s", filewatch_directories[i].path);
|
||||||
|
}
|
||||||
|
|
||||||
|
int const filewatch_files_len = arrlen(filewatch_files);
|
||||||
|
for (int i = 0; i < filewatch_files_len; ++i) {
|
||||||
|
xWatcher_reference ref = {
|
||||||
|
.path = filewatch_files[i].path,
|
||||||
|
.callback_func = filewatch_dispatch,
|
||||||
|
.context = -(i + 1), /* in negative range to allow inrefence */
|
||||||
|
};
|
||||||
|
if (!xWatcher_appendDir(filewatcher, &ref))
|
||||||
|
log_warn("Error watching file: %s", filewatch_files[i].path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xWatcher_start(filewatcher)) {
|
||||||
|
log_warn("Error creating xWatcher instance, no file watching is done");
|
||||||
|
xWatcher_destroy(filewatcher);
|
||||||
|
filewatcher = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool filewatch_add_directory(char *dir, FileatchCallback callback) {
|
||||||
|
SDL_assert(dir && callback);
|
||||||
|
|
||||||
|
struct FilewatchPathToCallback const w = {
|
||||||
|
.callback = callback,
|
||||||
|
.path = SDL_strdup(dir),
|
||||||
|
.action_processed = true,
|
||||||
|
.tick_last_reported = ctx.game.frame_number,
|
||||||
|
};
|
||||||
|
arrpush(filewatch_directories, w);
|
||||||
|
|
||||||
|
return filewatcher_rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool filewatch_add_file(char *filepath, FileatchCallback callback) {
|
||||||
|
SDL_assert(filepath && callback);
|
||||||
|
|
||||||
|
struct FilewatchPathToCallback const f = {
|
||||||
|
.callback = callback,
|
||||||
|
.path = SDL_strdup(filepath),
|
||||||
|
.action_processed = true,
|
||||||
|
.tick_last_reported = ctx.game.frame_number,
|
||||||
|
};
|
||||||
|
arrpush(filewatch_files, f);
|
||||||
|
|
||||||
|
return filewatcher_rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void filewatch_poll(void) {
|
||||||
|
SDL_LockMutex(filewatcher_lock);
|
||||||
|
|
||||||
|
int const filewatch_directories_len = arrlen(filewatch_directories);
|
||||||
|
for (int i = 0; i < filewatch_directories_len; ++i) {
|
||||||
|
if (!filewatch_directories[i].action_processed
|
||||||
|
&& (ctx.game.frame_number - filewatch_directories[i].tick_last_reported > FILEWATCH_MODIFIED_TICKS_MERGED)) {
|
||||||
|
SDL_assert(filewatch_directories[i].action_pending != FILEWATCH_ACTION_FILE_NONE);
|
||||||
|
filewatch_directories[i].callback(filewatch_directories[i].path, filewatch_directories[i].action_pending);
|
||||||
|
filewatch_directories[i].action_pending = FILEWATCH_ACTION_FILE_NONE;
|
||||||
|
filewatch_directories[i].action_processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int const filewatch_files_len = arrlen(filewatch_files);
|
||||||
|
for (int i = 0; i < filewatch_files_len; ++i) {
|
||||||
|
if (!filewatch_files[i].action_processed
|
||||||
|
&& (ctx.game.frame_number - filewatch_files[i].tick_last_reported > FILEWATCH_MODIFIED_TICKS_MERGED)) {
|
||||||
|
SDL_assert(filewatch_files[i].action_pending != FILEWATCH_ACTION_FILE_NONE);
|
||||||
|
filewatch_files[i].callback(filewatch_files[i].path, filewatch_files[i].action_pending);
|
||||||
|
filewatch_files[i].action_pending = FILEWATCH_ACTION_FILE_NONE;
|
||||||
|
filewatch_files[i].action_processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_UnlockMutex(filewatcher_lock);
|
||||||
|
}
|
23
src/twn_filewatch_c.h
Normal file
23
src/twn_filewatch_c.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef TWN_FILEWATCH_C_H
|
||||||
|
#define TWN_FILEWATCH_C_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define FILEWATCH_MODIFIED_TICKS_MERGED 10
|
||||||
|
|
||||||
|
enum FilewatchAction {
|
||||||
|
FILEWATCH_ACTION_FILE_NONE,
|
||||||
|
FILEWATCH_ACTION_FILE_CREATED,
|
||||||
|
FILEWATCH_ACTION_FILE_DELETED,
|
||||||
|
FILEWATCH_ACTION_FILE_MODIFIED,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*FileatchCallback)(char const *path, enum FilewatchAction action);
|
||||||
|
|
||||||
|
bool filewatch_add_directory(char *dir, FileatchCallback callback);
|
||||||
|
|
||||||
|
bool filewatch_add_file(char *file, FileatchCallback callback);
|
||||||
|
|
||||||
|
void filewatch_poll(void);
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,6 @@
|
|||||||
#include "twn_loop.h"
|
#include "twn_loop.h"
|
||||||
#include "twn_engine_context_c.h"
|
#include "twn_engine_context_c.h"
|
||||||
|
#include "twn_filewatch_c.h"
|
||||||
#include "twn_input_c.h"
|
#include "twn_input_c.h"
|
||||||
#include "twn_util.h"
|
#include "twn_util.h"
|
||||||
#include "twn_util_c.h"
|
#include "twn_util_c.h"
|
||||||
@ -733,8 +734,6 @@ static void clean_up(void) {
|
|||||||
text_cache_deinit(&ctx.text_cache);
|
text_cache_deinit(&ctx.text_cache);
|
||||||
textures_cache_deinit(&ctx.texture_cache);
|
textures_cache_deinit(&ctx.texture_cache);
|
||||||
|
|
||||||
textures_reset_state();
|
|
||||||
|
|
||||||
arrfree(ctx.render_queue_2d);
|
arrfree(ctx.render_queue_2d);
|
||||||
|
|
||||||
toml_free(ctx.config_table);
|
toml_free(ctx.config_table);
|
||||||
@ -754,6 +753,25 @@ static void reset_state(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void pack_contents_modified(char const *path, enum FilewatchAction action) {
|
||||||
|
log_info("Pack contents invalidated: %s, action: %i", path, action);
|
||||||
|
reset_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: handle .btw packs */
|
||||||
|
static bool try_mounting_root_pack(char *path) {
|
||||||
|
log_info("Mounting %s", path);
|
||||||
|
|
||||||
|
if (!PHYSFS_mount(path, NULL, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
filewatch_add_directory(path, &pack_contents_modified);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int enter_loop(int argc, char **argv) {
|
int enter_loop(int argc, char **argv) {
|
||||||
profile_start("startup");
|
profile_start("startup");
|
||||||
|
|
||||||
@ -795,10 +813,8 @@ int enter_loop(int argc, char **argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PHYSFS_mount(argv[i+1], NULL, true)) {
|
if (!try_mounting_root_pack(argv[i+1]))
|
||||||
CRY_PHYSFS("Data dir mount override failed.");
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
|
||||||
|
|
||||||
data_dir_mounted = true;
|
data_dir_mounted = true;
|
||||||
|
|
||||||
@ -823,10 +839,10 @@ int enter_loop(int argc, char **argv) {
|
|||||||
/* try mouning data folder first, relative to executable root */
|
/* try mouning data folder first, relative to executable root */
|
||||||
char *full_path;
|
char *full_path;
|
||||||
SDL_asprintf(&full_path, "%sdata", ctx.base_dir);
|
SDL_asprintf(&full_path, "%sdata", ctx.base_dir);
|
||||||
if (!PHYSFS_mount(full_path, NULL, true)) {
|
if (!try_mounting_root_pack(full_path)) {
|
||||||
SDL_free(full_path);
|
SDL_free(full_path);
|
||||||
SDL_asprintf(&full_path, "%sdata.btw", ctx.base_dir);
|
SDL_asprintf(&full_path, "%sdata.btw", ctx.base_dir);
|
||||||
if (!PHYSFS_mount(full_path, NULL, true)) {
|
if (!try_mounting_root_pack(full_path)) {
|
||||||
SDL_free(full_path);
|
SDL_free(full_path);
|
||||||
CRY_PHYSFS("Cannot find data.btw or data directory in root. Please create them or specify with --data-dir parameter.");
|
CRY_PHYSFS("Cannot find data.btw or data directory in root. Please create them or specify with --data-dir parameter.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -857,6 +873,7 @@ int enter_loop(int argc, char **argv) {
|
|||||||
reset_state();
|
reset_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filewatch_poll();
|
||||||
main_loop();
|
main_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +308,8 @@ static void update_texture_rects_in_atlas(TextureCache *cache, stbrp_rect *rects
|
|||||||
|
|
||||||
|
|
||||||
void textures_cache_init(TextureCache *cache, SDL_Window *window) {
|
void textures_cache_init(TextureCache *cache, SDL_Window *window) {
|
||||||
|
SDL_zero(*cache);
|
||||||
|
|
||||||
cache->window = window;
|
cache->window = window;
|
||||||
sh_new_arena(cache->hash);
|
sh_new_arena(cache->hash);
|
||||||
|
|
||||||
@ -581,4 +583,6 @@ size_t textures_get_num_atlases(const TextureCache *cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void textures_reset_state(void) {
|
void textures_reset_state(void) {
|
||||||
|
textures_cache_deinit(&ctx.texture_cache);
|
||||||
|
textures_cache_init(&ctx.texture_cache, ctx.window);
|
||||||
}
|
}
|
||||||
|
44
third-party/x-watcher/x-watcher.h
vendored
44
third-party/x-watcher/x-watcher.h
vendored
@ -37,7 +37,7 @@ typedef struct xWatcher_reference {
|
|||||||
void *additional_data;
|
void *additional_data;
|
||||||
} xWatcher_reference;
|
} xWatcher_reference;
|
||||||
|
|
||||||
struct file {
|
typedef struct xWatcher_file {
|
||||||
// just the file name alone
|
// just the file name alone
|
||||||
char *name;
|
char *name;
|
||||||
// used for adding (additional) context in the handler (if needed)
|
// used for adding (additional) context in the handler (if needed)
|
||||||
@ -50,11 +50,11 @@ struct file {
|
|||||||
const char *path,
|
const char *path,
|
||||||
int context,
|
int context,
|
||||||
void *additional_data);
|
void *additional_data);
|
||||||
} file;
|
} xWatcher_file;
|
||||||
|
|
||||||
struct directory {
|
typedef struct xWatcher_directory {
|
||||||
// list of files
|
// list of files
|
||||||
struct file *files;
|
struct xWatcher_file *files;
|
||||||
|
|
||||||
char *path;
|
char *path;
|
||||||
// used for adding (additional) context in the handler (if needed)
|
// used for adding (additional) context in the handler (if needed)
|
||||||
@ -78,10 +78,10 @@ struct directory {
|
|||||||
#else
|
#else
|
||||||
#error "Unsupported"
|
#error "Unsupported"
|
||||||
#endif
|
#endif
|
||||||
} directory;
|
} xWatcher_directory;
|
||||||
|
|
||||||
typedef struct x_watcher {
|
typedef struct x_watcher {
|
||||||
struct directory *directories;
|
struct xWatcher_directory *directories;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
int thread_id;
|
int thread_id;
|
||||||
bool alive;
|
bool alive;
|
||||||
@ -118,7 +118,7 @@ typedef struct x_watcher {
|
|||||||
x_watcher *watcher = (x_watcher*) argument;
|
x_watcher *watcher = (x_watcher*) argument;
|
||||||
char buffer[BUF_LEN];
|
char buffer[BUF_LEN];
|
||||||
ssize_t lenght;
|
ssize_t lenght;
|
||||||
struct directory *directories = watcher->directories;
|
struct xWatcher_directory *directories = watcher->directories;
|
||||||
|
|
||||||
while(watcher->alive) {
|
while(watcher->alive) {
|
||||||
// poll for events
|
// poll for events
|
||||||
@ -150,7 +150,7 @@ typedef struct x_watcher {
|
|||||||
&buffer[i];
|
&buffer[i];
|
||||||
|
|
||||||
// find directory for which this even matches via the descriptor
|
// find directory for which this even matches via the descriptor
|
||||||
struct directory *directory = NULL;
|
struct xWatcher_directory *directory = NULL;
|
||||||
for(size_t j = 0; j < arr_count(directories); j++) {
|
for(size_t j = 0; j < arr_count(directories); j++) {
|
||||||
if(directories[j].inotify_watch_fd == event->wd) {
|
if(directories[j].inotify_watch_fd == event->wd) {
|
||||||
directory = &directories[j];
|
directory = &directories[j];
|
||||||
@ -163,7 +163,7 @@ typedef struct x_watcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find matching file (if any)
|
// find matching file (if any)
|
||||||
struct file *file = NULL;
|
struct xWatcher_file *file = NULL;
|
||||||
for(size_t j = 0; j < arr_count(directory->files); j++) {
|
for(size_t j = 0; j < arr_count(directory->files); j++) {
|
||||||
if(strcmp(directory->files[j].name, event->name) == 0) {
|
if(strcmp(directory->files[j].name, event->name) == 0) {
|
||||||
file = &directory->files[j];
|
file = &directory->files[j];
|
||||||
@ -225,9 +225,9 @@ typedef struct x_watcher {
|
|||||||
|
|
||||||
// cleanup time
|
// cleanup time
|
||||||
for(size_t i = 0; i < arr_count(watcher->directories); i++) {
|
for(size_t i = 0; i < arr_count(watcher->directories); i++) {
|
||||||
struct directory *directory = &watcher->directories[i];
|
struct xWatcher_directory *directory = &watcher->directories[i];
|
||||||
for(size_t j = 0; j < arr_count(directory->files); j++) {
|
for(size_t j = 0; j < arr_count(directory->files); j++) {
|
||||||
struct file *file = &directory->files[j];
|
struct xWatcher_file *file = &directory->files[j];
|
||||||
free(file->name);
|
free(file->name);
|
||||||
}
|
}
|
||||||
arr_free(directory->files);
|
arr_free(directory->files);
|
||||||
@ -247,7 +247,7 @@ typedef struct x_watcher {
|
|||||||
|
|
||||||
static inline void *__internal_xWatcherProcess(void *argument) {
|
static inline void *__internal_xWatcherProcess(void *argument) {
|
||||||
x_watcher *watcher = (x_watcher*) argument;
|
x_watcher *watcher = (x_watcher*) argument;
|
||||||
struct directory *directories = watcher->directories;
|
struct xWatcher_directory *directories = watcher->directories;
|
||||||
|
|
||||||
// create an event list so we can still make use of the Windows API
|
// create an event list so we can still make use of the Windows API
|
||||||
HANDLE events[arr_count(directories)];
|
HANDLE events[arr_count(directories)];
|
||||||
@ -281,7 +281,7 @@ typedef struct x_watcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shorhand for convenience
|
// shorhand for convenience
|
||||||
struct directory *dir = &directories[object_index];
|
struct xWatcher_directory *dir = &directories[object_index];
|
||||||
|
|
||||||
// retrieve event data
|
// retrieve event data
|
||||||
DWORD bytes_transferred;
|
DWORD bytes_transferred;
|
||||||
@ -326,7 +326,7 @@ typedef struct x_watcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find matching file (if any)
|
// find matching file (if any)
|
||||||
struct file *file = NULL;
|
struct xWatcher_file *file = NULL;
|
||||||
for(size_t j = 0; j < arr_count(dir->files); j++) {
|
for(size_t j = 0; j < arr_count(dir->files); j++) {
|
||||||
if(strcmp(dir->files[j].name, name_char) == 0) {
|
if(strcmp(dir->files[j].name, name_char) == 0) {
|
||||||
file = &dir->files[j];
|
file = &dir->files[j];
|
||||||
@ -423,9 +423,9 @@ typedef struct x_watcher {
|
|||||||
}
|
}
|
||||||
// cleanup time
|
// cleanup time
|
||||||
for(size_t i = 0; i < arr_count(watcher->directories); i++) {
|
for(size_t i = 0; i < arr_count(watcher->directories); i++) {
|
||||||
struct directory *directory = &watcher->directories[i];
|
struct xWatcher_directory *directory = &watcher->directories[i];
|
||||||
for(size_t j = 0; j < arr_count(directory->files); j++) {
|
for(size_t j = 0; j < arr_count(directory->files); j++) {
|
||||||
struct file *file = &directory->files[j];
|
struct xWatcher_file *file = &directory->files[j];
|
||||||
free(file->name);
|
free(file->name);
|
||||||
}
|
}
|
||||||
arr_free(directory->files);
|
arr_free(directory->files);
|
||||||
@ -487,7 +487,7 @@ static inline bool xWatcher_appendFile(
|
|||||||
filename = path;
|
filename = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct directory *dir = NULL;
|
struct xWatcher_directory *dir = NULL;
|
||||||
|
|
||||||
// check against the database of (pre-existing) directories
|
// check against the database of (pre-existing) directories
|
||||||
for(size_t i = 0; i < arr_count(watcher->directories); i++) {
|
for(size_t i = 0; i < arr_count(watcher->directories); i++) {
|
||||||
@ -499,7 +499,7 @@ static inline bool xWatcher_appendFile(
|
|||||||
|
|
||||||
// directory exists, check if an callback has been already added
|
// directory exists, check if an callback has been already added
|
||||||
if(dir == NULL) {
|
if(dir == NULL) {
|
||||||
struct directory new_dir;
|
struct xWatcher_directory new_dir;
|
||||||
|
|
||||||
new_dir.callback_func = NULL; // DO NOT add callbacks if it's a file
|
new_dir.callback_func = NULL; // DO NOT add callbacks if it's a file
|
||||||
new_dir.context = 0; // context should be invalid as well
|
new_dir.context = 0; // context should be invalid as well
|
||||||
@ -524,7 +524,7 @@ static inline bool xWatcher_appendFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// search for the file
|
// search for the file
|
||||||
struct file *file = NULL;
|
struct xWatcher_file *file = NULL;
|
||||||
for(size_t i = 0; i < arr_count(dir->files); i++) {
|
for(size_t i = 0; i < arr_count(dir->files); i++) {
|
||||||
if(strcmp(dir->files[i].name, filename) == 0) {
|
if(strcmp(dir->files[i].name, filename) == 0) {
|
||||||
file = &dir->files[i];
|
file = &dir->files[i];
|
||||||
@ -535,7 +535,7 @@ static inline bool xWatcher_appendFile(
|
|||||||
return false; // file already exists, that's an ERROR
|
return false; // file already exists, that's an ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file new_file;
|
struct xWatcher_file new_file;
|
||||||
// avoid an invalid free because this shares the memory space
|
// avoid an invalid free because this shares the memory space
|
||||||
// of the full path string
|
// of the full path string
|
||||||
new_file.name = strdup(filename);
|
new_file.name = strdup(filename);
|
||||||
@ -667,7 +667,7 @@ static inline bool xWatcher_appendDir(
|
|||||||
if(path[strlen(path)-1] == DIRBRK)
|
if(path[strlen(path)-1] == DIRBRK)
|
||||||
path[strlen(path)-1] = '\0';
|
path[strlen(path)-1] = '\0';
|
||||||
|
|
||||||
struct directory *dir = NULL;
|
struct xWatcher_directory *dir = NULL;
|
||||||
|
|
||||||
// check against the database of (pre-existing) directories
|
// check against the database of (pre-existing) directories
|
||||||
for(size_t i=0; i < arr_count(watcher->directories); i++) {
|
for(size_t i=0; i < arr_count(watcher->directories); i++) {
|
||||||
@ -689,7 +689,7 @@ static inline bool xWatcher_appendDir(
|
|||||||
dir->additional_data = reference->additional_data;
|
dir->additional_data = reference->additional_data;
|
||||||
} else {
|
} else {
|
||||||
// keep an eye for this one as it's on the stack
|
// keep an eye for this one as it's on the stack
|
||||||
struct directory dir;
|
struct xWatcher_directory dir;
|
||||||
|
|
||||||
dir.path = path;
|
dir.path = path;
|
||||||
dir.callback_func = reference->callback_func;
|
dir.callback_func = reference->callback_func;
|
||||||
|
Loading…
Reference in New Issue
Block a user