faster file handling on windows
This commit is contained in:
@@ -32,6 +32,10 @@ endif
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
deps += cc.find_library('d3d11')
|
||||
# these are for tracy
|
||||
deps += cc.find_library('ws2_32')
|
||||
deps += cc.find_library('dbghelp')
|
||||
#end
|
||||
link += '-static' # Required to pack in mingw dlls on cross compilation
|
||||
endif
|
||||
|
||||
@@ -60,7 +64,7 @@ deps += dependency('qjs-layout',static:true)
|
||||
deps += dependency('qjs-nota',static:true)
|
||||
deps += dependency('qjs-miniz',static:true)
|
||||
deps += dependency('qjs-soloud',static:true)
|
||||
deps += dependency('qjs-dmon',static:true)
|
||||
#deps += dependency('qjs-dmon',static:true)
|
||||
deps += dependency('threads')
|
||||
|
||||
if get_option('chipmunk')
|
||||
|
||||
@@ -4,7 +4,8 @@ var actor_urs = {};
|
||||
|
||||
var actor_spawns = {};
|
||||
|
||||
globalThis.class_use = function class_use(script, config, base, callback) {
|
||||
function class_eval(script)
|
||||
{
|
||||
var file = Resources.find_script(script);
|
||||
|
||||
if (!file) {
|
||||
@@ -30,7 +31,22 @@ globalThis.class_use = function class_use(script, config, base, callback) {
|
||||
script = `(function use_${file.name()}() { var self = this; var $ = this.__proto__; ${script}; })`;
|
||||
|
||||
var fn = os.eval(file, script);
|
||||
fn.call(padawan);
|
||||
return {
|
||||
usefn: fn,
|
||||
file: file,
|
||||
parent: actor_urs[file]
|
||||
};
|
||||
}.hashify();
|
||||
|
||||
globalThis.class_use = function class_use(script, config, base, callback) {
|
||||
var prog = class_eval(script);
|
||||
var padawan = Object.create(prog.parent);
|
||||
actor_spawns[file].push(padawan);
|
||||
padawan._file = prog.file;
|
||||
padawan._root = prog.file.dir();
|
||||
|
||||
if (callback) callback(padawan);
|
||||
prog.fn.call(padawan);
|
||||
|
||||
if (typeof config === "object") Object.merge(padawan, config);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ function sprite_addbucket(sprite) {
|
||||
|
||||
function sprite_rmbucket(sprite) {
|
||||
if (sprite._oldlayer && sprite._oldtex) sprite_buckets[sprite._oldlayer][sprite._oldtex].remove(sprite);
|
||||
else for (var layer of Object.values(sprite_buckets)) for (var path of Object.values(layer)) path.remove(sprite);
|
||||
// else for (var layer of Object.values(sprite_buckets)) for (var path of Object.values(layer)) path.remove(sprite);
|
||||
};
|
||||
|
||||
/* an anim is simply an array of images */
|
||||
|
||||
@@ -324,6 +324,9 @@ globalThis.use = function use(file) {
|
||||
};
|
||||
|
||||
var allpaths = io.ls();
|
||||
//console.log(`found ${allpaths.length} files`);
|
||||
//console.log(json.encode(allpaths))
|
||||
|
||||
io.exists = function(path)
|
||||
{
|
||||
return allpaths.includes(path);// || core_db.exists(path);
|
||||
@@ -334,9 +337,8 @@ io.slurp = function slurp(path)
|
||||
{
|
||||
var findpath = Resources.replpath(path);
|
||||
var ret = tmpslurp(findpath, true); //|| core_db.slurp(findpath, true);
|
||||
if (!ret) console.info(`could not slurp path ${path} as ${findpath}`)
|
||||
return ret;
|
||||
}
|
||||
}.hashify();
|
||||
|
||||
io.slurpbytes = function(path)
|
||||
{
|
||||
|
||||
@@ -466,10 +466,9 @@ function make_shader(shader, pipe) {
|
||||
|
||||
var file = shader;
|
||||
shader = io.slurp(file);
|
||||
if (!shader) {
|
||||
console.info(`not found! slurping ${file}`);
|
||||
if (!shader)
|
||||
shader = io.slurp(`${file}`);
|
||||
}
|
||||
|
||||
var writejson = `.prosperon/${file.name()}.shader.json`;
|
||||
|
||||
breakme: if (io.exists(writejson)) {
|
||||
@@ -1450,15 +1449,6 @@ try{
|
||||
render.end_pass();
|
||||
render.commit();
|
||||
endframe();
|
||||
var cycles = os.gc();
|
||||
if (cycles.length > 0) {
|
||||
cycles.forEach(x => {
|
||||
x.address = x.address.toString(16);
|
||||
x.shape = x.shape.toString(16);
|
||||
x.class = x.class.toString(16);
|
||||
});
|
||||
tracy.message(`GC cycles freed: ${json.encode(cycles)}`);
|
||||
}
|
||||
tracy.gpu_collect();
|
||||
tracy.end_frame();
|
||||
tracy.gpu_sync();
|
||||
@@ -1472,7 +1462,7 @@ try{
|
||||
}
|
||||
};
|
||||
|
||||
dmon.watch('.');
|
||||
//if (dmon) dmon.watch('.');
|
||||
|
||||
function dmon_cb(e)
|
||||
{
|
||||
@@ -1489,7 +1479,7 @@ function dmon_cb(e)
|
||||
prosperon.process = function process() {
|
||||
layout.newframe();
|
||||
// check for hot reloading
|
||||
dmon.poll(dmon_cb);
|
||||
// if (dmon) dmon.poll(dmon_cb);
|
||||
var dt = profile.secs(profile.now()) - frame_t;
|
||||
frame_t = profile.secs(profile.now());
|
||||
|
||||
|
||||
217
source/jsffi.c
217
source/jsffi.c
@@ -29,7 +29,7 @@
|
||||
#include <stdint.h>
|
||||
#include "timer.h"
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include "tinydir.h"
|
||||
#include "cute_aseprite.h"
|
||||
|
||||
JSValue js_getpropertyuint32(JSContext *js, JSValue v, unsigned int i)
|
||||
@@ -644,15 +644,15 @@ JSC_CCALL(render_camera_screen2world,
|
||||
|
||||
JSC_CCALL(render_set_projection_ortho,
|
||||
lrtb extents = js2lrtb(js, argv[0]);
|
||||
float near = js2number(js,argv[1]);
|
||||
float far = js2number(js,argv[2]);
|
||||
float nearme = js2number(js,argv[1]);
|
||||
float farme = js2number(js,argv[2]);
|
||||
globalview.p = HMM_Orthographic_RH_ZO(
|
||||
extents.l,
|
||||
extents.r,
|
||||
extents.b,
|
||||
extents.t,
|
||||
near,
|
||||
far
|
||||
nearme,
|
||||
farme
|
||||
);
|
||||
globalview.vp = HMM_MulM4(globalview.p, globalview.v);
|
||||
)
|
||||
@@ -660,9 +660,9 @@ JSC_CCALL(render_set_projection_ortho,
|
||||
JSC_CCALL(render_set_projection_perspective,
|
||||
float fov = js2number(js,argv[0]);
|
||||
float aspect = js2number(js,argv[1]);
|
||||
float near = js2number(js,argv[2]);
|
||||
float far = js2number(js,argv[3]);
|
||||
globalview.p = HMM_Perspective_RH_NO(fov, aspect, near, far);
|
||||
float nearme = js2number(js,argv[2]);
|
||||
float farme = js2number(js,argv[3]);
|
||||
globalview.p = HMM_Perspective_RH_NO(fov, aspect, nearme, farme);
|
||||
globalview.vp = HMM_MulM4(globalview.p, globalview.v);
|
||||
)
|
||||
|
||||
@@ -1667,8 +1667,7 @@ static const JSCFunctionListEntry js_time_funcs[] = {
|
||||
};
|
||||
|
||||
JSC_SCALL(console_log,
|
||||
printf("%s\n",str);
|
||||
fflush(stdout);
|
||||
printf("%s\n", str);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_console_funcs[] = {
|
||||
@@ -1741,29 +1740,64 @@ static const JSCFunctionListEntry js_debug_funcs[] = {
|
||||
MIST_FUNC_DEF(debug, dump_obj, 1),
|
||||
};
|
||||
|
||||
#ifdef __WIN32
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void list_files(const char *path, JSContext *js, JSValue v, int *n) {
|
||||
WIN32_FIND_DATA ffd;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
char searchPath[MAX_PATH];
|
||||
|
||||
// Prepare the path for search
|
||||
snprintf(searchPath, sizeof(searchPath), "%s/*", path);
|
||||
|
||||
hFind = FindFirstFileEx(searchPath, FindExInfoStandard, &ffd, FindExSearchLimitToDirectories, NULL, 0);
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (strcmp(ffd.cFileName, ".") != 0 && strcmp(ffd.cFileName, "..") != 0) {
|
||||
char filePath[MAX_PATH];
|
||||
snprintf(filePath, sizeof(filePath), "%s/%s", path, ffd.cFileName);
|
||||
|
||||
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// If it's a directory, recurse into it
|
||||
// printf("Directory: %s\n", filePath);
|
||||
list_files(filePath, js, v, n);
|
||||
} else {
|
||||
JS_SetPropertyUint32(js, v, *n, JS_NewString(js, filePath+2));
|
||||
*n = *n+1;
|
||||
// If it's a file, print it
|
||||
// printf("File: %s\n", filePath);
|
||||
}
|
||||
}
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
|
||||
FindClose(hFind);
|
||||
}
|
||||
#else
|
||||
static void list_files(const char *path, JSContext *js, JSValue v, int *n)
|
||||
{
|
||||
DIR *dir = opendir(path);
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
char full_path[1024];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
|
||||
struct stat statbuf;
|
||||
if (stat(full_path, &statbuf) == 0) {
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
list_files(full_path, js, v, n);
|
||||
} else if (S_ISREG(statbuf.st_mode)) {
|
||||
JS_SetPropertyUint32(js, v, *n, JS_NewString(js, full_path+2));
|
||||
*n = *n + 1;
|
||||
}
|
||||
tinydir_dir dir;
|
||||
tinydir_open(&dir, path);
|
||||
do {
|
||||
tinydir_file file;
|
||||
tinydir_readfile(&dir, &file);
|
||||
if (file.is_dir) {
|
||||
if (!strcmp(file.name, ".") || !strcmp(file.name, "..")) continue;
|
||||
list_files(file.path, js, v, n);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
else {
|
||||
JS_SetPropertyUint32(js, v, *n, JS_NewString(js, file.path+2));
|
||||
*n = *n+1;
|
||||
}
|
||||
} while (!tinydir_next(&dir));
|
||||
|
||||
tinydir_close(&dir);
|
||||
}
|
||||
|
||||
#endif
|
||||
JSC_CCALL(io_ls,
|
||||
JSValue strarr = JS_NewArray(js);
|
||||
int i = 0;
|
||||
@@ -1775,31 +1809,103 @@ JSC_SCALL(io_chdir, ret = number2js(js,chdir(str)))
|
||||
JSC_SCALL(io_rm, ret = number2js(js,remove(str)))
|
||||
JSC_SCALL(io_mkdir, ret = number2js(js,mkdir(str,0777)))
|
||||
|
||||
JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
const char *file = JS_ToCString(js, argv[0]);
|
||||
|
||||
FILE *f = fopen(file, "rb");
|
||||
JS_FreeCString(js,file);
|
||||
if (!f)
|
||||
return JS_UNDEFINED;
|
||||
#include <quickjs.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
fseek(f,0,SEEK_END);
|
||||
size_t fsize = ftell(f);
|
||||
rewind(f);
|
||||
void *slurp = malloc(fsize);
|
||||
fread(slurp,fsize,1,f);
|
||||
fclose(f);
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
JSValue ret;
|
||||
if (JS_ToBool(js,argv[1]))
|
||||
ret = JS_NewStringLen(js, slurp, fsize);
|
||||
else
|
||||
ret = JS_NewArrayBufferCopy(js, slurp, fsize);
|
||||
JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
const char *file = JS_ToCString(js, argv[0]);
|
||||
if (!file)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
free(slurp);
|
||||
|
||||
return ret;
|
||||
size_t fsize;
|
||||
void *slurp = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows file mapping
|
||||
HANDLE hFile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
JS_FreeCString(js, file);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(hFile, &fileSize)) {
|
||||
CloseHandle(hFile);
|
||||
JS_FreeCString(js, file);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
fsize = (size_t)fileSize.QuadPart;
|
||||
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMapping == NULL) {
|
||||
CloseHandle(hFile);
|
||||
JS_FreeCString(js, file);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
slurp = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
CloseHandle(hMapping);
|
||||
CloseHandle(hFile);
|
||||
|
||||
if (slurp == NULL) {
|
||||
JS_FreeCString(js, file);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
#else
|
||||
// POSIX mmap
|
||||
int fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
JS_FreeCString(js, file);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
struct stat sb;
|
||||
if (fstat(fd, &sb) == -1) {
|
||||
close(fd);
|
||||
JS_FreeCString(js, file);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
fsize = sb.st_size;
|
||||
slurp = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
close(fd);
|
||||
|
||||
if (slurp == MAP_FAILED) {
|
||||
JS_FreeCString(js, file);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
#endif
|
||||
|
||||
JSValue ret;
|
||||
if (JS_ToBool(js, argv[1])) {
|
||||
// Return as string
|
||||
ret = JS_NewStringLen(js, slurp, fsize);
|
||||
} else {
|
||||
// Return as ArrayBuffer
|
||||
ret = JS_NewArrayBufferCopy(js, slurp, fsize);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Unmap on Windows
|
||||
UnmapViewOfFile(slurp);
|
||||
#else
|
||||
// Unmap on POSIX
|
||||
munmap(slurp, fsize);
|
||||
#endif
|
||||
|
||||
JS_FreeCString(js, file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValue js_io_slurpwrite(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
@@ -2133,7 +2239,10 @@ JSValue js_os_cwd(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
return JS_NewString(js,cwd);
|
||||
}
|
||||
|
||||
JSC_SCALL(os_env, ret = JS_NewString(js,getenv(str)))
|
||||
JSC_SCALL(os_env,
|
||||
char *env = getenv(str);
|
||||
if (env) ret = JS_NewString(js,env);
|
||||
)
|
||||
|
||||
JSValue js_os_sys(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
@@ -2799,7 +2908,7 @@ JSValue js_layout_use(JSContext *js);
|
||||
JSValue js_miniz_use(JSContext *js);
|
||||
JSValue js_soloud_use(JSContext *js);
|
||||
JSValue js_chipmunk2d_use(JSContext *js);
|
||||
JSValue js_dmon_use(JSContext *js);
|
||||
//JSValue js_dmon_use(JSContext *js);
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
JSValue js_tracy_use(JSContext *js);
|
||||
@@ -2889,7 +2998,7 @@ void ffi_load(JSContext *js) {
|
||||
JS_SetPropertyStr(js, globalThis, "miniz", js_miniz_use(js));
|
||||
JS_SetPropertyStr(js, globalThis, "soloud", js_soloud_use(js));
|
||||
JS_SetPropertyStr(js, globalThis, "chipmunk2d", js_chipmunk2d_use(js));
|
||||
JS_SetPropertyStr(js, globalThis, "dmon", js_dmon_use(js));
|
||||
// JS_SetPropertyStr(js, globalThis, "dmon", js_dmon_use(js));
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
JS_SetPropertyStr(js, globalThis, "tracy", js_tracy_use(js));
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include <quickjs.h>
|
||||
#include "glad.h"
|
||||
#include <tracy/TracyC.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "render.h"
|
||||
|
||||
static JSValue js_tracy_fiber_enter(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
#ifdef TRACY_ON_DEMAND
|
||||
if (!TracyCIsConnected) {
|
||||
JS_Call(js,argv[0], JS_UNDEFINED,0,NULL);
|
||||
@@ -24,6 +25,7 @@ static JSValue js_tracy_fiber_enter(JSContext *js, JSValue self, int argc, JSVal
|
||||
|
||||
static JSValue js_tracy_fiber_leave(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
#ifdef TRACY_ON_DEMAND
|
||||
if (!TracyCIsConnected)
|
||||
return JS_UNDEFINED;
|
||||
@@ -105,7 +107,6 @@ static JSValue js_tracy_zone_begin(JSContext *js, JSValue self, int argc, JSValu
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DEEP_TRACE
|
||||
const char *fn_src = JS_AtomToCString(js, js_fn_filename(js, argv[0]));
|
||||
const char *js_fn_name = get_func_name(js, argv[0]);
|
||||
const char *fn_name;
|
||||
@@ -118,14 +119,36 @@ static JSValue js_tracy_zone_begin(JSContext *js, JSValue self, int argc, JSValu
|
||||
|
||||
JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
|
||||
TracyCZoneEnd(TCTX);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SOKOL_GLCORE
|
||||
#include "glad.h"
|
||||
GLuint *ids;
|
||||
static GLsizei query_count = 64*1024;
|
||||
static int qhead = 0;
|
||||
static int qtail = 0;
|
||||
|
||||
static JSValue js_tracy_gpu_init(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
printf("GLAD LOAD %d\n", gladLoadGL());
|
||||
ids = malloc(sizeof(GLuint)*query_count);
|
||||
glGenQueries(query_count, ids); // generate new query ids
|
||||
int64_t tgpu;
|
||||
glGetInteger64v(GL_TIMESTAMP, &tgpu);
|
||||
|
||||
float period = 1.f;
|
||||
struct ___tracy_gpu_new_context_data gpuctx = {
|
||||
.gpuTime = tgpu,
|
||||
.period = period,
|
||||
.context = 0,
|
||||
.flags = 0,
|
||||
.type = 1
|
||||
};
|
||||
___tracy_emit_gpu_new_context(gpuctx);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_zone_begin(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
#ifdef TRACY_ON_DEMAND
|
||||
@@ -170,44 +193,6 @@ static JSValue js_tracy_gpu_zone_begin(JSContext *js, JSValue self, int argc, JS
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_zone_end(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
#ifdef TRACY_ON_DEMAND
|
||||
if (!TracyCIsConnected)
|
||||
return JS_UNDEFINED;
|
||||
#endif
|
||||
|
||||
glQueryCounter(ids[qhead], GL_TIMESTAMP);
|
||||
struct ___tracy_gpu_zone_end_data data = {
|
||||
.queryId = ids[qhead],
|
||||
.context = 0
|
||||
};
|
||||
___tracy_emit_gpu_zone_end(data);
|
||||
qhead = (qhead+1)%query_count;
|
||||
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_init(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
ids = malloc(sizeof(GLuint)*query_count);
|
||||
glGenQueries(query_count, ids); // generate new query ids
|
||||
int64_t tgpu;
|
||||
glGetInteger64v(GL_TIMESTAMP, &tgpu);
|
||||
|
||||
float period = 1.f;
|
||||
struct ___tracy_gpu_new_context_data gpuctx = {
|
||||
.gpuTime = tgpu,
|
||||
.period = period,
|
||||
.context = 0,
|
||||
.flags = 0,
|
||||
.type = 1
|
||||
};
|
||||
___tracy_emit_gpu_new_context(gpuctx);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
#ifdef TRACY_ON_DEMAND
|
||||
@@ -246,12 +231,62 @@ static JSValue js_tracy_gpu_collect(JSContext *js, JSValue self, int argc, JSVal
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
#elifdef SOKOL_D3D11
|
||||
static int max_queries = 64*1024;
|
||||
|
||||
static JSValue js_tracy_gpu_init(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
// D3D11_QUERY_DESC desc= {};
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_zone_begin(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_Call(js,argv[0], JS_UNDEFINED, 0, NULL);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_collect(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static JSValue js_tracy_gpu_init(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_zone_begin(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_Call(js,argv[0], JS_UNDEFINED, 0, NULL);
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_tracy_gpu_collect(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const JSCFunctionListEntry js_tracy_funcs[] = {
|
||||
JS_CFUNC_DEF("fiber", 1, js_tracy_fiber_enter),
|
||||
JS_CFUNC_DEF("fiber_leave", 1, js_tracy_fiber_leave),
|
||||
JS_CFUNC_DEF("gpu_zone", 1, js_tracy_gpu_zone_begin),
|
||||
JS_CFUNC_DEF("gpu_collect", 0, js_tracy_gpu_collect),
|
||||
JS_CFUNC_DEF("gpu_init", 0, js_tracy_gpu_init),
|
||||
JS_CFUNC_DEF("gpu_sync", 0, js_tracy_gpu_sync),
|
||||
JS_CFUNC_DEF("end_frame", 0, js_tracy_frame_mark),
|
||||
JS_CFUNC_DEF("zone", 1, js_tracy_zone_begin),
|
||||
JS_CFUNC_DEF("message", 1, js_tracy_message),
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <tracy/Tracy.hpp>
|
||||
#include <tracy/TracyOpenGL.hpp>
|
||||
|
||||
|
||||
void trace_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range *data, void *user_data)
|
||||
{
|
||||
}
|
||||
@@ -111,6 +110,7 @@ static sg_trace_hooks hooks;
|
||||
extern "C"{
|
||||
void render_trace_init()
|
||||
{
|
||||
return;
|
||||
hooks.apply_pipeline = trace_apply_pipeline;
|
||||
hooks.begin_pass = trace_begin_pass;
|
||||
SG_HOOK_SET(buffer);
|
||||
@@ -124,8 +124,6 @@ void render_trace_init()
|
||||
hooks.draw = trace_draw;
|
||||
|
||||
sg_trace_hooks hh = sg_install_trace_hooks(&hooks);
|
||||
|
||||
printf("GLAD LOAD %d\n", gladLoadGL());
|
||||
|
||||
TracyGpuContext;
|
||||
}
|
||||
|
||||
848
source/tinydir.h
Normal file
848
source/tinydir.h
Normal file
@@ -0,0 +1,848 @@
|
||||
/*
|
||||
Copyright (c) 2013-2021, tinydir authors:
|
||||
- Cong Xu
|
||||
- Lautis Sun
|
||||
- Baudouin Feildel
|
||||
- Andargor <andargor@yahoo.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TINYDIR_H
|
||||
#define TINYDIR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if ((defined _UNICODE) && !(defined UNICODE))
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#if ((defined UNICODE) && !(defined _UNICODE))
|
||||
#define _UNICODE
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _MSC_VER
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <tchar.h>
|
||||
# pragma warning(push)
|
||||
# pragma warning (disable : 4996)
|
||||
#else
|
||||
# include <dirent.h>
|
||||
# include <libgen.h>
|
||||
# include <sys/stat.h>
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
# include <tchar.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* types */
|
||||
|
||||
/* Windows UNICODE wide character support */
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
# define _tinydir_char_t TCHAR
|
||||
# define TINYDIR_STRING(s) _TEXT(s)
|
||||
# define _tinydir_strlen _tcslen
|
||||
# define _tinydir_strcpy _tcscpy
|
||||
# define _tinydir_strcat _tcscat
|
||||
# define _tinydir_strcmp _tcscmp
|
||||
# define _tinydir_strrchr _tcsrchr
|
||||
# define _tinydir_strncmp _tcsncmp
|
||||
#else
|
||||
# define _tinydir_char_t char
|
||||
# define TINYDIR_STRING(s) s
|
||||
# define _tinydir_strlen strlen
|
||||
# define _tinydir_strcpy strcpy
|
||||
# define _tinydir_strcat strcat
|
||||
# define _tinydir_strcmp strcmp
|
||||
# define _tinydir_strrchr strrchr
|
||||
# define _tinydir_strncmp strncmp
|
||||
#endif
|
||||
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
# include <windows.h>
|
||||
# define _TINYDIR_PATH_MAX MAX_PATH
|
||||
#elif defined __linux__
|
||||
# include <limits.h>
|
||||
# ifdef PATH_MAX
|
||||
# define _TINYDIR_PATH_MAX PATH_MAX
|
||||
# endif
|
||||
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
# include <sys/param.h>
|
||||
# if defined(BSD)
|
||||
# include <limits.h>
|
||||
# ifdef PATH_MAX
|
||||
# define _TINYDIR_PATH_MAX PATH_MAX
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _TINYDIR_PATH_MAX
|
||||
#define _TINYDIR_PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* extra chars for the "\\*" mask */
|
||||
# define _TINYDIR_PATH_EXTRA 2
|
||||
#else
|
||||
# define _TINYDIR_PATH_EXTRA 0
|
||||
#endif
|
||||
|
||||
#define _TINYDIR_FILENAME_MAX 256
|
||||
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
#define _TINYDIR_DRIVE_MAX 3
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _TINYDIR_FUNC static __inline
|
||||
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
|
||||
# define _TINYDIR_FUNC static __inline__
|
||||
#elif defined(__cplusplus)
|
||||
# define _TINYDIR_FUNC static inline
|
||||
#elif defined(__GNUC__)
|
||||
/* Suppress unused function warning */
|
||||
# define _TINYDIR_FUNC __attribute__((unused)) static
|
||||
#else
|
||||
# define _TINYDIR_FUNC static
|
||||
#endif
|
||||
|
||||
#if defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
|
||||
#ifdef _MSC_VER
|
||||
# define _TINYDIR_CDECL __cdecl
|
||||
#else
|
||||
# define _TINYDIR_CDECL __attribute__((cdecl))
|
||||
#endif
|
||||
#else
|
||||
# define _TINYDIR_CDECL
|
||||
#endif
|
||||
|
||||
/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
|
||||
#ifdef TINYDIR_USE_READDIR_R
|
||||
|
||||
/* readdir_r is a POSIX-only function, and may not be available under various
|
||||
* environments/settings, e.g. MinGW. Use readdir fallback */
|
||||
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\
|
||||
_POSIX_SOURCE
|
||||
# define _TINYDIR_HAS_READDIR_R
|
||||
#endif
|
||||
#if _POSIX_C_SOURCE >= 200112L
|
||||
# define _TINYDIR_HAS_FPATHCONF
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if _BSD_SOURCE || _SVID_SOURCE || \
|
||||
(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
|
||||
# define _TINYDIR_HAS_DIRFD
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\
|
||||
defined _PC_NAME_MAX
|
||||
# define _TINYDIR_USE_FPATHCONF
|
||||
#endif
|
||||
#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\
|
||||
!(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
|
||||
# define _TINYDIR_USE_READDIR
|
||||
#endif
|
||||
|
||||
/* Use readdir by default */
|
||||
#else
|
||||
# define _TINYDIR_USE_READDIR
|
||||
#endif
|
||||
|
||||
/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
|
||||
#ifndef _MSC_VER
|
||||
#if (defined __MINGW32__) && (defined _UNICODE)
|
||||
#define _TINYDIR_DIR _WDIR
|
||||
#define _tinydir_dirent _wdirent
|
||||
#define _tinydir_opendir _wopendir
|
||||
#define _tinydir_readdir _wreaddir
|
||||
#define _tinydir_closedir _wclosedir
|
||||
#else
|
||||
#define _TINYDIR_DIR DIR
|
||||
#define _tinydir_dirent dirent
|
||||
#define _tinydir_opendir opendir
|
||||
#define _tinydir_readdir readdir
|
||||
#define _tinydir_closedir closedir
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
|
||||
#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE)
|
||||
#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
|
||||
#else
|
||||
#error "Either define both alloc and free or none of them!"
|
||||
#endif
|
||||
|
||||
#if !defined(_TINYDIR_MALLOC)
|
||||
#define _TINYDIR_MALLOC(_size) malloc(_size)
|
||||
#define _TINYDIR_FREE(_ptr) free(_ptr)
|
||||
#endif /* !defined(_TINYDIR_MALLOC) */
|
||||
|
||||
typedef struct tinydir_file
|
||||
{
|
||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t name[_TINYDIR_FILENAME_MAX];
|
||||
_tinydir_char_t *extension;
|
||||
int is_dir;
|
||||
int is_reg;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#ifdef __MINGW32__
|
||||
struct _stat _s;
|
||||
#else
|
||||
struct stat _s;
|
||||
#endif
|
||||
#endif
|
||||
} tinydir_file;
|
||||
|
||||
typedef struct tinydir_dir
|
||||
{
|
||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||
int has_next;
|
||||
size_t n_files;
|
||||
|
||||
tinydir_file *_files;
|
||||
#ifdef _MSC_VER
|
||||
HANDLE _h;
|
||||
WIN32_FIND_DATA _f;
|
||||
#else
|
||||
_TINYDIR_DIR *_d;
|
||||
struct _tinydir_dirent *_e;
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
struct _tinydir_dirent *_ep;
|
||||
#endif
|
||||
#endif
|
||||
} tinydir_dir;
|
||||
|
||||
|
||||
/* declarations */
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path);
|
||||
_TINYDIR_FUNC
|
||||
void tinydir_close(tinydir_dir *dir);
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_next(tinydir_dir *dir);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i);
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i);
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path);
|
||||
_TINYDIR_FUNC
|
||||
void _tinydir_get_ext(tinydir_file *file);
|
||||
_TINYDIR_FUNC
|
||||
int _TINYDIR_CDECL _tinydir_file_cmp(const void *a, const void *b);
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
_TINYDIR_FUNC
|
||||
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* definitions*/
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
int error;
|
||||
int size; /* using int size */
|
||||
#endif
|
||||
#else
|
||||
_tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
|
||||
#endif
|
||||
_tinydir_char_t *pathp;
|
||||
|
||||
if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* initialise dir */
|
||||
dir->_files = NULL;
|
||||
#ifdef _MSC_VER
|
||||
dir->_h = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
dir->_d = NULL;
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
dir->_ep = NULL;
|
||||
#endif
|
||||
#endif
|
||||
tinydir_close(dir);
|
||||
|
||||
_tinydir_strcpy(dir->path, path);
|
||||
/* Remove trailing slashes */
|
||||
pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
|
||||
while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/')))
|
||||
{
|
||||
*pathp = TINYDIR_STRING('\0');
|
||||
pathp++;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
_tinydir_strcpy(path_buf, dir->path);
|
||||
_tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
|
||||
#if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
|
||||
dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0);
|
||||
#else
|
||||
dir->_h = FindFirstFile(path_buf, &dir->_f);
|
||||
#endif
|
||||
if (dir->_h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
errno = ENOENT;
|
||||
#else
|
||||
dir->_d = _tinydir_opendir(path);
|
||||
if (dir->_d == NULL)
|
||||
{
|
||||
#endif
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* read first file */
|
||||
dir->has_next = 1;
|
||||
#ifndef _MSC_VER
|
||||
#ifdef _TINYDIR_USE_READDIR
|
||||
dir->_e = _tinydir_readdir(dir->_d);
|
||||
#else
|
||||
/* allocate dirent buffer for readdir_r */
|
||||
size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
|
||||
if (size == -1) return -1;
|
||||
dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
|
||||
if (dir->_ep == NULL) return -1;
|
||||
|
||||
error = readdir_r(dir->_d, dir->_ep, &dir->_e);
|
||||
if (error != 0) return -1;
|
||||
#endif
|
||||
if (dir->_e == NULL)
|
||||
{
|
||||
dir->has_next = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
tinydir_close(dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
|
||||
{
|
||||
/* Count the number of files first, to pre-allocate the files array */
|
||||
size_t n_files = 0;
|
||||
if (tinydir_open(dir, path) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
while (dir->has_next)
|
||||
{
|
||||
n_files++;
|
||||
if (tinydir_next(dir) == -1)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
tinydir_close(dir);
|
||||
|
||||
if (n_files == 0 || tinydir_open(dir, path) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->n_files = 0;
|
||||
dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
|
||||
if (dir->_files == NULL)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
while (dir->has_next)
|
||||
{
|
||||
tinydir_file *p_file;
|
||||
dir->n_files++;
|
||||
|
||||
p_file = &dir->_files[dir->n_files - 1];
|
||||
if (tinydir_readfile(dir, p_file) == -1)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (tinydir_next(dir) == -1)
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Just in case the number of files has changed between the first and
|
||||
second reads, terminate without writing into unallocated memory */
|
||||
if (dir->n_files == n_files)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
tinydir_close(dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
void tinydir_close(tinydir_dir *dir)
|
||||
{
|
||||
if (dir == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset(dir->path, 0, sizeof(dir->path));
|
||||
dir->has_next = 0;
|
||||
dir->n_files = 0;
|
||||
_TINYDIR_FREE(dir->_files);
|
||||
dir->_files = NULL;
|
||||
#ifdef _MSC_VER
|
||||
if (dir->_h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose(dir->_h);
|
||||
}
|
||||
dir->_h = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
if (dir->_d)
|
||||
{
|
||||
_tinydir_closedir(dir->_d);
|
||||
}
|
||||
dir->_d = NULL;
|
||||
dir->_e = NULL;
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
_TINYDIR_FREE(dir->_ep);
|
||||
dir->_ep = NULL;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_next(tinydir_dir *dir)
|
||||
{
|
||||
if (dir == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (!dir->has_next)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
if (FindNextFile(dir->_h, &dir->_f) == 0)
|
||||
#else
|
||||
#ifdef _TINYDIR_USE_READDIR
|
||||
dir->_e = _tinydir_readdir(dir->_d);
|
||||
#else
|
||||
if (dir->_ep == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (dir->_e == NULL)
|
||||
#endif
|
||||
{
|
||||
dir->has_next = 0;
|
||||
#ifdef _MSC_VER
|
||||
if (GetLastError() != ERROR_SUCCESS &&
|
||||
GetLastError() != ERROR_NO_MORE_FILES)
|
||||
{
|
||||
tinydir_close(dir);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
|
||||
{
|
||||
const _tinydir_char_t *filename;
|
||||
if (dir == NULL || file == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
if (dir->_h == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
if (dir->_e == NULL)
|
||||
#endif
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
filename =
|
||||
#ifdef _MSC_VER
|
||||
dir->_f.cFileName;
|
||||
#else
|
||||
dir->_e->d_name;
|
||||
#endif
|
||||
if (_tinydir_strlen(dir->path) +
|
||||
_tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >=
|
||||
_TINYDIR_PATH_MAX)
|
||||
{
|
||||
/* the path for the file will be too long */
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX)
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tinydir_strcpy(file->path, dir->path);
|
||||
if (_tinydir_strcmp(dir->path, TINYDIR_STRING("/")) != 0)
|
||||
_tinydir_strcat(file->path, TINYDIR_STRING("/"));
|
||||
_tinydir_strcpy(file->name, filename);
|
||||
_tinydir_strcat(file->path, filename);
|
||||
#ifndef _MSC_VER
|
||||
#ifdef __MINGW32__
|
||||
if (_tstat(
|
||||
#elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) \
|
||||
|| ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|
||||
|| ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \
|
||||
|| ((defined __APPLE__) && (defined __MACH__)) \
|
||||
|| (defined BSD)
|
||||
if (lstat(
|
||||
#else
|
||||
if (stat(
|
||||
#endif
|
||||
file->path, &file->_s) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
_tinydir_get_ext(file);
|
||||
|
||||
file->is_dir =
|
||||
#ifdef _MSC_VER
|
||||
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
#else
|
||||
S_ISDIR(file->_s.st_mode);
|
||||
#endif
|
||||
file->is_reg =
|
||||
#ifdef _MSC_VER
|
||||
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
|
||||
(
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) &&
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
|
||||
#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
|
||||
#endif
|
||||
#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
|
||||
#endif
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) &&
|
||||
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
|
||||
#else
|
||||
S_ISREG(file->_s.st_mode);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
|
||||
{
|
||||
if (dir == NULL || file == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (i >= dir->n_files)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(file, &dir->_files[i], sizeof(tinydir_file));
|
||||
_tinydir_get_ext(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
|
||||
{
|
||||
_tinydir_char_t path[_TINYDIR_PATH_MAX];
|
||||
if (dir == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (i >= dir->n_files || !dir->_files[i].is_dir)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tinydir_strcpy(path, dir->_files[i].path);
|
||||
tinydir_close(dir);
|
||||
if (tinydir_open_sorted(dir, path) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open a single file given its path */
|
||||
_TINYDIR_FUNC
|
||||
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
|
||||
{
|
||||
tinydir_dir dir;
|
||||
int result = 0;
|
||||
int found = 0;
|
||||
_tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t file_name_buf[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t *dir_name;
|
||||
_tinydir_char_t *base_name;
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
_tinydir_char_t drive_buf[_TINYDIR_PATH_MAX];
|
||||
_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
|
||||
#endif
|
||||
|
||||
if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the parent path */
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
|
||||
errno = _tsplitpath_s(
|
||||
path,
|
||||
drive_buf, _TINYDIR_DRIVE_MAX,
|
||||
dir_name_buf, _TINYDIR_FILENAME_MAX,
|
||||
file_name_buf, _TINYDIR_FILENAME_MAX,
|
||||
ext_buf, _TINYDIR_FILENAME_MAX);
|
||||
#else
|
||||
_tsplitpath(
|
||||
path,
|
||||
drive_buf,
|
||||
dir_name_buf,
|
||||
file_name_buf,
|
||||
ext_buf);
|
||||
#endif
|
||||
|
||||
if (errno)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* _splitpath_s not work fine with only filename and widechar support */
|
||||
#ifdef _UNICODE
|
||||
if (drive_buf[0] == L'\xFEFE')
|
||||
drive_buf[0] = '\0';
|
||||
if (dir_name_buf[0] == L'\xFEFE')
|
||||
dir_name_buf[0] = '\0';
|
||||
#endif
|
||||
|
||||
/* Emulate the behavior of dirname by returning "." for dir name if it's
|
||||
empty */
|
||||
if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
|
||||
{
|
||||
_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
|
||||
}
|
||||
/* Concatenate the drive letter and dir name to form full dir name */
|
||||
_tinydir_strcat(drive_buf, dir_name_buf);
|
||||
dir_name = drive_buf;
|
||||
/* Concatenate the file name and extension to form base name */
|
||||
_tinydir_strcat(file_name_buf, ext_buf);
|
||||
base_name = file_name_buf;
|
||||
#else
|
||||
_tinydir_strcpy(dir_name_buf, path);
|
||||
dir_name = dirname(dir_name_buf);
|
||||
_tinydir_strcpy(file_name_buf, path);
|
||||
base_name = basename(file_name_buf);
|
||||
#endif
|
||||
|
||||
/* Special case: if the path is a root dir, open the parent dir as the file */
|
||||
#if (defined _MSC_VER || defined __MINGW32__)
|
||||
if (_tinydir_strlen(base_name) == 0)
|
||||
#else
|
||||
if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0)
|
||||
#endif
|
||||
{
|
||||
memset(file, 0, sizeof * file);
|
||||
file->is_dir = 1;
|
||||
file->is_reg = 0;
|
||||
_tinydir_strcpy(file->path, dir_name);
|
||||
file->extension = file->path + _tinydir_strlen(file->path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the parent directory */
|
||||
if (tinydir_open(&dir, dir_name) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read through the parent directory and look for the file */
|
||||
while (dir.has_next)
|
||||
{
|
||||
if (tinydir_readfile(&dir, file) == -1)
|
||||
{
|
||||
result = -1;
|
||||
goto bail;
|
||||
}
|
||||
if (_tinydir_strcmp(file->name, base_name) == 0)
|
||||
{
|
||||
/* File found */
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
tinydir_next(&dir);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
result = -1;
|
||||
errno = ENOENT;
|
||||
}
|
||||
|
||||
bail:
|
||||
tinydir_close(&dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
void _tinydir_get_ext(tinydir_file *file)
|
||||
{
|
||||
_tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
|
||||
if (period == NULL)
|
||||
{
|
||||
file->extension = &(file->name[_tinydir_strlen(file->name)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
file->extension = period + 1;
|
||||
}
|
||||
}
|
||||
|
||||
_TINYDIR_FUNC
|
||||
int _TINYDIR_CDECL _tinydir_file_cmp(const void *a, const void *b)
|
||||
{
|
||||
const tinydir_file *fa = (const tinydir_file *)a;
|
||||
const tinydir_file *fb = (const tinydir_file *)b;
|
||||
if (fa->is_dir != fb->is_dir)
|
||||
{
|
||||
return -(fa->is_dir - fb->is_dir);
|
||||
}
|
||||
return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#ifndef _TINYDIR_USE_READDIR
|
||||
/*
|
||||
The following authored by Ben Hutchings <ben@decadent.org.uk>
|
||||
from https://womble.decadent.org.uk/readdir_r-advisory.html
|
||||
*/
|
||||
/* Calculate the required buffer size (in bytes) for directory *
|
||||
* entries read from the given directory handle. Return -1 if this *
|
||||
* this cannot be done. *
|
||||
* *
|
||||
* This code does not trust values of NAME_MAX that are less than *
|
||||
* 255, since some systems (including at least HP-UX) incorrectly *
|
||||
* define it to be a smaller value. */
|
||||
_TINYDIR_FUNC
|
||||
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
|
||||
{
|
||||
long name_max;
|
||||
size_t name_end;
|
||||
/* parameter may be unused */
|
||||
(void)dirp;
|
||||
|
||||
#if defined _TINYDIR_USE_FPATHCONF
|
||||
name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
|
||||
if (name_max == -1)
|
||||
#if defined(NAME_MAX)
|
||||
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
||||
#else
|
||||
return (size_t)(-1);
|
||||
#endif
|
||||
#elif defined(NAME_MAX)
|
||||
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
|
||||
#else
|
||||
#error "buffer size for readdir_r cannot be determined"
|
||||
#endif
|
||||
name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
|
||||
return (name_end > sizeof(struct _tinydir_dirent) ?
|
||||
name_end : sizeof(struct _tinydir_dirent));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
# if defined (_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user