started switching file tracking over to an integrated subsystem
parent
3edcf0a5b3
commit
2b2e90c987
|
@ -275,70 +275,6 @@ eol_in_place_convert_out(char *data, i32 size, i32 max, i32 *size_out){
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
// TODO(allen): ditch this shit yo
|
|
||||||
inline i32
|
|
||||||
is_whitespace(char c){
|
|
||||||
i32 result;
|
|
||||||
result = (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v');
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline i32
|
|
||||||
is_alphanumeric_true(char c){
|
|
||||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
inline i32
|
|
||||||
is_alphanumeric(char c){
|
|
||||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_');
|
|
||||||
}
|
|
||||||
|
|
||||||
inline i32
|
|
||||||
is_upper(char c){
|
|
||||||
return (c >= 'A' && c <= 'Z');
|
|
||||||
}
|
|
||||||
|
|
||||||
inline i32
|
|
||||||
is_lower(char c){
|
|
||||||
return (c >= 'a' && c <= 'z');
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char
|
|
||||||
to_upper(char c){
|
|
||||||
if (is_lower(c)){
|
|
||||||
c += 'A' - 'a';
|
|
||||||
}
|
|
||||||
return(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal i32
|
|
||||||
is_match(char *a, char *b, i32 len){
|
|
||||||
i32 result = 1;
|
|
||||||
for (;len > 0; --len, ++a, ++b){
|
|
||||||
if (*a != *b){
|
|
||||||
result = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal i32
|
|
||||||
is_match_insensitive(char *a, char *b, i32 len){
|
|
||||||
i32 result = 1;
|
|
||||||
for (;len > 0; --len, ++a, ++b){
|
|
||||||
if (to_upper(*a) != to_upper(*b)){
|
|
||||||
result = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Implementation of the gap buffer
|
// Implementation of the gap buffer
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
/*
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
Copy Right FourTech LLC, 2016
|
*
|
||||||
All Rights Are Reserved
|
* 20.07.2016
|
||||||
|
*
|
||||||
The OS agnostic file tracking API for applications
|
* File tracking API.
|
||||||
that want to interact with potentially many files on
|
*
|
||||||
the disk that could be changed by other applications.
|
*/
|
||||||
|
|
||||||
Created on: 20.07.2016
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
#ifndef FILE_TRACK_4TECH_H
|
#if !defined(FILE_TRACK_4TECH_H)
|
||||||
#define FILE_TRACK_4TECH_H
|
#define FILE_TRACK_4TECH_H
|
||||||
|
|
||||||
#ifndef FILE_TRACK_LINK
|
#if !defined(FILE_TRACK_LINK)
|
||||||
#define FILE_TRACK_LINK static
|
# define FILE_TRACK_LINK static
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
typedef struct{
|
||||||
|
u8 opaque[128];
|
||||||
|
} File_Track_System;
|
||||||
|
|
||||||
|
typedef i32 File_Track_Result;
|
||||||
enum{
|
enum{
|
||||||
FileTrack_Good,
|
FileTrack_Good,
|
||||||
FileTrack_MemoryTooSmall,
|
FileTrack_MemoryTooSmall,
|
||||||
|
@ -31,16 +30,8 @@ enum{
|
||||||
FileTrack_FileSystemError
|
FileTrack_FileSystemError
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
uint8_t opaque[128];
|
|
||||||
} File_Track_System;
|
|
||||||
|
|
||||||
typedef int32_t File_Track_Result;
|
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
init_track_system(File_Track_System *system,
|
init_track_system(File_Track_System *system, void *table_memory, i32 table_memory_size, void *listener_memory, i32 listener_memory_size);
|
||||||
void *table_memory, int32_t table_memory_size,
|
|
||||||
void *listener_memory, int32_t listener_memory_size);
|
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
add_listener(File_Track_System *system, char *filename);
|
add_listener(File_Track_System *system, char *filename);
|
||||||
|
@ -49,13 +40,13 @@ FILE_TRACK_LINK File_Track_Result
|
||||||
remove_listener(File_Track_System *system, char *filename);
|
remove_listener(File_Track_System *system, char *filename);
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
move_track_system(File_Track_System *system, void *mem, int32_t size);
|
move_track_system(File_Track_System *system, void *mem, i32 size);
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size);
|
expand_track_system_listeners(File_Track_System *system, void *mem, i32 size);
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
get_change_event(File_Track_System *system, char *buffer, int32_t max);
|
get_change_event(File_Track_System *system, u8 *buffer, i32 max);
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
shut_down_track_system(File_Track_System *system);
|
shut_down_track_system(File_Track_System *system);
|
|
@ -1,45 +1,33 @@
|
||||||
/*
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
Copy Right FourTech LLC, 2016
|
*
|
||||||
All Rights Are Reserved
|
* 20.08.2016
|
||||||
|
*
|
||||||
The OS agnostic file tracking API for applications
|
* File tracking shared.
|
||||||
that want to interact with potentially many files on
|
*
|
||||||
the disk that could be changed by other applications.
|
*/
|
||||||
|
|
||||||
Created on: 27.08.2016
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
#ifndef Assert
|
|
||||||
# define Assert(c) do { if (!(c)) { *((int*)0) = 0xA11E; } } while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ZeroStruct
|
|
||||||
# define ZeroStruct(s) for (int32_t i = 0; i < sizeof(s); ++i) { ((char*)(&(s)))[i] = 0; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint32_t id[4];
|
u32 id[4];
|
||||||
} File_Index;
|
} File_Index;
|
||||||
|
|
||||||
typedef uint32_t rptr32;
|
typedef u32 rptr32;
|
||||||
|
|
||||||
#define to_ptr(b,p) ((void*)((char*)b + p))
|
#define to_ptr(b,p) ((void*)((char*)b + p))
|
||||||
#define to_rptr32(b,p) ((rptr32)((char*)(p) - (char*)(b)))
|
#define to_rptr32(b,p) ((rptr32)((char*)(p) - (char*)(b)))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
File_Index hash;
|
File_Index hash;
|
||||||
uint32_t opaque[4];
|
u32 opaque[4];
|
||||||
} File_Track_Entry;
|
} File_Track_Entry;
|
||||||
|
global_const File_Track_Entry null_file_track_entry = {0};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t size;
|
i32 size;
|
||||||
uint32_t tracked_count;
|
u32 tracked_count;
|
||||||
uint32_t max;
|
u32 max;
|
||||||
rptr32 file_table;
|
rptr32 file_table;
|
||||||
} File_Track_Tables;
|
} File_Track_Tables;
|
||||||
|
|
||||||
|
@ -50,13 +38,13 @@ typedef struct DLL_Node {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static File_Index
|
internal File_Index
|
||||||
zero_file_index(){
|
zero_file_index(){
|
||||||
File_Index a = {0};
|
File_Index a = {0};
|
||||||
return(a);
|
return(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t
|
internal i32
|
||||||
file_hash_is_zero(File_Index a){
|
file_hash_is_zero(File_Index a){
|
||||||
return ((a.id[0] == 0) &&
|
return ((a.id[0] == 0) &&
|
||||||
(a.id[1] == 0) &&
|
(a.id[1] == 0) &&
|
||||||
|
@ -64,7 +52,7 @@ file_hash_is_zero(File_Index a){
|
||||||
(a.id[3] == 0));
|
(a.id[3] == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t
|
internal i32
|
||||||
file_hash_is_deleted(File_Index a){
|
file_hash_is_deleted(File_Index a){
|
||||||
return ((a.id[0] == 0xFFFFFFFF) &&
|
return ((a.id[0] == 0xFFFFFFFF) &&
|
||||||
(a.id[1] == 0xFFFFFFFF) &&
|
(a.id[1] == 0xFFFFFFFF) &&
|
||||||
|
@ -72,7 +60,7 @@ file_hash_is_deleted(File_Index a){
|
||||||
(a.id[3] == 0xFFFFFFFF));
|
(a.id[3] == 0xFFFFFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t
|
internal i32
|
||||||
file_index_eq(File_Index a, File_Index b){
|
file_index_eq(File_Index a, File_Index b){
|
||||||
return ((a.id[0] == b.id[0]) &&
|
return ((a.id[0] == b.id[0]) &&
|
||||||
(a.id[1] == b.id[1]) &&
|
(a.id[1] == b.id[1]) &&
|
||||||
|
@ -80,7 +68,7 @@ file_index_eq(File_Index a, File_Index b){
|
||||||
(a.id[3] == b.id[3]));
|
(a.id[3] == b.id[3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
internal void
|
||||||
insert_node(DLL_Node *pos, DLL_Node *node){
|
insert_node(DLL_Node *pos, DLL_Node *node){
|
||||||
node->prev = pos;
|
node->prev = pos;
|
||||||
node->next = pos->next;
|
node->next = pos->next;
|
||||||
|
@ -88,19 +76,19 @@ insert_node(DLL_Node *pos, DLL_Node *node){
|
||||||
node->next->prev = node;
|
node->next->prev = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
internal void
|
||||||
remove_node(DLL_Node *node){
|
remove_node(DLL_Node *node){
|
||||||
node->next->prev = node->prev;
|
node->next->prev = node->prev;
|
||||||
node->prev->next = node->next;
|
node->prev->next = node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
internal void
|
||||||
init_sentinel_node(DLL_Node *node){
|
init_sentinel_node(DLL_Node *node){
|
||||||
node->next = node;
|
node->next = node;
|
||||||
node->prev = node;
|
node->prev = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DLL_Node*
|
internal DLL_Node*
|
||||||
allocate_node(DLL_Node *sentinel){
|
allocate_node(DLL_Node *sentinel){
|
||||||
DLL_Node *result = 0;
|
DLL_Node *result = 0;
|
||||||
if (sentinel->next != sentinel){
|
if (sentinel->next != sentinel){
|
||||||
|
@ -113,17 +101,17 @@ allocate_node(DLL_Node *sentinel){
|
||||||
#define FILE_ENTRY_COST (sizeof(File_Track_Entry))
|
#define FILE_ENTRY_COST (sizeof(File_Track_Entry))
|
||||||
|
|
||||||
|
|
||||||
static int32_t
|
internal i32
|
||||||
tracking_system_has_space(File_Track_Tables *tables, int32_t new_count){
|
tracking_system_has_space(File_Track_Tables *tables, i32 new_count){
|
||||||
uint32_t count = tables->tracked_count;
|
u32 count = tables->tracked_count;
|
||||||
uint32_t max = tables->max;
|
u32 max = tables->max;
|
||||||
int32_t result = ((count + new_count)*8 < max*7);
|
i32 result = ((count + new_count)*8 < max*7);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t
|
internal i32
|
||||||
entry_is_available(File_Track_Entry *entry){
|
entry_is_available(File_Track_Entry *entry){
|
||||||
int32_t result = 0;
|
i32 result = 0;
|
||||||
if (entry){
|
if (entry){
|
||||||
result =
|
result =
|
||||||
file_hash_is_zero(entry->hash) ||
|
file_hash_is_zero(entry->hash) ||
|
||||||
|
@ -132,12 +120,12 @@ entry_is_available(File_Track_Entry *entry){
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Track_Entry*
|
internal File_Track_Entry*
|
||||||
tracking_system_lookup_entry(File_Track_Tables *tables, File_Index key){
|
tracking_system_lookup_entry(File_Track_Tables *tables, File_Index key){
|
||||||
uint32_t hash = key.id[0];
|
u32 hash = key.id[0];
|
||||||
uint32_t max = tables->max;
|
u32 max = tables->max;
|
||||||
uint32_t index = (hash) % max;
|
u32 index = (hash) % max;
|
||||||
uint32_t start = index;
|
u32 start = index;
|
||||||
|
|
||||||
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
||||||
|
|
||||||
|
@ -169,7 +157,7 @@ tracking_system_lookup_entry(File_Track_Tables *tables, File_Index key){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Track_Entry*
|
internal File_Track_Entry*
|
||||||
get_file_entry(File_Track_Tables *tables, File_Index index){
|
get_file_entry(File_Track_Tables *tables, File_Index index){
|
||||||
File_Track_Entry *entry = 0;
|
File_Track_Entry *entry = 0;
|
||||||
|
|
||||||
|
@ -181,11 +169,11 @@ get_file_entry(File_Track_Tables *tables, File_Index index){
|
||||||
return(entry);
|
return(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
internal void
|
||||||
internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){
|
internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){
|
||||||
Assert(!entry_is_available(entry));
|
Assert(!entry_is_available(entry));
|
||||||
|
|
||||||
ZeroStruct(*entry);
|
*entry = null_file_track_entry;
|
||||||
entry->hash.id[0] = 0xFFFFFFFF;
|
entry->hash.id[0] = 0xFFFFFFFF;
|
||||||
entry->hash.id[1] = 0xFFFFFFFF;
|
entry->hash.id[1] = 0xFFFFFFFF;
|
||||||
entry->hash.id[2] = 0xFFFFFFFF;
|
entry->hash.id[2] = 0xFFFFFFFF;
|
||||||
|
@ -194,27 +182,26 @@ internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){
|
||||||
--tables->tracked_count;
|
--tables->tracked_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t
|
internal i32
|
||||||
enough_memory_to_init_table(int32_t table_memory_size){
|
enough_memory_to_init_table(i32 table_memory_size){
|
||||||
int32_t result = (sizeof(File_Track_Tables) + FILE_ENTRY_COST*8 <= table_memory_size);
|
i32 result = (sizeof(File_Track_Tables) + FILE_ENTRY_COST*8 <= table_memory_size);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
internal void
|
||||||
init_table_memory(File_Track_Tables *tables, int32_t table_memory_size){
|
init_table_memory(File_Track_Tables *tables, i32 table_memory_size){
|
||||||
tables->size = table_memory_size;
|
tables->size = table_memory_size;
|
||||||
tables->tracked_count = 0;
|
tables->tracked_count = 0;
|
||||||
|
|
||||||
int32_t max_number_of_entries =
|
i32 max_number_of_entries = (table_memory_size - sizeof(*tables)) / FILE_ENTRY_COST;
|
||||||
(table_memory_size - sizeof(*tables)) / FILE_ENTRY_COST;
|
|
||||||
|
|
||||||
tables->file_table = sizeof(*tables);
|
tables->file_table = sizeof(*tables);
|
||||||
tables->max = max_number_of_entries;
|
tables->max = max_number_of_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Track_Result
|
internal File_Track_Result
|
||||||
move_table_memory(File_Track_Tables *original_tables,
|
move_table_memory(File_Track_Tables *original_tables,
|
||||||
void *mem, int32_t size){
|
void *mem, i32 size){
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
|
|
||||||
if (original_tables->size < size){
|
if (original_tables->size < size){
|
||||||
|
@ -224,24 +211,22 @@ move_table_memory(File_Track_Tables *original_tables,
|
||||||
{
|
{
|
||||||
tables->size = size;
|
tables->size = size;
|
||||||
|
|
||||||
int32_t likely_entry_size = FILE_ENTRY_COST;
|
i32 likely_entry_size = FILE_ENTRY_COST;
|
||||||
int32_t max_number_of_entries = (size - sizeof(*tables)) / likely_entry_size;
|
i32 max_number_of_entries = (size - sizeof(*tables)) / likely_entry_size;
|
||||||
|
|
||||||
tables->file_table = sizeof(*tables);
|
tables->file_table = sizeof(*tables);
|
||||||
tables->max = max_number_of_entries;
|
tables->max = max_number_of_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tables->max > original_tables->max){
|
if (tables->max > original_tables->max){
|
||||||
uint32_t original_max = original_tables->max;
|
u32 original_max = original_tables->max;
|
||||||
|
|
||||||
// NOTE(allen): Rehash the tracking table
|
// NOTE(allen): Rehash the tracking table
|
||||||
{
|
{
|
||||||
File_Track_Entry *entries = (File_Track_Entry*)
|
File_Track_Entry *entries = (File_Track_Entry*)
|
||||||
to_ptr(original_tables, original_tables->file_table);
|
to_ptr(original_tables, original_tables->file_table);
|
||||||
|
|
||||||
for (uint32_t index = 0;
|
for (u32 index = 0; index < original_max; ++index){
|
||||||
index < original_max;
|
|
||||||
++index){
|
|
||||||
File_Track_Entry *entry = entries + index;
|
File_Track_Entry *entry = entries + index;
|
||||||
if (!entry_is_available(entry)){
|
if (!entry_is_available(entry)){
|
||||||
File_Index hash = entry->hash;
|
File_Index hash = entry->hash;
|
||||||
|
@ -267,4 +252,5 @@ move_table_memory(File_Track_Tables *original_tables,
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
/*
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
The OS agnostic file tracking API for applications
|
*
|
||||||
that want to interact with potentially many files on
|
* 20.07.2016
|
||||||
the disk that could be changed by other applications.
|
*
|
||||||
|
* File tracking win32.
|
||||||
Created on: 20.07.2016
|
*
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
#include "4tech_file_track.h"
|
#include "4ed_file_track.h"
|
||||||
#include "4tech_file_track_general.c"
|
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
@ -19,8 +17,9 @@ typedef struct {
|
||||||
OVERLAPPED overlapped;
|
OVERLAPPED overlapped;
|
||||||
char result[2048];
|
char result[2048];
|
||||||
HANDLE dir;
|
HANDLE dir;
|
||||||
int32_t user_count;
|
i32 user_count;
|
||||||
} Win32_Directory_Listener;
|
} Win32_Directory_Listener;
|
||||||
|
global_const OVERLAPPED null_overlapped = {0};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DLL_Node node;
|
DLL_Node node;
|
||||||
|
@ -44,9 +43,7 @@ typedef struct {
|
||||||
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
init_track_system(File_Track_System *system,
|
init_track_system(File_Track_System *system, void *table_memory, i32 table_memory_size, void *listener_memory, i32 listener_memory_size){
|
||||||
void *table_memory, int32_t table_memory_size,
|
|
||||||
void *listener_memory, int32_t listener_memory_size){
|
|
||||||
File_Track_Result result = FileTrack_MemoryTooSmall;
|
File_Track_Result result = FileTrack_MemoryTooSmall;
|
||||||
Win32_File_Track_Vars *vars = to_vars(system);
|
Win32_File_Track_Vars *vars = to_vars(system);
|
||||||
|
|
||||||
|
@ -65,8 +62,8 @@ init_track_system(File_Track_System *system,
|
||||||
init_sentinel_node(&vars->free_sentinel);
|
init_sentinel_node(&vars->free_sentinel);
|
||||||
|
|
||||||
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)listener_memory;
|
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)listener_memory;
|
||||||
int32_t count = listener_memory_size / sizeof(Win32_Directory_Listener_Node);
|
i32 count = listener_memory_size / sizeof(Win32_Directory_Listener_Node);
|
||||||
for (int32_t i = 0; i < count; ++i, ++listener){
|
for (i32 i = 0; i < count; ++i, ++listener){
|
||||||
insert_node(&vars->free_sentinel, &listener->node);
|
insert_node(&vars->free_sentinel, &listener->node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,22 +80,19 @@ init_track_system(File_Track_System *system,
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t
|
internal i32
|
||||||
internal_get_parent_name(char *out, int32_t max, char *name){
|
internal_get_parent_name(char *out, i32 max, char *name){
|
||||||
int32_t len, slash_i;
|
|
||||||
|
|
||||||
char *ptr = name;
|
char *ptr = name;
|
||||||
for (; *ptr != 0; ++ptr);
|
for (; *ptr != 0; ++ptr);
|
||||||
len = (int32_t)(ptr - name);
|
i32 len = (i32)(ptr - name);
|
||||||
|
|
||||||
// TODO(allen): make this system real
|
// TODO(allen): make this system real
|
||||||
Assert(len < max);
|
Assert(len < max);
|
||||||
|
|
||||||
for (slash_i = len-1;
|
i32 slash_i = len-1;
|
||||||
slash_i > 0 && name[slash_i] != '\\' && name[slash_i] != '/';
|
for (;slash_i > 0 && name[slash_i] != '\\' && name[slash_i] != '/';--slash_i);
|
||||||
--slash_i);
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < slash_i; ++i){
|
for (i32 i = 0; i < slash_i; ++i){
|
||||||
out[i] = name[i];
|
out[i] = name[i];
|
||||||
}
|
}
|
||||||
out[slash_i] = 0;
|
out[slash_i] = 0;
|
||||||
|
@ -106,7 +100,7 @@ internal_get_parent_name(char *out, int32_t max, char *name){
|
||||||
return(slash_i);
|
return(slash_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Index
|
internal File_Index
|
||||||
internal_get_file_index(BY_HANDLE_FILE_INFORMATION info){
|
internal_get_file_index(BY_HANDLE_FILE_INFORMATION info){
|
||||||
File_Index hash;
|
File_Index hash;
|
||||||
hash.id[0] = info.nFileIndexLow;
|
hash.id[0] = info.nFileIndexLow;
|
||||||
|
@ -157,7 +151,7 @@ add_listener(File_Track_System *system, char *filename){
|
||||||
allocate_node(&vars->free_sentinel);
|
allocate_node(&vars->free_sentinel);
|
||||||
if (node){
|
if (node){
|
||||||
if (CreateIoCompletionPort(dir, vars->iocp, (ULONG_PTR)node, 1)){
|
if (CreateIoCompletionPort(dir, vars->iocp, (ULONG_PTR)node, 1)){
|
||||||
ZeroStruct(node->listener.overlapped);
|
node->listener.overlapped = null_overlapped;
|
||||||
if (ReadDirectoryChangesW(dir, node->listener.result, sizeof(node->listener.result), 1, FLAGS, 0, &node->listener.overlapped, 0)){
|
if (ReadDirectoryChangesW(dir, node->listener.result, sizeof(node->listener.result), 1, FLAGS, 0, &node->listener.overlapped, 0)){
|
||||||
node->listener.dir = dir;
|
node->listener.dir = dir;
|
||||||
node->listener.user_count = 1;
|
node->listener.user_count = 1;
|
||||||
|
@ -216,51 +210,42 @@ remove_listener(File_Track_System *system, char *filename){
|
||||||
|
|
||||||
EnterCriticalSection(&vars->table_lock);
|
EnterCriticalSection(&vars->table_lock);
|
||||||
|
|
||||||
{
|
File_Track_Tables *tables = to_tables(vars);
|
||||||
File_Track_Tables *tables = to_tables(vars);
|
|
||||||
|
// TODO(allen): make this real!
|
||||||
|
char dir_name[1024];
|
||||||
|
internal_get_parent_name(dir_name, sizeof(dir_name), filename);
|
||||||
|
|
||||||
|
HANDLE dir = CreateFile(dir_name, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0);
|
||||||
|
|
||||||
|
if (dir != INVALID_HANDLE_VALUE){
|
||||||
|
BY_HANDLE_FILE_INFORMATION dir_info = {0};
|
||||||
|
DWORD getinfo_result = GetFileInformationByHandle(dir, &dir_info);
|
||||||
|
|
||||||
// TODO(allen): make this real!
|
if (getinfo_result){
|
||||||
char dir_name[1024];
|
File_Index dir_hash = internal_get_file_index(dir_info);
|
||||||
internal_get_parent_name(dir_name, sizeof(dir_name), filename);
|
File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash);
|
||||||
|
Win32_File_Track_Entry *win32_dir = (Win32_File_Track_Entry*)dir_lookup;
|
||||||
HANDLE dir = CreateFile(
|
|
||||||
dir_name,
|
|
||||||
FILE_LIST_DIRECTORY,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
0,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (dir != INVALID_HANDLE_VALUE){
|
|
||||||
BY_HANDLE_FILE_INFORMATION dir_info = {0};
|
|
||||||
DWORD getinfo_result = GetFileInformationByHandle(dir, &dir_info);
|
|
||||||
|
|
||||||
if (getinfo_result){
|
Assert(!entry_is_available(dir_lookup));
|
||||||
File_Index dir_hash = internal_get_file_index(dir_info);
|
Win32_Directory_Listener_Node *node = win32_dir->listener_node;
|
||||||
File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash);
|
--node->listener.user_count;
|
||||||
Win32_File_Track_Entry *win32_dir = (Win32_File_Track_Entry*)dir_lookup;
|
|
||||||
|
|
||||||
Assert(!entry_is_available(dir_lookup));
|
|
||||||
Win32_Directory_Listener_Node *node = win32_dir->listener_node;
|
|
||||||
--node->listener.user_count;
|
|
||||||
|
|
||||||
if (node->listener.user_count == 0){
|
|
||||||
insert_node(&vars->free_sentinel, &node->node);
|
|
||||||
CancelIo(win32_dir->dir);
|
|
||||||
CloseHandle(win32_dir->dir);
|
|
||||||
internal_free_slot(tables, dir_lookup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = FileTrack_FileSystemError;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(dir);
|
if (node->listener.user_count == 0){
|
||||||
|
insert_node(&vars->free_sentinel, &node->node);
|
||||||
|
CancelIo(win32_dir->dir);
|
||||||
|
CloseHandle(win32_dir->dir);
|
||||||
|
internal_free_slot(tables, dir_lookup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
result = FileTrack_FileSystemError;
|
result = FileTrack_FileSystemError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CloseHandle(dir);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result = FileTrack_FileSystemError;
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&vars->table_lock);
|
LeaveCriticalSection(&vars->table_lock);
|
||||||
|
@ -269,17 +254,15 @@ remove_listener(File_Track_System *system, char *filename){
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
move_track_system(File_Track_System *system, void *mem, int32_t size){
|
move_track_system(File_Track_System *system, void *mem, i32 size){
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
Win32_File_Track_Vars *vars = to_vars(system);
|
Win32_File_Track_Vars *vars = to_vars(system);
|
||||||
|
|
||||||
EnterCriticalSection(&vars->table_lock);
|
EnterCriticalSection(&vars->table_lock);
|
||||||
{
|
File_Track_Tables *original_tables = to_tables(vars);
|
||||||
File_Track_Tables *original_tables = to_tables(vars);
|
result = move_table_memory(original_tables, mem, size);
|
||||||
result = move_table_memory(original_tables, mem, size);
|
if (result == FileTrack_Good){
|
||||||
if (result == FileTrack_Good){
|
vars->tables = mem;
|
||||||
vars->tables = mem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&vars->table_lock);
|
LeaveCriticalSection(&vars->table_lock);
|
||||||
|
|
||||||
|
@ -287,7 +270,7 @@ move_track_system(File_Track_System *system, void *mem, int32_t size){
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size){
|
expand_track_system_listeners(File_Track_System *system, void *mem, i32 size){
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
Win32_File_Track_Vars *vars = to_vars(system);
|
Win32_File_Track_Vars *vars = to_vars(system);
|
||||||
|
|
||||||
|
@ -295,8 +278,8 @@ expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size
|
||||||
|
|
||||||
if (sizeof(Win32_Directory_Listener_Node) <= size){
|
if (sizeof(Win32_Directory_Listener_Node) <= size){
|
||||||
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)mem;
|
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)mem;
|
||||||
int32_t count = size / sizeof(Win32_Directory_Listener_Node);
|
i32 count = size / sizeof(Win32_Directory_Listener_Node);
|
||||||
for (int32_t i = 0; i < count; ++i, ++listener){
|
for (i32 i = 0; i < count; ++i, ++listener){
|
||||||
insert_node(&vars->free_sentinel, &listener->node);
|
insert_node(&vars->free_sentinel, &listener->node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,99 +293,84 @@ expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_TRACK_LINK File_Track_Result
|
FILE_TRACK_LINK File_Track_Result
|
||||||
get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *size){
|
get_change_event(File_Track_System *system, char *buffer, i32 max, i32 *size){
|
||||||
File_Track_Result result = FileTrack_NoMoreEvents;
|
File_Track_Result result = FileTrack_NoMoreEvents;
|
||||||
Win32_File_Track_Vars *vars = to_vars(system);
|
Win32_File_Track_Vars *vars = to_vars(system);
|
||||||
|
|
||||||
static int32_t has_buffered_event = 0;
|
local_persist i32 has_buffered_event = 0;
|
||||||
static DWORD offset = 0;
|
local_persist DWORD offset = 0;
|
||||||
static Win32_Directory_Listener listener;
|
local_persist Win32_Directory_Listener listener;
|
||||||
|
|
||||||
EnterCriticalSection(&vars->table_lock);
|
EnterCriticalSection(&vars->table_lock);
|
||||||
|
|
||||||
{
|
OVERLAPPED *overlapped = 0;
|
||||||
OVERLAPPED *overlapped = 0;
|
DWORD length = 0;
|
||||||
DWORD length = 0;
|
ULONG_PTR key = 0;
|
||||||
ULONG_PTR key = 0;
|
|
||||||
|
i32 has_result = 0;
|
||||||
int32_t has_result = 0;
|
|
||||||
|
if (has_buffered_event){
|
||||||
if (has_buffered_event){
|
has_buffered_event = 0;
|
||||||
has_buffered_event = 0;
|
has_result = 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (GetQueuedCompletionStatus(vars->iocp, &length, &key, &overlapped, 0)){
|
||||||
|
Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped;
|
||||||
|
|
||||||
|
// NOTE(allen): Get a copy of the state of this node so we can set the node
|
||||||
|
// to work listening for changes again right away.
|
||||||
|
listener = *listener_ptr;
|
||||||
|
|
||||||
|
listener_ptr->overlapped = null_overlapped;
|
||||||
|
ReadDirectoryChangesW(listener_ptr->dir, listener_ptr->result, sizeof(listener_ptr->result), 1, FLAGS, 0, &listener_ptr->overlapped, 0);
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
has_result = 1;
|
has_result = 1;
|
||||||
}
|
}
|
||||||
else{
|
}
|
||||||
if (GetQueuedCompletionStatus(vars->iocp,
|
|
||||||
&length,
|
if (has_result){
|
||||||
&key,
|
|
||||||
&overlapped,
|
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*)(listener.result + offset);
|
||||||
0)){
|
|
||||||
Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped;
|
i32 len = info->FileNameLength / 2;
|
||||||
|
i32 dir_len = GetFinalPathNameByHandle(listener.dir, 0, 0, FILE_NAME_NORMALIZED);
|
||||||
// NOTE(allen): Get a copy of the state of this node so we can set the node
|
|
||||||
// to work listening for changes again right away.
|
i32 req_size = dir_len + 1 + len;
|
||||||
listener = *listener_ptr;
|
*size = req_size;
|
||||||
|
if (req_size < max){
|
||||||
ZeroStruct(listener_ptr->overlapped);
|
i32 pos = 0;
|
||||||
ReadDirectoryChangesW(listener_ptr->dir,
|
|
||||||
listener_ptr->result,
|
pos = GetFinalPathNameByHandle(listener.dir, buffer, max, FILE_NAME_NORMALIZED);
|
||||||
sizeof(listener_ptr->result),
|
buffer[pos++] = '\\';
|
||||||
1,
|
|
||||||
FLAGS,
|
for (i32 i = 0; i < len; ++i, ++pos){
|
||||||
0,
|
buffer[pos] = (char)info->FileName[i];
|
||||||
&listener_ptr->overlapped,
|
|
||||||
0);
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
has_result = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buffer[0] == '\\'){
|
||||||
|
for (i32 i = 0; i+4 < pos; ++i){
|
||||||
|
buffer[i] = buffer[i+4];
|
||||||
|
}
|
||||||
|
*size -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = FileTrack_Good;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// TODO(allen): Need some way to stash this result so that if the
|
||||||
|
// user comes back with more memory we can give them the change
|
||||||
|
// notification they missed.
|
||||||
|
result = FileTrack_MemoryTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_result){
|
if (info->NextEntryOffset != 0){
|
||||||
|
// TODO(allen): We're not ready to handle this yet.
|
||||||
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*)(listener.result + offset);
|
// For now I am breaking. In the future, if there
|
||||||
|
// are more results we should stash them and return
|
||||||
int32_t len = info->FileNameLength / 2;
|
// them in future calls.
|
||||||
int32_t dir_len = GetFinalPathNameByHandle(listener.dir, 0, 0,
|
offset += info->NextEntryOffset;
|
||||||
FILE_NAME_NORMALIZED);
|
has_buffered_event = 1;
|
||||||
|
|
||||||
int32_t req_size = dir_len + 1 + len;
|
|
||||||
*size = req_size;
|
|
||||||
if (req_size < max){
|
|
||||||
int32_t pos = 0;
|
|
||||||
|
|
||||||
pos = GetFinalPathNameByHandle(listener.dir, buffer, max,
|
|
||||||
FILE_NAME_NORMALIZED);
|
|
||||||
buffer[pos++] = '\\';
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < len; ++i, ++pos){
|
|
||||||
buffer[pos] = (char)info->FileName[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer[0] == '\\'){
|
|
||||||
for (int32_t i = 0; i+4 < pos; ++i){
|
|
||||||
buffer[i] = buffer[i+4];
|
|
||||||
}
|
|
||||||
*size -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = FileTrack_Good;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// TODO(allen): Need some way to stash this result so that if the
|
|
||||||
// user comes back with more memory we can give them the change
|
|
||||||
// notification they missed.
|
|
||||||
result = FileTrack_MemoryTooSmall;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->NextEntryOffset != 0){
|
|
||||||
// TODO(allen): We're not ready to handle this yet.
|
|
||||||
// For now I am breaking. In the future, if there
|
|
||||||
// are more results we should stash them and return
|
|
||||||
// them in future calls.
|
|
||||||
offset += info->NextEntryOffset;
|
|
||||||
has_buffered_event = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,9 +391,9 @@ shut_down_track_system(File_Track_System *system){
|
||||||
File_Track_Tables *tables = to_tables(vars);
|
File_Track_Tables *tables = to_tables(vars);
|
||||||
|
|
||||||
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
||||||
uint32_t max = tables->max;
|
u32 max = tables->max;
|
||||||
|
|
||||||
for (uint32_t index = 0; index < max; ++index){
|
for (u32 index = 0; index < max; ++index){
|
||||||
File_Track_Entry *entry = entries + index;
|
File_Track_Entry *entry = entries + index;
|
||||||
|
|
||||||
if (!entry_is_available(entry)){
|
if (!entry_is_available(entry)){
|
|
@ -1113,9 +1113,7 @@ wrap_state_consume_token(System_Functions *system, Render_Font *font, Code_Wrap_
|
||||||
end = fixed_end_point;
|
end = fixed_end_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < line_start){
|
i = clamp_top(i, line_start);
|
||||||
i = line_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == line_start){
|
if (i == line_start){
|
||||||
skipping_whitespace = true;
|
skipping_whitespace = true;
|
||||||
|
|
|
@ -28,6 +28,12 @@
|
||||||
// Program setup
|
// Program setup
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#define SUPPORT_DPI 1
|
||||||
|
#define UNICODE
|
||||||
|
|
||||||
|
#define FPS 60
|
||||||
|
#define frame_useconds (1000000 / FPS)
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "4tech_defines.h"
|
#include "4tech_defines.h"
|
||||||
|
@ -63,21 +69,20 @@
|
||||||
|
|
||||||
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
||||||
|
|
||||||
#include "filetrack/4tech_file_track_win32.c"
|
//////////////////////////////
|
||||||
|
|
||||||
|
#include "4ed_file_track.h"
|
||||||
#include "4ed_system_shared.h"
|
#include "4ed_system_shared.h"
|
||||||
|
|
||||||
#define SUPPORT_DPI 1
|
#include "4ed_file_track_general.cpp"
|
||||||
|
#include "4ed_file_track_win32.cpp"
|
||||||
#define FPS 60
|
|
||||||
#define frame_useconds (1000000 / FPS)
|
|
||||||
|
|
||||||
#define WM_4coder_ANIMATE (WM_USER + 0)
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Win32_Vars structs
|
// Win32_Vars structs
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#define WM_4coder_ANIMATE (WM_USER + 0)
|
||||||
|
|
||||||
struct Thread_Context{
|
struct Thread_Context{
|
||||||
u32 job_id;
|
u32 job_id;
|
||||||
b32 running;
|
b32 running;
|
||||||
|
|
Loading…
Reference in New Issue