bbccf7f0ba
Don't expect the vulkan headers to be present on the development system. Instead, download the using meson wrap. Signed-off-by: Piotr Krygier <piotrkrygier@everyonecancode.xyz>
202 lines
5.2 KiB
C
202 lines
5.2 KiB
C
#include "file_utils.h"
|
|
|
|
#define CGLTF_IMPLEMENTATION
|
|
#include "cgltf.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "SDL3/SDL_log.h"
|
|
#include "commons.h"
|
|
#include "errors_common.h"
|
|
|
|
#ifdef __linux__
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#endif /* ifndef __linux */
|
|
|
|
static rse_err_t get_curr_path(char* path)
|
|
{
|
|
char* last_sep = NULL;
|
|
char* tmp_path = NULL;
|
|
size_t path_length = 0U;
|
|
ssize_t binary_path_length = 0U;
|
|
size_t directory_path_length = 0U;
|
|
|
|
if (NULL == path) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to get path. Provided pointer is NULL");
|
|
|
|
return RSE_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
path_length = strlen(path);
|
|
if (path_length > MAX_PATH_LENGTH) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Max path length cannot be 0");
|
|
|
|
return RSE_ERROR_INVALID_PARAM;
|
|
}
|
|
|
|
rse_memset(path, '\0', path_length);
|
|
rse_malloc(tmp_path, MAX_PATH_LENGTH);
|
|
|
|
#ifdef __linux__
|
|
binary_path_length = readlink("/proc/self/exe", tmp_path, MAX_PATH_LENGTH - 1);
|
|
if (binary_path_length == -1) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to read current binary path");
|
|
|
|
return RSE_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
tmp_path[binary_path_length] = '\0';
|
|
#endif /* ifdef __linux__ */
|
|
|
|
last_sep = strrchr(tmp_path, '/') + 1;
|
|
|
|
if (NULL == last_sep) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to get last separator in path");
|
|
|
|
return RSE_ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
directory_path_length = last_sep - tmp_path;
|
|
|
|
if (directory_path_length > MAX_PATH_LENGTH) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Provided path buffer is too small");
|
|
|
|
return RSE_ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
strncpy(path, tmp_path, directory_path_length);
|
|
|
|
free(tmp_path);
|
|
|
|
return RSE_ERROR_NO_ERROR;
|
|
}
|
|
|
|
rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size)
|
|
{
|
|
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
|
size_t curr_path_length = 0U;
|
|
size_t file_path_length = 0U;
|
|
char curr_path[MAX_PATH_LENGTH] = {0};
|
|
char temp_path[MAX_PATH_LENGTH] = {0};
|
|
|
|
file_path_length = strlen(file_path);
|
|
|
|
if (file_path_length > max_buffer_size) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided max_buffer_size is smaller than the file path itself");
|
|
|
|
return RSE_ERROR_INVALID_PARAM;
|
|
}
|
|
|
|
if ((ret = get_curr_path(curr_path)) != RSE_ERROR_NO_ERROR) {
|
|
return ret;
|
|
}
|
|
|
|
curr_path_length = strlen(curr_path);
|
|
|
|
if ((curr_path_length + file_path_length) > max_buffer_size) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
|
|
"Provided max_buffer_size is to small to hold concatenated file path. %ld vs %ld",
|
|
(curr_path_length + file_path_length),
|
|
max_buffer_size);
|
|
}
|
|
|
|
strncpy(temp_path, file_path, MAX_PATH_LENGTH);
|
|
|
|
memset(file_path, 0, max_buffer_size);
|
|
|
|
strncat(file_path, curr_path, max_buffer_size);
|
|
strncat(file_path, temp_path, max_buffer_size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
rse_err_t file_read_bytes(const char* file_name, size_t* bytes_count, unsigned char* buffer)
|
|
{
|
|
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
|
FILE* file = NULL;
|
|
char real_path[MAX_PATH_LENGTH] = {0};
|
|
|
|
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
|
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
|
return ret;
|
|
}
|
|
|
|
file = fopen(real_path, "rb");
|
|
|
|
if (file == NULL) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to open file for read: %s", real_path);
|
|
ret = RSE_ERROR_INTERNAL_ERROR;
|
|
|
|
return ret;
|
|
}
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
*bytes_count = ftell(file);
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
if (buffer == NULL) {
|
|
goto file_close;
|
|
}
|
|
|
|
fread(buffer, *bytes_count, 1, file);
|
|
if (ferror(file) != 0) {
|
|
perror("Error reading file");
|
|
|
|
ret = RSE_ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
file_close:
|
|
fclose(file);
|
|
|
|
return ret;
|
|
}
|
|
|
|
rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer)
|
|
{
|
|
FILE* file = NULL;
|
|
char real_path[MAX_PATH_LENGTH] = {0};
|
|
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
|
|
|
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
|
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
|
return ret;
|
|
}
|
|
|
|
file = fopen(real_path, "wb");
|
|
|
|
if (file == NULL) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to open file for write: %s", file_name);
|
|
return RSE_ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
fwrite(buffer, bytes_count, 1, file);
|
|
fclose(file);
|
|
|
|
return ret;
|
|
}
|
|
|
|
rse_err_t file_load_gltf(const char* file_name, cgltf_data** data)
|
|
{
|
|
char real_path[MAX_PATH_LENGTH] = {0};
|
|
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
|
cgltf_options options = {0};
|
|
|
|
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
|
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
|
return ret;
|
|
}
|
|
|
|
if (cgltf_parse_file(&options, real_path, data) != cgltf_result_success) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to parse GLTF data");
|
|
|
|
return RSE_ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
return ret;
|
|
}
|