mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
131 lines
4.1 KiB
C
131 lines
4.1 KiB
C
#include "pocketpy/interpreter/vfs.h"
|
|
#include "pocketpy/interpreter/vm.h"
|
|
|
|
#define SMALLMAP_T__SOURCE
|
|
#define K c11_sv
|
|
#define V VfsEntry
|
|
#define NAME VfsDir
|
|
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
|
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
|
#include "pocketpy/xmacros/smallmap.h"
|
|
#undef SMALLMAP_T__SOURCE
|
|
|
|
static VfsEntry* Vfs__get(const char* path) {
|
|
c11_vector /*T=c11_sv*/ cpnts = c11_sv__split((c11_sv){path, strlen(path)}, '/');
|
|
|
|
VfsEntry* root = &pk_current_vm->__vfs.root;
|
|
for(int i = 0; i < cpnts.count; i++) {
|
|
c11_sv cpnt = c11__getitem(c11_sv, &cpnts, i);
|
|
VfsEntry* entry = VfsDir__try_get(&root->_dir, cpnt);
|
|
if(entry == NULL) {
|
|
c11_vector__dtor(&cpnts);
|
|
return NULL;
|
|
}
|
|
if(entry->is_file) {
|
|
VfsEntry* retval = i == cpnts.count - 1 ? entry : NULL;
|
|
c11_vector__dtor(&cpnts);
|
|
return retval;
|
|
} else {
|
|
root = entry;
|
|
}
|
|
}
|
|
c11_vector__dtor(&cpnts);
|
|
return root;
|
|
}
|
|
|
|
static void VfsDir__delete_recursively(VfsDir* self) {
|
|
for(int i = 0; i < self->count; i++) {
|
|
VfsDir_KV* kv = c11__at(VfsDir_KV, self, i);
|
|
free((char*)kv->key.data);
|
|
if(kv->value.is_file) {
|
|
free(kv->value._file.data);
|
|
} else {
|
|
VfsDir__delete_recursively(&kv->value._dir);
|
|
}
|
|
}
|
|
VfsDir__dtor(self);
|
|
}
|
|
|
|
void Vfs__ctor(Vfs* self) {
|
|
self->root.is_file = false;
|
|
VfsDir__ctor(&self->root._dir);
|
|
}
|
|
|
|
void Vfs__dtor(Vfs* self) { VfsDir__delete_recursively(&self->root._dir); }
|
|
|
|
unsigned char* py_vfsread(const char* path, int* size) {
|
|
VfsEntry* entry = Vfs__get(path);
|
|
if(entry == NULL || !entry->is_file) return NULL;
|
|
*size = entry->_file.size;
|
|
unsigned char* retval = malloc(*size);
|
|
memcpy(retval, entry->_file.data, *size);
|
|
return retval;
|
|
}
|
|
|
|
static void VfsDir__dupset(VfsDir* self, c11_sv key, VfsEntry value) {
|
|
char* p = malloc(key.size);
|
|
memcpy(p, key.data, key.size);
|
|
VfsDir__set(self, (c11_sv){p, key.size}, value);
|
|
}
|
|
|
|
bool py_vfswrite(const char* path, unsigned char* data, int size) {
|
|
c11_vector /*T=c11_sv*/ cpnts = c11_sv__split((c11_sv){path, strlen(path)}, '/');
|
|
VfsEntry* root = &pk_current_vm->__vfs.root;
|
|
for(int i = 0; i < cpnts.count; i++) {
|
|
c11_sv cpnt = c11__getitem(c11_sv, &cpnts, i);
|
|
VfsEntry* entry = VfsDir__try_get(&root->_dir, cpnt);
|
|
if(entry == NULL) {
|
|
if(i == cpnts.count - 1) {
|
|
// create file
|
|
VfsEntry entry = {
|
|
.is_file = true,
|
|
._file.size = size,
|
|
._file.data = data,
|
|
};
|
|
VfsDir__dupset(&root->_dir, cpnt, entry);
|
|
c11_vector__dtor(&cpnts);
|
|
return true;
|
|
} else {
|
|
// create missing directory
|
|
VfsEntry entry = {
|
|
.is_file = false,
|
|
};
|
|
VfsDir__ctor(&entry._dir);
|
|
VfsDir__dupset(&root->_dir, cpnt, entry);
|
|
}
|
|
} else {
|
|
if(i == cpnts.count - 1) {
|
|
if(!entry->is_file) break;
|
|
// update file
|
|
free(entry->_file.data);
|
|
entry->_file.size = size;
|
|
entry->_file.data = data;
|
|
c11_vector__dtor(&cpnts);
|
|
return true;
|
|
} else {
|
|
if(entry->is_file) break;
|
|
root = entry;
|
|
}
|
|
}
|
|
}
|
|
c11_vector__dtor(&cpnts);
|
|
return false;
|
|
}
|
|
|
|
char** py_vfslist(const char* path, int* length) {
|
|
VfsEntry* entry = Vfs__get(path);
|
|
if(entry == NULL || entry->is_file) return NULL;
|
|
*length = 0;
|
|
char** ret = malloc(sizeof(char*) * entry->_dir.count);
|
|
for(int i = 0; i < entry->_dir.count; i++) {
|
|
VfsDir_KV* child = c11__at(VfsDir_KV, &entry->_dir, i);
|
|
if(child->value.is_file) {
|
|
int size = child->key.size;
|
|
ret[i] = malloc(size + 1);
|
|
memcpy(ret[i], child->key.data, size);
|
|
ret[i][size] = '\0';
|
|
(*length)++;
|
|
}
|
|
}
|
|
return ret;
|
|
} |