WARNING: REDESIGN: REMOVED: utils module, functionality moved to rcore module: logging and file-system #4551

[utils] was created long time ago, when [rcore] contained all the platforms code, the purpose of the file was exposing basic filesystem functionality across modules and also logging mechanism but many things have changed since then and there is no need to keep using this module.

 - Logging system has been move to [rcore] module and macros are exposed through `config.h` to other modules
 - File system functionality has also been centralized in [rcore] module that along the years it was already adding more and more file-system functions, now they are all in the same module
 - Android specific code has been moved to `rcore_android.c`, it had no sense to have specific platform code in `utils`, [rcore] is responsible of all platform code.
This commit is contained in:
Ray
2026-01-10 12:13:07 +01:00
parent 2f6feb74d4
commit dd7a1948f1
22 changed files with 525 additions and 689 deletions

View File

@ -197,7 +197,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
}
var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2);
c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" });
c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c" });
if (options.rshapes) {
try c_source_files.append(b.allocator, "src/rshapes.c");

View File

@ -582,7 +582,6 @@
<ClCompile Include="..\..\..\src\rshapes.c" />
<ClCompile Include="..\..\..\src\rtext.c" />
<ClCompile Include="..\..\..\src\rtextures.c" />
<ClCompile Include="..\..\..\src\utils.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\external\cgltf.h" />

View File

@ -22,9 +22,6 @@
<ClCompile Include="..\..\..\src\rtextures.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\utils.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\platforms\rcore_android.c">
<Filter>Source Files\Platform Files</Filter>
</ClCompile>

View File

@ -658,8 +658,7 @@ endif
OBJS = rcore.o \
rshapes.o \
rtextures.o \
rtext.o \
utils.o
rtext.o
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(USE_EXTERNAL_GLFW),FALSE)
@ -758,7 +757,7 @@ endif
rcore.o : platforms/*.c
# Compile core module
rcore.o : rcore.c raylib.h rlgl.h utils.h raymath.h rcamera.h rgestures.h
rcore.o : rcore.c raylib.h rlgl.h raymath.h rcamera.h rgestures.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
# Compile rglfw module
@ -770,15 +769,11 @@ rshapes.o : rshapes.c raylib.h rlgl.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
# Compile textures module
rtextures.o : rtextures.c raylib.h rlgl.h utils.h
rtextures.o : rtextures.c raylib.h rlgl.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
# Compile text module
rtext.o : rtext.c raylib.h utils.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
# Compile utils module
utils.o : utils.c utils.h
rtext.o : rtext.c raylib.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)
# Compile models module

View File

@ -30,7 +30,7 @@
//------------------------------------------------------------------------------------
// Module selection - Some modules could be avoided
// Mandatory modules: rcore, rlgl, utils
// Mandatory modules: rcore, rlgl
//------------------------------------------------------------------------------------
#define SUPPORT_MODULE_RSHAPES 1
#define SUPPORT_MODULE_RTEXTURES 1
@ -41,6 +41,16 @@
//------------------------------------------------------------------------------------
// Module: rcore - Configuration Flags
//------------------------------------------------------------------------------------
// Standard file io library (stdio.h) included
#define SUPPORT_STANDARD_FILEIO 1
// Show TRACELOG() output messages
#define SUPPORT_TRACELOG 1
#if defined(SUPPORT_TRACELOG)
#define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
#else
#define TRACELOG(level, ...) (void)0
#endif
// Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
#define SUPPORT_CAMERA_SYSTEM 1
// Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
@ -72,7 +82,7 @@
// Support for clipboard image loading
// NOTE: Only working on SDL3, GLFW (Windows) and RGFW (Windows)
#define SUPPORT_CLIPBOARD_IMAGE 1
#define SUPPORT_CLIPBOARD_IMAGE 1
// NOTE: Clipboard image loading requires support for some image file formats
// TODO: Those defines should probably be removed from here, letting the user manage them
@ -96,6 +106,7 @@
// rcore: Configuration values
//------------------------------------------------------------------------------------
#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
#define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
@ -281,16 +292,4 @@
#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Maximum number of audio pool channels
//------------------------------------------------------------------------------------
// Module: utils - Configuration Flags
//------------------------------------------------------------------------------------
// Standard file io library (stdio.h) included
#define SUPPORT_STANDARD_FILEIO 1
// Show TRACELOG() output messages
#define SUPPORT_TRACELOG 1
// utils: Configuration values
//------------------------------------------------------------------------------------
#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
#endif // CONFIG_H

View File

@ -13,9 +13,6 @@
* - Improvement 01
* - Improvement 02
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define RCORE_PLATFORM_CUSTOM_FLAG
* Custom flag for rcore on target platform -not used-
@ -48,7 +45,11 @@
#include <android_native_app_glue.h> // Required for: android_app struct and activity management
#include <android/window.h> // Required for: AWINDOW_FLAG_FULLSCREEN definition and others
#include <android/log.h> // Required for: Android log system: __android_log_vprint()
#include <android/asset_manager.h> // Required for: AAssetManager
//#include <android/sensor.h> // Required for: Android sensors functions (accelerometer, gyroscope, light...)
#include <errno.h> // Required for: error types
#include <jni.h> // Required for: JNIEnv and JavaVM [Used in OpenURL() and GetCurrentMonitor()]
#include <EGL/egl.h> // Native platform windowing system interface
@ -269,6 +270,17 @@ static GamepadButton AndroidTranslateGamepadButton(int button);
static void SetupFramebuffer(int width, int height); // Setup main framebuffer (required by InitPlatform())
static int android_read(void *cookie, char *buf, int size);
static int android_write(void *cookie, const char *buf, int size);
static fpos_t android_seek(void *cookie, fpos_t offset, int whence);
static int android_close(void *cookie);
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only!
FILE *funopen(const void *cookie, int (*readfn)(void *, char *, int), int (*writefn)(void *, const char *, int),
fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *));
#define fopen(name, mode) android_fopen(name, mode)
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
@ -819,8 +831,6 @@ int InitPlatform(void)
// Initialize storage system
//----------------------------------------------------------------------------
InitAssetManager(platform.app->activity->assetManager, platform.app->activity->internalDataPath); // Initialize assets manager
CORE.Storage.basePath = platform.app->activity->internalDataPath; // Define base path for storage
//----------------------------------------------------------------------------
@ -1514,4 +1524,66 @@ static void SetupFramebuffer(int width, int height)
}
}
// Replacement for fopen()
// REF: https://developer.android.com/ndk/reference/group/asset
FILE *android_fopen(const char *fileName, const char *mode)
{
FILE *file = NULL;
if (mode[0] == 'w')
{
// NOTE: fopen() is mapped to android_fopen() that only grants read access to
// assets directory through AAssetManager but we want to also be able to
// write data when required using the standard stdio FILE access functions
// REF: https://stackoverflow.com/questions/11294487/android-writing-saving-files-from-native-code-only
#undef fopen
file = fopen(TextFormat("%s/%s", platform.app->activity->internalDataPath, fileName), mode);
#define fopen(name, mode) android_fopen(name, mode)
}
else
{
// NOTE: AAsset provides access to read-only asset
AAsset *asset = AAssetManager_open(platform.app->activity->assetManager, fileName, AASSET_MODE_UNKNOWN);
if (asset != NULL)
{
// Get pointer to file in the assets
file = funopen(asset, android_read, android_write, android_seek, android_close);
}
else
{
#undef fopen
// Just do a regular open if file is not found in the assets
file = fopen(TextFormat("%s/%s", platform.app->activity->internalDataPath, fileName), mode);
if (file == NULL) file = fopen(fileName, mode);
#define fopen(name, mode) android_fopen(name, mode)
}
}
return file;
}
static int android_read(void *cookie, char *data, int dataSize)
{
return AAsset_read((AAsset *)cookie, data, dataSize);
}
static int android_write(void *cookie, const char *data, int dataSize)
{
TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");
return EACCES;
}
static fpos_t android_seek(void *cookie, fpos_t offset, int whence)
{
return AAsset_seek((AAsset *)cookie, offset, whence);
}
static int android_close(void *cookie)
{
AAsset_close((AAsset *)cookie);
return 0;
}
// EOF

View File

@ -16,9 +16,6 @@
* - Improvement 01
* - Improvement 02
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define RCORE_PLATFORM_CUSTOM_FLAG
* Custom flag for rcore on target platform -not used-
@ -1364,7 +1361,6 @@ void PollInputEvents(void)
//----------------------------------------------------------------------------------
// Function wrappers around RL_*alloc macros, used by glfwInitAllocator() inside of InitPlatform()
// We need to provide these because GLFWallocator expects function pointers with specific signatures
// Similar wrappers exist in utils.c but we cannot reuse them here due to declaration mismatch
// REF: https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
static void *AllocateWrapper(size_t size, void *user)
{

View File

@ -13,10 +13,7 @@
* - TODO
*
* POSSIBLE IMPROVEMENTS:
* - TODO
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
* - TBD
*
* CONFIGURATION:
* #define RCORE_PLATFORM_RGFW

View File

@ -15,9 +15,6 @@
* - Improvement 01
* - Improvement 02
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define RCORE_PLATFORM_CUSTOM_FLAG
* Custom flag for rcore on target platform -not used-

View File

@ -13,9 +13,6 @@
* - Improvement 01
* - Improvement 02
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define RCORE_PLATFORM_CUSTOM_FLAG
* Custom flag for rcore on target platform -not used-

View File

@ -13,9 +13,6 @@
* - Improvement 01
* - Improvement 02
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define SUPPORT_SSH_KEYBOARD_RPI (Raspberry Pi only)
* Reconfigure standard input to receive key inputs, works with SSH connection

View File

@ -13,9 +13,6 @@
* - Improvement 01
* - Improvement 02
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define RCORE_PLATFORM_CUSTOM_FLAG
* Custom flag for rcore on target platform -not used-

View File

@ -12,9 +12,6 @@
* POSSIBLE IMPROVEMENTS:
* - Replace glfw3 dependency by direct browser API calls (same as library_glfw3.js)
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define RCORE_PLATFORM_CUSTOM_FLAG
* Custom flag for rcore on target platform -not used-

View File

@ -11,9 +11,6 @@
* POSSIBLE IMPROVEMENTS:
* - TBD
*
* ADDITIONAL NOTES:
* - TRACELOG() function is located in raylib [utils] module
*
* CONFIGURATION:
* #define RCORE_PLATFORM_CUSTOM_FLAG
* Custom flag for rcore on target platform -not used-

View File

@ -78,7 +78,7 @@
#if !defined(EXTERNAL_CONFIG_FLAGS)
#include "config.h" // Defines module configuration flags
#endif
#include "utils.h" // Required for: fopen() Android mapping
//#include "utils.h" // Required for: fopen() Android mapping
#endif
#if defined(SUPPORT_MODULE_RAUDIO) || defined(RAUDIO_STANDALONE)

View File

@ -1074,47 +1074,41 @@ RLAPI Matrix GetCameraMatrix(Camera camera); // Get c
RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix
// Timing-related functions
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
RLAPI int GetFPS(void); // Get current FPS
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
RLAPI int GetFPS(void); // Get current FPS
// Custom frame control functions
// NOTE: Those functions are intended for advanced users that want full control over the frame processing
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
RLAPI void PollInputEvents(void); // Register all input events
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
RLAPI void PollInputEvents(void); // Register all input events
RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
// Random values generation functions
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated
RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence
RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence
// Misc. functions
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
// NOTE: Following functions implemented in module [utils]
//------------------------------------------------------------------
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
RLAPI void MemFree(void *ptr); // Internal memory free
// Logging system
RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
// Set custom callbacks
// WARNING: Callbacks setup is intended for advanced users
RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
// Memory management, using internal allocators
RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
RLAPI void MemFree(void *ptr); // Internal memory free
// Files management functions
// File system management functions
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
@ -1122,9 +1116,14 @@ RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
RLAPI bool SaveFileText(const char *fileName, const char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
//------------------------------------------------------------------
// File system functions
// File access custom callbacks
// WARNING: Callbacks setup is intended for advanced users
RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
RLAPI int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists)
RLAPI int FileRemove(const char *fileName); // Remove file (if exists)
RLAPI int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist

View File

@ -109,11 +109,10 @@
#include "config.h" // Defines module configuration flags
#endif
#include "utils.h" // Required for: TRACELOG() macros
#include <stdlib.h> // Required for: srand(), rand(), atexit()
#include <stdio.h> // Required for: sprintf() [Used in OpenURL()]
#include <string.h> // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset()
#include <stdlib.h> // Required for: srand(), rand(), atexit(), exit()
#include <stdio.h> // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()]
#include <string.h> // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset(), strcat()
#include <stdarg.h> // Required for: va_list, va_start(), va_end() [Used in TraceLog()]
#include <time.h> // Required for: time() [Used in InitTimer()]
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
@ -217,6 +216,10 @@
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#ifndef MAX_TRACELOG_MSG_LENGTH
#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
#endif
#ifndef MAX_FILEPATH_CAPACITY
#define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath
#endif
@ -387,10 +390,18 @@ typedef struct CoreData {
//----------------------------------------------------------------------------------
RLAPI const char *raylib_version = RAYLIB_VERSION; // raylib version exported symbol, required for some bindings
CoreData CORE = { 0 }; // Global CORE state context
CoreData CORE = { 0 }; // Global CORE state context
static int logTypeLevel = LOG_INFO; // Minimum log type level
static TraceLogCallback traceLog = NULL; // TraceLog callback function pointer
static LoadFileDataCallback loadFileData = NULL; // LoadFileData callback function pointer
static SaveFileDataCallback saveFileData = NULL; // SaveFileText callback function pointer
static LoadFileTextCallback loadFileText = NULL; // LoadFileText callback function pointer
static SaveFileTextCallback saveFileText = NULL; // SaveFileText callback function pointer
#if defined(SUPPORT_SCREEN_CAPTURE)
static int screenshotCounter = 0; // Screenshots counter
static int screenshotCounter = 0; // Screenshots counter
#endif
#if defined(SUPPORT_AUTOMATION_EVENTS)
@ -1857,9 +1868,389 @@ void SetConfigFlags(unsigned int flags)
FLAG_SET(CORE.Window.flags, flags);
}
// void OpenURL(const char *url); // Defined per platform
//----------------------------------------------------------------------------------
// Module Functions Definition: File system
// Module Functions Definition: Logging system
//----------------------------------------------------------------------------------
// Set the current threshold (minimum) log level
void SetTraceLogLevel(int logType) { logTypeLevel = logType; }
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
void TraceLog(int logType, const char *text, ...)
{
#if defined(SUPPORT_TRACELOG)
// Message has level below current threshold, don't emit
if ((logType < logTypeLevel) || (text == NULL)) return;
va_list args;
va_start(args, text);
if (traceLog)
{
traceLog(logType, text, args);
va_end(args);
return;
}
#if defined(PLATFORM_ANDROID)
switch (logType)
{
case LOG_TRACE: __android_log_vprint(ANDROID_LOG_VERBOSE, "raylib", text, args); break;
case LOG_DEBUG: __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", text, args); break;
case LOG_INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", text, args); break;
case LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", text, args); break;
case LOG_ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", text, args); break;
case LOG_FATAL: __android_log_vprint(ANDROID_LOG_FATAL, "raylib", text, args); break;
default: break;
}
#else
char buffer[MAX_TRACELOG_MSG_LENGTH] = { 0 };
switch (logType)
{
case LOG_TRACE: strncpy(buffer, "TRACE: ", 8); break;
case LOG_DEBUG: strncpy(buffer, "DEBUG: ", 8); break;
case LOG_INFO: strncpy(buffer, "INFO: ", 7); break;
case LOG_WARNING: strncpy(buffer, "WARNING: ", 10); break;
case LOG_ERROR: strncpy(buffer, "ERROR: ", 8); break;
case LOG_FATAL: strncpy(buffer, "FATAL: ", 8); break;
default: break;
}
unsigned int textLength = (unsigned int)strlen(text);
memcpy(buffer + strlen(buffer), text, (textLength < (MAX_TRACELOG_MSG_LENGTH - 12))? textLength : (MAX_TRACELOG_MSG_LENGTH - 12));
strcat(buffer, "\n");
vprintf(buffer, args);
fflush(stdout);
#endif
va_end(args);
if (logType == LOG_FATAL) exit(EXIT_FAILURE); // If fatal logging, exit program
#endif // SUPPORT_TRACELOG
}
// Set custom trace log
void SetTraceLogCallback(TraceLogCallback callback)
{
traceLog = callback;
}
//----------------------------------------------------------------------------------
// Module Functions Definition: Memory management
//----------------------------------------------------------------------------------
// Internal memory allocator
// NOTE: Initializes to zero by default
void *MemAlloc(unsigned int size)
{
void *ptr = RL_CALLOC(size, 1);
return ptr;
}
// Internal memory reallocator
void *MemRealloc(void *ptr, unsigned int size)
{
void *ret = RL_REALLOC(ptr, size);
return ret;
}
// Internal memory free
void MemFree(void *ptr)
{
RL_FREE(ptr);
}
//----------------------------------------------------------------------------------
// Module Functions Definition: File System management
//----------------------------------------------------------------------------------
// Load data from file into a buffer
unsigned char *LoadFileData(const char *fileName, int *dataSize)
{
unsigned char *data = NULL;
*dataSize = 0;
if (fileName != NULL)
{
if (loadFileData)
{
data = loadFileData(fileName, dataSize);
return data;
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "rb");
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); // WARNING: ftell() returns 'long int', maximum size returned is INT_MAX (2147483647 bytes)
fseek(file, 0, SEEK_SET);
if (size > 0)
{
data = (unsigned char *)RL_CALLOC(size, sizeof(unsigned char));
if (data != NULL)
{
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
size_t count = fread(data, sizeof(unsigned char), size, file);
// WARNING: fread() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation)
// dataSize is unified along raylib as a 'int' type, so, for file-sizes > INT_MAX (2147483647 bytes) we have a limitation
if (count > 2147483647)
{
TRACELOG(LOG_WARNING, "FILEIO: [%s] File is bigger than 2147483647 bytes, avoid using LoadFileData()", fileName);
RL_FREE(data);
data = NULL;
}
else
{
*dataSize = (int)count;
if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, dataSize, count);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
}
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to allocated memory for file reading", fileName);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read file", fileName);
fclose(file);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return data;
}
// Unload file data allocated by LoadFileData()
void UnloadFileData(unsigned char *data)
{
RL_FREE(data);
}
// Save data to file from buffer
bool SaveFileData(const char *fileName, void *data, int dataSize)
{
bool success = false;
if (fileName != NULL)
{
if (saveFileData)
{
return saveFileData(fileName, data, dataSize);
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "wb");
if (file != NULL)
{
// WARNING: fwrite() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation)
// and expects a size_t input value but as dataSize is limited to INT_MAX (2147483647 bytes), there shouldn't be a problem
int count = (int)fwrite(data, sizeof(unsigned char), dataSize, file);
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
int result = fclose(file);
if (result == 0) success = true;
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return success;
}
// Export data to code (.h), returns true on success
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
{
bool success = false;
#ifndef TEXT_BYTES_PER_LINE
#define TEXT_BYTES_PER_LINE 20
#endif
// NOTE: Text data buffer size is estimated considering raw data size in bytes
// and requiring 6 char bytes for every byte: "0x00, "
char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
int byteCount = 0;
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// DataAsCode exporter v1.0 - Raw data exported as an array of bytes //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2022-2026 Ramon Santamaria (@raysan5) //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
// Get file name from path
char varFileName[256] = { 0 };
strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1);
for (int i = 0; varFileName[i] != '\0'; i++)
{
// Convert variable name to uppercase
if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
// Replace non valid character for C identifier with '_'
else if (varFileName[i] == '.' || varFileName[i] == '-' || varFileName[i] == '?' || varFileName[i] == '!' || varFileName[i] == '+') { varFileName[i] = '_'; }
}
byteCount += sprintf(txtData + byteCount, "#define %s_DATA_SIZE %i\n\n", varFileName, dataSize);
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%s_DATA_SIZE] = { ", varFileName, varFileName);
for (int i = 0; i < (dataSize - 1); i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
// NOTE: Text data size exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData);
RL_FREE(txtData);
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
return success;
}
// Load text data from file, returns a '\0' terminated string
// NOTE: text chars array should be freed manually
char *LoadFileText(const char *fileName)
{
char *text = NULL;
if (fileName != NULL)
{
if (loadFileText)
{
text = loadFileText(fileName);
return text;
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "rt");
if (file != NULL)
{
// WARNING: When reading a file as 'text' file,
// text mode causes carriage return-linefeed translation...
// ...but using fseek() should return correct byte-offset
fseek(file, 0, SEEK_END);
unsigned int size = (unsigned int)ftell(file);
fseek(file, 0, SEEK_SET);
if (size > 0)
{
text = (char *)RL_CALLOC(size + 1, sizeof(char));
if (text != NULL)
{
unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
// WARNING: \r\n is converted to \n on reading, so,
// read bytes count gets reduced by the number of lines
if (count < size) text = (char *)RL_REALLOC(text, count + 1);
// Zero-terminate the string
text[count] = '\0';
TRACELOG(LOG_INFO, "FILEIO: [%s] Text file loaded successfully", fileName);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to allocated memory for file reading", fileName);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read text file", fileName);
fclose(file);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return text;
}
// Unload file text data allocated by LoadFileText()
void UnloadFileText(char *text)
{
RL_FREE(text);
}
// Save text data to file (write), string must be '\0' terminated
bool SaveFileText(const char *fileName, const char *text)
{
bool success = false;
if (fileName != NULL)
{
if (saveFileText)
{
return saveFileText(fileName, text);
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "wt");
if (file != NULL)
{
int count = fprintf(file, "%s", text);
if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
int result = fclose(file);
if (result == 0) success = true;
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return success;
}
// File access custom callbacks
// WARNING: Callbacks setup is intended for advanced users
// Set custom file binary data loader
void SetLoadFileDataCallback(LoadFileDataCallback callback)
{
loadFileData = callback;
}
// Set custom file binary data saver
void SetSaveFileDataCallback(SaveFileDataCallback callback)
{
saveFileData = callback;
}
// Set custom file text data loader
void SetLoadFileTextCallback(LoadFileTextCallback callback)
{
loadFileText = callback;
}
// Set custom file text data saver
void SetSaveFileTextCallback(SaveFileTextCallback callback)
{
saveFileText = callback;
}
// Rename file (if exists)
// NOTE: Only rename file name required, not full path

View File

@ -49,7 +49,6 @@
#if defined(SUPPORT_MODULE_RMODELS)
#include "utils.h" // Required for: TRACELOG(), LoadFileData(), LoadFileText(), SaveFileText()
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
#include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality

View File

@ -62,7 +62,6 @@
#if defined(SUPPORT_MODULE_RTEXT)
#include "utils.h" // Required for: LoadFile*()
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro()
#include <stdlib.h> // Required for: malloc(), free()

View File

@ -70,7 +70,6 @@
#if defined(SUPPORT_MODULE_RTEXTURES)
#include "utils.h" // Required for: TRACELOG()
#include "rlgl.h" // OpenGL abstraction layer to multiple versions
#include <stdlib.h> // Required for: malloc(), calloc(), free()

View File

@ -1,514 +0,0 @@
/**********************************************************************************************
*
* raylib.utils - Some common utility functions
*
* CONFIGURATION:
* #define SUPPORT_TRACELOG
* Show TraceLog() output messages
* NOTE: By default LOG_DEBUG traces not shown
*
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2014-2026 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h" // WARNING: Required for: LogType enum
// Check if config flags have been externally provided on compilation line
#if !defined(EXTERNAL_CONFIG_FLAGS)
#include "config.h" // Defines module configuration flags
#endif
#include "utils.h"
#if defined(PLATFORM_ANDROID)
#include <errno.h> // Required for: Android error types
#include <android/log.h> // Required for: Android log system: __android_log_vprint()
#include <android/asset_manager.h> // Required for: Android assets manager: AAsset, AAssetManager_open()...
#endif
#include <stdlib.h> // Required for: exit()
#include <stdio.h> // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose()
#include <stdarg.h> // Required for: va_list, va_start(), va_end()
#include <string.h> // Required for: strcpy(), strcat()
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#ifndef MAX_TRACELOG_MSG_LENGTH
#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static int logTypeLevel = LOG_INFO; // Minimum log type level
static TraceLogCallback traceLog = NULL; // TraceLog callback function pointer
static LoadFileDataCallback loadFileData = NULL; // LoadFileData callback function pointer
static SaveFileDataCallback saveFileData = NULL; // SaveFileText callback function pointer
static LoadFileTextCallback loadFileText = NULL; // LoadFileText callback function pointer
static SaveFileTextCallback saveFileText = NULL; // SaveFileText callback function pointer
//----------------------------------------------------------------------------------
// Functions to set internal callbacks
//----------------------------------------------------------------------------------
void SetTraceLogCallback(TraceLogCallback callback) { traceLog = callback; } // Set custom trace log
void SetLoadFileDataCallback(LoadFileDataCallback callback) { loadFileData = callback; } // Set custom file data loader
void SetSaveFileDataCallback(SaveFileDataCallback callback) { saveFileData = callback; } // Set custom file data saver
void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; } // Set custom file text loader
void SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; } // Set custom file text saver
#if defined(PLATFORM_ANDROID)
static AAssetManager *assetManager = NULL; // Android assets manager pointer
static const char *internalDataPath = NULL; // Android internal data path
#endif
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID)
FILE *funopen(const void *cookie, int (*readfn)(void *, char *, int), int (*writefn)(void *, const char *, int),
fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *));
static int android_read(void *cookie, char *buf, int size);
static int android_write(void *cookie, const char *buf, int size);
static fpos_t android_seek(void *cookie, fpos_t offset, int whence);
static int android_close(void *cookie);
#endif
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Set the current threshold (minimum) log level
void SetTraceLogLevel(int logType) { logTypeLevel = logType; }
// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
void TraceLog(int logType, const char *text, ...)
{
#if defined(SUPPORT_TRACELOG)
// Message has level below current threshold, don't emit
if ((logType < logTypeLevel) || (text == NULL)) return;
va_list args;
va_start(args, text);
if (traceLog)
{
traceLog(logType, text, args);
va_end(args);
return;
}
#if defined(PLATFORM_ANDROID)
switch (logType)
{
case LOG_TRACE: __android_log_vprint(ANDROID_LOG_VERBOSE, "raylib", text, args); break;
case LOG_DEBUG: __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", text, args); break;
case LOG_INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", text, args); break;
case LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", text, args); break;
case LOG_ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", text, args); break;
case LOG_FATAL: __android_log_vprint(ANDROID_LOG_FATAL, "raylib", text, args); break;
default: break;
}
#else
char buffer[MAX_TRACELOG_MSG_LENGTH] = { 0 };
switch (logType)
{
case LOG_TRACE: strcpy(buffer, "TRACE: "); break;
case LOG_DEBUG: strcpy(buffer, "DEBUG: "); break;
case LOG_INFO: strcpy(buffer, "INFO: "); break;
case LOG_WARNING: strcpy(buffer, "WARNING: "); break;
case LOG_ERROR: strcpy(buffer, "ERROR: "); break;
case LOG_FATAL: strcpy(buffer, "FATAL: "); break;
default: break;
}
unsigned int textLength = (unsigned int)strlen(text);
memcpy(buffer + strlen(buffer), text, (textLength < (MAX_TRACELOG_MSG_LENGTH - 12))? textLength : (MAX_TRACELOG_MSG_LENGTH - 12));
strcat(buffer, "\n");
vprintf(buffer, args);
fflush(stdout);
#endif
va_end(args);
if (logType == LOG_FATAL) exit(EXIT_FAILURE); // If fatal logging, exit program
#endif // SUPPORT_TRACELOG
}
// Internal memory allocator
// NOTE: Initializes to zero by default
void *MemAlloc(unsigned int size)
{
void *ptr = RL_CALLOC(size, 1);
return ptr;
}
// Internal memory reallocator
void *MemRealloc(void *ptr, unsigned int size)
{
void *ret = RL_REALLOC(ptr, size);
return ret;
}
// Internal memory free
void MemFree(void *ptr)
{
RL_FREE(ptr);
}
// Load data from file into a buffer
unsigned char *LoadFileData(const char *fileName, int *dataSize)
{
unsigned char *data = NULL;
*dataSize = 0;
if (fileName != NULL)
{
if (loadFileData)
{
data = loadFileData(fileName, dataSize);
return data;
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "rb");
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); // WARNING: ftell() returns 'long int', maximum size returned is INT_MAX (2147483647 bytes)
fseek(file, 0, SEEK_SET);
if (size > 0)
{
data = (unsigned char *)RL_CALLOC(size, sizeof(unsigned char));
if (data != NULL)
{
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
size_t count = fread(data, sizeof(unsigned char), size, file);
// WARNING: fread() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation)
// dataSize is unified along raylib as a 'int' type, so, for file-sizes > INT_MAX (2147483647 bytes) we have a limitation
if (count > 2147483647)
{
TRACELOG(LOG_WARNING, "FILEIO: [%s] File is bigger than 2147483647 bytes, avoid using LoadFileData()", fileName);
RL_FREE(data);
data = NULL;
}
else
{
*dataSize = (int)count;
if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, dataSize, count);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
}
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to allocated memory for file reading", fileName);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read file", fileName);
fclose(file);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return data;
}
// Unload file data allocated by LoadFileData()
void UnloadFileData(unsigned char *data)
{
RL_FREE(data);
}
// Save data to file from buffer
bool SaveFileData(const char *fileName, void *data, int dataSize)
{
bool success = false;
if (fileName != NULL)
{
if (saveFileData)
{
return saveFileData(fileName, data, dataSize);
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "wb");
if (file != NULL)
{
// WARNING: fwrite() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation)
// and expects a size_t input value but as dataSize is limited to INT_MAX (2147483647 bytes), there shouldn't be a problem
int count = (int)fwrite(data, sizeof(unsigned char), dataSize, file);
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
int result = fclose(file);
if (result == 0) success = true;
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return success;
}
// Export data to code (.h), returns true on success
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
{
bool success = false;
#ifndef TEXT_BYTES_PER_LINE
#define TEXT_BYTES_PER_LINE 20
#endif
// NOTE: Text data buffer size is estimated considering raw data size in bytes
// and requiring 6 char bytes for every byte: "0x00, "
char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
int byteCount = 0;
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// DataAsCode exporter v1.0 - Raw data exported as an array of bytes //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2022-2026 Ramon Santamaria (@raysan5) //\n");
byteCount += sprintf(txtData + byteCount, "// //\n");
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
// Get file name from path
char varFileName[256] = { 0 };
strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1);
for (int i = 0; varFileName[i] != '\0'; i++)
{
// Convert variable name to uppercase
if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
// Replace non valid character for C identifier with '_'
else if (varFileName[i] == '.' || varFileName[i] == '-' || varFileName[i] == '?' || varFileName[i] == '!' || varFileName[i] == '+') { varFileName[i] = '_'; }
}
byteCount += sprintf(txtData + byteCount, "#define %s_DATA_SIZE %i\n\n", varFileName, dataSize);
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%s_DATA_SIZE] = { ", varFileName, varFileName);
for (int i = 0; i < (dataSize - 1); i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
// NOTE: Text data size exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData);
RL_FREE(txtData);
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
return success;
}
// Load text data from file, returns a '\0' terminated string
// NOTE: text chars array should be freed manually
char *LoadFileText(const char *fileName)
{
char *text = NULL;
if (fileName != NULL)
{
if (loadFileText)
{
text = loadFileText(fileName);
return text;
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "rt");
if (file != NULL)
{
// WARNING: When reading a file as 'text' file,
// text mode causes carriage return-linefeed translation...
// ...but using fseek() should return correct byte-offset
fseek(file, 0, SEEK_END);
unsigned int size = (unsigned int)ftell(file);
fseek(file, 0, SEEK_SET);
if (size > 0)
{
text = (char *)RL_CALLOC(size + 1, sizeof(char));
if (text != NULL)
{
unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
// WARNING: \r\n is converted to \n on reading, so,
// read bytes count gets reduced by the number of lines
if (count < size) text = (char *)RL_REALLOC(text, count + 1);
// Zero-terminate the string
text[count] = '\0';
TRACELOG(LOG_INFO, "FILEIO: [%s] Text file loaded successfully", fileName);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to allocated memory for file reading", fileName);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read text file", fileName);
fclose(file);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return text;
}
// Unload file text data allocated by LoadFileText()
void UnloadFileText(char *text)
{
RL_FREE(text);
}
// Save text data to file (write), string must be '\0' terminated
bool SaveFileText(const char *fileName, const char *text)
{
bool success = false;
if (fileName != NULL)
{
if (saveFileText)
{
return saveFileText(fileName, text);
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "wt");
if (file != NULL)
{
int count = fprintf(file, "%s", text);
if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
int result = fclose(file);
if (result == 0) success = true;
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
#else
TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
#endif
}
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
return success;
}
#if defined(PLATFORM_ANDROID)
// Initialize asset manager from android app
void InitAssetManager(AAssetManager *manager, const char *dataPath)
{
assetManager = manager;
internalDataPath = dataPath;
}
// Replacement for fopen()
// REF: https://developer.android.com/ndk/reference/group/asset
FILE *android_fopen(const char *fileName, const char *mode)
{
FILE *file = NULL;
if (mode[0] == 'w')
{
// NOTE: fopen() is mapped to android_fopen() that only grants read access to
// assets directory through AAssetManager but we want to also be able to
// write data when required using the standard stdio FILE access functions
// REF: https://stackoverflow.com/questions/11294487/android-writing-saving-files-from-native-code-only
#undef fopen
file = fopen(TextFormat("%s/%s", internalDataPath, fileName), mode);
#define fopen(name, mode) android_fopen(name, mode)
}
else
{
// NOTE: AAsset provides access to read-only asset
AAsset *asset = AAssetManager_open(assetManager, fileName, AASSET_MODE_UNKNOWN);
if (asset != NULL)
{
// Get pointer to file in the assets
file = funopen(asset, android_read, android_write, android_seek, android_close);
}
else
{
#undef fopen
// Just do a regular open if file is not found in the assets
file = fopen(TextFormat("%s/%s", internalDataPath, fileName), mode);
if (file == NULL) file = fopen(fileName, mode);
#define fopen(name, mode) android_fopen(name, mode)
}
}
return file;
}
#endif // PLATFORM_ANDROID
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID)
static int android_read(void *cookie, char *data, int dataSize)
{
return AAsset_read((AAsset *)cookie, data, dataSize);
}
static int android_write(void *cookie, const char *data, int dataSize)
{
TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");
return EACCES;
}
static fpos_t android_seek(void *cookie, fpos_t offset, int whence)
{
return AAsset_seek((AAsset *)cookie, offset, whence);
}
static int android_close(void *cookie)
{
AAsset_close((AAsset *)cookie);
return 0;
}
#endif // PLATFORM_ANDROID

View File

@ -1,74 +0,0 @@
/**********************************************************************************************
*
* raylib.utils - Some common utility functions
*
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2014-2026 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef UTILS_H
#define UTILS_H
#if defined(PLATFORM_ANDROID)
#include <stdio.h> // Required for: FILE
#include <android/asset_manager.h> // Required for: AAssetManager
#endif
#if defined(SUPPORT_TRACELOG)
#define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
#else
#define TRACELOG(level, ...) (void)0
#endif
//----------------------------------------------------------------------------------
// Some basic Defines
//----------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID)
#define fopen(name, mode) android_fopen(name, mode)
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
//...
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// Nop...
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
#if defined(__cplusplus)
extern "C" { // Prevents name mangling of functions
#endif
#if defined(PLATFORM_ANDROID)
void InitAssetManager(AAssetManager *manager, const char *dataPath); // Initialize asset manager from android app
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only!
#endif
#if defined(__cplusplus)
}
#endif
#endif // UTILS_H