Don't read from file until mju_readResource is called.
PiperOrigin-RevId: 615434757 Change-Id: I96a1e77f74203e91bc62dc24ac9225810fcacb20
This commit is contained in:
committed by
Copybara-Service
parent
40baa51072
commit
0d16587135
@@ -35,12 +35,17 @@
|
|||||||
#include "engine/engine_plugin.h"
|
#include "engine/engine_plugin.h"
|
||||||
#include "engine/engine_util_errmem.h"
|
#include "engine/engine_util_errmem.h"
|
||||||
|
|
||||||
|
// internal helper for mju_fileToMemory (closes fp automatically)
|
||||||
|
static void* _fileToMemory(FILE* fp, const char* filename, size_t* filesize);
|
||||||
|
|
||||||
// file buffer used internally for the OS filesystem
|
// file buffer used internally for the OS filesystem
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
FILE* fp; // file handle
|
||||||
|
int is_read; // set to nonzero if buffer was read into
|
||||||
uint8_t* buffer; // raw bytes from file
|
uint8_t* buffer; // raw bytes from file
|
||||||
size_t nbuffer; // size of buffer in bytes
|
size_t nbuffer; // size of buffer in bytes
|
||||||
time_t mtime; // last modified time
|
time_t mtime; // last modified time
|
||||||
} file_buffer;
|
} file_spec;
|
||||||
|
|
||||||
// open the given resource; if the name doesn't have a prefix matching with a
|
// open the given resource; if the name doesn't have a prefix matching with a
|
||||||
// resource provider, then the OS filesystem is used
|
// resource provider, then the OS filesystem is used
|
||||||
@@ -89,10 +94,13 @@ mjResource* mju_openResource(const char* name, char* error, size_t error_sz) {
|
|||||||
|
|
||||||
// lastly fallback to OS filesystem
|
// lastly fallback to OS filesystem
|
||||||
resource->provider = NULL;
|
resource->provider = NULL;
|
||||||
resource->data = mju_malloc(sizeof(file_buffer));
|
resource->data = mju_malloc(sizeof(file_spec));
|
||||||
file_buffer* fb = (file_buffer*) resource->data;
|
file_spec* spec = (file_spec*) resource->data;
|
||||||
fb->buffer = mju_fileToMemory(name, &(fb->nbuffer));
|
spec->is_read = 0;
|
||||||
if (fb->buffer == NULL) {
|
spec->buffer = NULL;
|
||||||
|
spec->nbuffer = 0;
|
||||||
|
spec->fp = fopen(name, "rb");
|
||||||
|
if (!spec->fp) {
|
||||||
if (error) {
|
if (error) {
|
||||||
snprintf(error, error_sz,
|
snprintf(error, error_sz,
|
||||||
"resource not found via provider or OS filesystem: '%s'", name);
|
"resource not found via provider or OS filesystem: '%s'", name);
|
||||||
@@ -102,12 +110,13 @@ mjResource* mju_openResource(const char* name, char* error, size_t error_sz) {
|
|||||||
}
|
}
|
||||||
struct stat file_stat;
|
struct stat file_stat;
|
||||||
if (stat(name, &file_stat) == 0) {
|
if (stat(name, &file_stat) == 0) {
|
||||||
memcpy(&fb->mtime, &file_stat.st_mtime, sizeof(time_t));
|
memcpy(&spec->mtime, &file_stat.st_mtime, sizeof(time_t));
|
||||||
} else {
|
} else {
|
||||||
memset(&fb->mtime, 0, sizeof(time_t));
|
memset(&spec->mtime, 0, sizeof(time_t));
|
||||||
resource->timestamp[0] = '\0';
|
resource->timestamp[0] = '\0';
|
||||||
}
|
}
|
||||||
strftime(resource->timestamp, 512, "%Y-%m-%d-%H:%M:%S", localtime(&(fb->mtime)));
|
strftime(resource->timestamp, 512, "%Y-%m-%d-%H:%M:%S",
|
||||||
|
localtime(&(spec->mtime)));
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,10 +133,10 @@ void mju_closeResource(mjResource* resource) {
|
|||||||
resource->provider->close(resource);
|
resource->provider->close(resource);
|
||||||
} else {
|
} else {
|
||||||
// clear OS filesystem if present
|
// clear OS filesystem if present
|
||||||
file_buffer* fb = (file_buffer*) resource->data;
|
file_spec* spec = (file_spec*) resource->data;
|
||||||
if (fb) {
|
if (spec) {
|
||||||
if (fb->buffer) mju_free(fb->buffer);
|
if (spec->buffer) mju_free(spec->buffer);
|
||||||
mju_free(fb);
|
mju_free(spec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,9 +160,19 @@ int mju_readResource(mjResource* resource, const void** buffer) {
|
|||||||
|
|
||||||
|
|
||||||
// if provider is NULL, then OS filesystem is used
|
// if provider is NULL, then OS filesystem is used
|
||||||
const file_buffer* fb = (file_buffer*) resource->data;
|
file_spec* spec = (file_spec*) resource->data;
|
||||||
*buffer = fb->buffer;
|
if (!spec->fp && !spec->is_read) {
|
||||||
return fb->nbuffer;
|
mjERROR("internal error FILE pointer undefined"); // should not occur
|
||||||
|
}
|
||||||
|
|
||||||
|
// only read once from file
|
||||||
|
if (!spec->is_read) {
|
||||||
|
spec->buffer = _fileToMemory(spec->fp, resource->name, &(spec->nbuffer));
|
||||||
|
spec->fp = NULL; // closed by _fileToMemory
|
||||||
|
spec->is_read = 1;
|
||||||
|
}
|
||||||
|
*buffer = spec->buffer;
|
||||||
|
return spec->nbuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -181,11 +200,11 @@ void mju_getResourceDir(mjResource* resource, const char** dir, int* ndir) {
|
|||||||
|
|
||||||
|
|
||||||
// modified callback for OS filesystem
|
// modified callback for OS filesystem
|
||||||
static int mju_isModifiedFile(const char* name, const file_buffer* fb) {
|
static int mju_isModifiedFile(const char* name, const file_spec* spec) {
|
||||||
if (fb != NULL) {
|
if (spec != NULL) {
|
||||||
struct stat file_stat;
|
struct stat file_stat;
|
||||||
if (stat(name, &file_stat) == 0) {
|
if (stat(name, &file_stat) == 0) {
|
||||||
return difftime(fb->mtime, file_stat.st_mtime) < 0;
|
return difftime(spec->mtime, file_stat.st_mtime) < 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1; // modified (default)
|
return 1; // modified (default)
|
||||||
@@ -205,7 +224,7 @@ int mju_isModifiedResource(const mjResource* resource, const char* timestamp) {
|
|||||||
return 1; // default (modified)
|
return 1; // default (modified)
|
||||||
}
|
}
|
||||||
|
|
||||||
return mju_isModifiedFile(resource->name, (file_buffer*) resource->data);
|
return mju_isModifiedFile(resource->name, (file_spec*) resource->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -230,13 +249,19 @@ int mju_dirnamelen(const char* path) {
|
|||||||
|
|
||||||
// read file into memory buffer (allocated here with mju_malloc)
|
// read file into memory buffer (allocated here with mju_malloc)
|
||||||
void* mju_fileToMemory(const char* filename, size_t* filesize) {
|
void* mju_fileToMemory(const char* filename, size_t* filesize) {
|
||||||
// open file
|
|
||||||
*filesize = 0;
|
|
||||||
FILE* fp = fopen(filename, "rb");
|
FILE* fp = fopen(filename, "rb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return _fileToMemory(fp, filename, filesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal helper for mju_fileToMemory (closes fp automatically)
|
||||||
|
static void* _fileToMemory(FILE* fp, const char* filename, size_t* filesize) {
|
||||||
|
// open file
|
||||||
|
*filesize = 0;
|
||||||
|
|
||||||
// find size
|
// find size
|
||||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|||||||
Reference in New Issue
Block a user