From 23bde477e56714c4d10e017abad00401207c1a12 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 27 Feb 2020 13:18:15 +0100 Subject: [PATCH] REDESIGN: LoadStorageValue()/SaveStorageValue() Using new file I/O ABI --- examples/core/core_storage_values.c | 13 ++-- src/config.h | 2 + src/core.c | 96 ++++++++++++++++------------- src/utils.c | 7 ++- 4 files changed, 68 insertions(+), 50 deletions(-) diff --git a/examples/core/core_storage_values.c b/examples/core/core_storage_values.c index df757a4fd..02e4c2625 100644 --- a/examples/core/core_storage_values.c +++ b/examples/core/core_storage_values.c @@ -12,7 +12,10 @@ #include "raylib.h" // NOTE: Storage positions must start with 0, directly related to file memory layout -typedef enum { STORAGE_SCORE = 0, STORAGE_HISCORE } StorageData; +typedef enum { + STORAGE_POSITION_SCORE = 0, + STORAGE_POSITION_HISCORE = 1 +} StorageData; int main(void) { @@ -43,14 +46,14 @@ int main(void) if (IsKeyPressed(KEY_ENTER)) { - SaveStorageValue(STORAGE_SCORE, score); - SaveStorageValue(STORAGE_HISCORE, hiscore); + SaveStorageValue(STORAGE_POSITION_SCORE, score); + SaveStorageValue(STORAGE_POSITION_HISCORE, hiscore); } else if (IsKeyPressed(KEY_SPACE)) { // NOTE: If requested position could not be found, value 0 is returned - score = LoadStorageValue(STORAGE_SCORE); - hiscore = LoadStorageValue(STORAGE_HISCORE); + score = LoadStorageValue(STORAGE_POSITION_SCORE); + hiscore = LoadStorageValue(STORAGE_POSITION_HISCORE); } framesCounter++; diff --git a/src/config.h b/src/config.h index 91e0decf6..9367faa70 100644 --- a/src/config.h +++ b/src/config.h @@ -60,6 +60,8 @@ //#define SUPPORT_HIGH_DPI 1 // Support CompressData() and DecompressData() functions #define SUPPORT_COMPRESSION_API 1 +#define SUPPORT_DATA_STORAGE 1 +// Support saving binary data automatically to a generated storage.data file. This file is managed internally. //------------------------------------------------------------------------------------ // Module: rlgl - Configuration Flags diff --git a/src/core.c b/src/core.c index fa5b748f1..2f130555f 100644 --- a/src/core.c +++ b/src/core.c @@ -82,6 +82,9 @@ * provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module * for linkage * +* #define SUPPORT_DATA_STORAGE +* Support saving binary data automatically to a generated storage.data file. This file is managed internally. +* * DEPENDENCIES: * rglfw - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX. FreeBSD, OpenBSD, NetBSD, DragonFly) * raymath - 3D math functionality (Vector2, Vector3, Matrix, Quaternion) @@ -152,7 +155,6 @@ #endif #include // Required for: srand(), rand(), atexit() -#include // Required for: FILE, fopen(), fseek(), fread(), fwrite(), fclose() [Used in SaveStorageValue()/LoadStorageValue()] #include // Required for: strrchr(), strcmp(), strlen() #include // Required for: time() [Used in InitTimer()] #include // Required for: tan() [Used in BeginMode3D()] @@ -283,12 +285,14 @@ #endif #define MAX_GAMEPADS 4 // Max number of gamepads supported -#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad) #define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad) +#define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad) #define MAX_CHARS_QUEUE 16 // Max number of characters in the input queue -#define STORAGE_FILENAME "storage.data" +#if defined(SUPPORT_DATA_STORAGE) + #define STORAGE_DATA_FILE "storage.data" +#endif //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -2182,40 +2186,50 @@ unsigned char *DecompressData(unsigned char *compData, int compDataLength, int * // NOTE: Storage positions is directly related to file memory layout (4 bytes each integer) void SaveStorageValue(int position, int value) { - FILE *storageFile = NULL; - +#if defined(SUPPORT_DATA_STORAGE) char path[512] = { 0 }; #if defined(PLATFORM_ANDROID) strcpy(path, CORE.Android.internalDataPath); strcat(path, "/"); - strcat(path, STORAGE_FILENAME); + strcat(path, STORAGE_DATA_FILE); #else - strcpy(path, STORAGE_FILENAME); + strcpy(path, STORAGE_DATA_FILE); #endif - // Try open existing file to append data - storageFile = fopen(path, "rb+"); - - // If file doesn't exist, create a new storage data file - if (!storageFile) storageFile = fopen(path, "wb"); - - if (!storageFile) TRACELOG(LOG_WARNING, "Storage data file could not be created"); - else + int dataSize = 0; + unsigned char *fileData = LoadFileData(path, &dataSize); + + if (fileData != NULL) { - // Get file size - fseek(storageFile, 0, SEEK_END); - int fileSize = ftell(storageFile); // Size in bytes - fseek(storageFile, 0, SEEK_SET); - - if (fileSize < (position*sizeof(int))) TRACELOG(LOG_WARNING, "Storage position could not be found"); + if (dataSize <= (position*sizeof(int))) + { + // Increase data size up to position and store value + dataSize = (position + 1)*sizeof(int); + fileData = (unsigned char *)RL_REALLOC(fileData, dataSize); + int *dataPtr = (int *)fileData; + dataPtr[position] = value; + } else { - fseek(storageFile, (position*sizeof(int)), SEEK_SET); - fwrite(&value, 1, sizeof(int), storageFile); + // Replace value on selected position + int *dataPtr = (int *)fileData; + dataPtr[position] = value; } - - fclose(storageFile); + + SaveFileData(path, fileData, dataSize); + RL_FREE(fileData); } + else + { + dataSize = (position + 1)*sizeof(int); + fileData = (unsigned char *)RL_MALLOC(dataSize); + int *dataPtr = (int *)fileData; + dataPtr[position] = value; + + SaveFileData(path, fileData, dataSize); + RL_FREE(fileData); + } +#endif } // Load integer value from storage file (from defined position) @@ -2223,37 +2237,31 @@ void SaveStorageValue(int position, int value) int LoadStorageValue(int position) { int value = 0; - +#if defined(SUPPORT_DATA_STORAGE) char path[512] = { 0 }; #if defined(PLATFORM_ANDROID) strcpy(path, CORE.Android.internalDataPath); strcat(path, "/"); - strcat(path, STORAGE_FILENAME); + strcat(path, STORAGE_DATA_FILE); #else - strcpy(path, STORAGE_FILENAME); + strcpy(path, STORAGE_DATA_FILE); #endif - // Try open existing file to append data - FILE *storageFile = fopen(path, "rb"); - - if (!storageFile) TRACELOG(LOG_WARNING, "Storage data file could not be found"); - else + int dataSize = 0; + unsigned char *fileData = LoadFileData(path, &dataSize); + + if (fileData != NULL) { - // Get file size - fseek(storageFile, 0, SEEK_END); - int fileSize = ftell(storageFile); // Size in bytes - fseek(storageFile, 0, SEEK_SET); // Reset file pointer - - if (fileSize < (position*4)) TRACELOG(LOG_WARNING, "Storage position could not be found"); + if (dataSize < (position*4)) TRACELOG(LOG_WARNING, "Storage position could not be found"); else { - fseek(storageFile, (position*4), SEEK_SET); - fread(&value, 4, 1, storageFile); // Read 1 element of 4 bytes size + int *dataPtr = (int *)fileData; + value = dataPtr[position]; } - - fclose(storageFile); + + RL_FREE(fileData); } - +#endif return value; } diff --git a/src/utils.c b/src/utils.c index 5d8f92b46..302bc6913 100644 --- a/src/utils.c +++ b/src/utils.c @@ -173,6 +173,8 @@ unsigned char *LoadFileData(const char *fileName, int *bytesRead) if (file != NULL) { + // WARNING: On binary streams SEEK_END could not be found, + // using fseek() and ftell() could not work in some (rare) cases fseek(file, 0, SEEK_END); int size = ftell(file); fseek(file, 0, SEEK_SET); @@ -180,10 +182,13 @@ unsigned char *LoadFileData(const char *fileName, int *bytesRead) if (size > 0) { data = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*size); + + // NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements] int count = fread(data, sizeof(unsigned char), size, file); *bytesRead = count; - if (count != size) TRACELOG(LOG_WARNING, "[%s] File partially read", fileName); + if (count != size) TRACELOG(LOG_WARNING, "[%s] File partially loaded", fileName); + else TRACELOG(LOG_INFO, "[%s] File loaded successfully", fileName); } else TRACELOG(LOG_WARNING, "[%s] File could not be read", fileName);