Wise&mystical  1.0
Project about Europe
Loading...
Searching...
No Matches
utils.c
Go to the documentation of this file.
1
33#include "raylib.h" // WARNING: Required for: LogType enum
34
35// Check if config flags have been externally provided on compilation line
36#if !defined(EXTERNAL_CONFIG_FLAGS)
37 #include "config.h" // Defines module configuration flags
38#endif
39
40#include "utils.h"
41
42#if defined(PLATFORM_ANDROID)
43 #include <errno.h> // Required for: Android error types
44 #include <android/log.h> // Required for: Android log system: __android_log_vprint()
45 #include <android/asset_manager.h> // Required for: Android assets manager: AAsset, AAssetManager_open(), ...
46#endif
47
48#include <stdlib.h> // Required for: exit()
49#include <stdio.h> // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose()
50#include <stdarg.h> // Required for: va_list, va_start(), va_end()
51#include <string.h> // Required for: strcpy(), strcat()
52
53//----------------------------------------------------------------------------------
54// Defines and Macros
55//----------------------------------------------------------------------------------
56#ifndef MAX_TRACELOG_MSG_LENGTH
57 #define MAX_TRACELOG_MSG_LENGTH 128 // Max length of one trace-log message
58#endif
59
60//----------------------------------------------------------------------------------
61// Global Variables Definition
62//----------------------------------------------------------------------------------
63static int logTypeLevel = LOG_INFO; // Minimum log type level
64
65static TraceLogCallback traceLog = NULL; // TraceLog callback function pointer
66static LoadFileDataCallback loadFileData = NULL; // LoadFileData callback funtion pointer
67static SaveFileDataCallback saveFileData = NULL; // SaveFileText callback funtion pointer
68static LoadFileTextCallback loadFileText = NULL; // LoadFileText callback funtion pointer
69static SaveFileTextCallback saveFileText = NULL; // SaveFileText callback funtion pointer
70
71//----------------------------------------------------------------------------------
72// Functions to set internal callbacks
73//----------------------------------------------------------------------------------
74void SetTraceLogCallback(TraceLogCallback callback) { traceLog = callback; } // Set custom trace log
75void SetLoadFileDataCallback(LoadFileDataCallback callback) { loadFileData = callback; } // Set custom file data loader
76void SetSaveFileDataCallback(SaveFileDataCallback callback) { saveFileData = callback; } // Set custom file data saver
77void SetLoadFileTextCallback(LoadFileTextCallback callback) { loadFileText = callback; } // Set custom file text loader
78void SetSaveFileTextCallback(SaveFileTextCallback callback) { saveFileText = callback; } // Set custom file text saver
79
80
81#if defined(PLATFORM_ANDROID)
82static AAssetManager *assetManager = NULL; // Android assets manager pointer
83static const char *internalDataPath = NULL; // Android internal data path
84#endif
85
86//----------------------------------------------------------------------------------
87// Module specific Functions Declaration
88//----------------------------------------------------------------------------------
89#if defined(PLATFORM_ANDROID)
90FILE *funopen(const void *cookie, int (*readfn)(void *, char *, int), int (*writefn)(void *, const char *, int),
91 fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *));
92
93static int android_read(void *cookie, char *buf, int size);
94static int android_write(void *cookie, const char *buf, int size);
95static fpos_t android_seek(void *cookie, fpos_t offset, int whence);
96static int android_close(void *cookie);
97#endif
98
99//----------------------------------------------------------------------------------
100// Module Functions Definition - Utilities
101//----------------------------------------------------------------------------------
102
103// Set the current threshold (minimum) log level
104void SetTraceLogLevel(int logType) { logTypeLevel = logType; }
105
106// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
107void TraceLog(int logType, const char *text, ...)
108{
109#if defined(SUPPORT_TRACELOG)
110 // Message has level below current threshold, don't emit
111 if (logType < logTypeLevel) return;
112
113 va_list args;
114 va_start(args, text);
115
116 if (traceLog)
117 {
118 traceLog(logType, text, args);
119 va_end(args);
120 return;
121 }
122
123#if defined(PLATFORM_ANDROID)
124 switch (logType)
125 {
126 case LOG_TRACE: __android_log_vprint(ANDROID_LOG_VERBOSE, "raylib", text, args); break;
127 case LOG_DEBUG: __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", text, args); break;
128 case LOG_INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", text, args); break;
129 case LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", text, args); break;
130 case LOG_ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", text, args); break;
131 case LOG_FATAL: __android_log_vprint(ANDROID_LOG_FATAL, "raylib", text, args); break;
132 default: break;
133 }
134#else
135 char buffer[MAX_TRACELOG_MSG_LENGTH] = { 0 };
136
137 switch (logType)
138 {
139 case LOG_TRACE: strcpy(buffer, "TRACE: "); break;
140 case LOG_DEBUG: strcpy(buffer, "DEBUG: "); break;
141 case LOG_INFO: strcpy(buffer, "INFO: "); break;
142 case LOG_WARNING: strcpy(buffer, "WARNING: "); break;
143 case LOG_ERROR: strcpy(buffer, "ERROR: "); break;
144 case LOG_FATAL: strcpy(buffer, "FATAL: "); break;
145 default: break;
146 }
147
148 strcat(buffer, text);
149 strcat(buffer, "\n");
150 vprintf(buffer, args);
151#endif
152
153 va_end(args);
154
155 if (logType == LOG_FATAL) exit(EXIT_FAILURE); // If fatal logging, exit program
156
157#endif // SUPPORT_TRACELOG
158}
159
160// Internal memory allocator
161// NOTE: Initializes to zero by default
162void *MemAlloc(int size)
163{
164 void *ptr = RL_CALLOC(size, 1);
165 return ptr;
166}
167
168// Internal memory reallocator
169void *MemRealloc(void *ptr, int size)
170{
171 void *ret = RL_REALLOC(ptr, size);
172 return ret;
173}
174
175// Internal memory free
176void MemFree(void *ptr)
177{
178 RL_FREE(ptr);
179}
180
181// Load data from file into a buffer
182unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
183{
184 unsigned char *data = NULL;
185 *bytesRead = 0;
186
187 if (fileName != NULL)
188 {
189 if (loadFileData)
190 {
191 data = loadFileData(fileName, bytesRead);
192 return data;
193 }
194#if defined(SUPPORT_STANDARD_FILEIO)
195 FILE *file = fopen(fileName, "rb");
196
197 if (file != NULL)
198 {
199 // WARNING: On binary streams SEEK_END could not be found,
200 // using fseek() and ftell() could not work in some (rare) cases
201 fseek(file, 0, SEEK_END);
202 int size = ftell(file);
203 fseek(file, 0, SEEK_SET);
204
205 if (size > 0)
206 {
207 data = (unsigned char *)RL_MALLOC(size*sizeof(unsigned char));
208
209 // NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
210 unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
211 *bytesRead = count;
212
213 if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
214 else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
215 }
216 else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read file", fileName);
217
218 fclose(file);
219 }
220 else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
221#else
222 TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
223#endif
224 }
225 else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
226
227 return data;
228}
229
230// Unload file data allocated by LoadFileData()
231void UnloadFileData(unsigned char *data)
232{
233 RL_FREE(data);
234}
235
236// Save data to file from buffer
237bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
238{
239 bool success = false;
240
241 if (fileName != NULL)
242 {
243 if (saveFileData)
244 {
245 return saveFileData(fileName, data, bytesToWrite);
246 }
247#if defined(SUPPORT_STANDARD_FILEIO)
248 FILE *file = fopen(fileName, "wb");
249
250 if (file != NULL)
251 {
252 unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), bytesToWrite, file);
253
254 if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
255 else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
256 else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
257
258 int result = fclose(file);
259 if (result == 0) success = true;
260 }
261 else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
262#else
263 TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
264#endif
265 }
266 else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
267
268 return success;
269}
270
271// Export data to code (.h), returns true on success
272bool ExportDataAsCode(const char *data, unsigned int size, const char *fileName)
273{
274 bool success = false;
275
276#ifndef TEXT_BYTES_PER_LINE
277 #define TEXT_BYTES_PER_LINE 20
278#endif
279
280 // NOTE: Text data buffer size is estimated considering raw data size in bytes
281 // and requiring 6 char bytes for every byte: "0x00, "
282 char *txtData = (char *)RL_CALLOC(size*6 + 2000, sizeof(char));
283
284 int byteCount = 0;
285 byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
286 byteCount += sprintf(txtData + byteCount, "// //\n");
287 byteCount += sprintf(txtData + byteCount, "// DataAsCode exporter v1.0 - Raw data exported as an array of bytes //\n");
288 byteCount += sprintf(txtData + byteCount, "// //\n");
289 byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
290 byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
291 byteCount += sprintf(txtData + byteCount, "// //\n");
292 byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2022 Ramon Santamaria (@raysan5) //\n");
293 byteCount += sprintf(txtData + byteCount, "// //\n");
294 byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
295
296 // Get file name from path and convert variable name to uppercase
297 char varFileName[256] = { 0 };
298 strcpy(varFileName, GetFileNameWithoutExt(fileName));
299 for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
300
301 byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, size);
302 for (int i = 0; i < size - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
303 byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[size - 1]);
304
305 // NOTE: Text data size exported is determined by '\0' (NULL) character
306 success = SaveFileText(fileName, txtData);
307
308 RL_FREE(txtData);
309
310 if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
311 else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
312
313 return success;
314}
315
316// Load text data from file, returns a '\0' terminated string
317// NOTE: text chars array should be freed manually
318char *LoadFileText(const char *fileName)
319{
320 char *text = NULL;
321
322 if (fileName != NULL)
323 {
324 if (loadFileText)
325 {
326 text = loadFileText(fileName);
327 return text;
328 }
329#if defined(SUPPORT_STANDARD_FILEIO)
330 FILE *file = fopen(fileName, "rt");
331
332 if (file != NULL)
333 {
334 // WARNING: When reading a file as 'text' file,
335 // text mode causes carriage return-linefeed translation...
336 // ...but using fseek() should return correct byte-offset
337 fseek(file, 0, SEEK_END);
338 unsigned int size = (unsigned int)ftell(file);
339 fseek(file, 0, SEEK_SET);
340
341 if (size > 0)
342 {
343 text = (char *)RL_MALLOC((size + 1)*sizeof(char));
344 unsigned int count = (unsigned int)fread(text, sizeof(char), size, file);
345
346 // WARNING: \r\n is converted to \n on reading, so,
347 // read bytes count gets reduced by the number of lines
348 if (count < size) text = RL_REALLOC(text, count + 1);
349
350 // Zero-terminate the string
351 text[count] = '\0';
352
353 TRACELOG(LOG_INFO, "FILEIO: [%s] Text file loaded successfully", fileName);
354 }
355 else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read text file", fileName);
356
357 fclose(file);
358 }
359 else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
360#else
361 TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
362#endif
363 }
364 else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
365
366 return text;
367}
368
369// Unload file text data allocated by LoadFileText()
370void UnloadFileText(char *text)
371{
372 RL_FREE(text);
373}
374
375// Save text data to file (write), string must be '\0' terminated
376bool SaveFileText(const char *fileName, char *text)
377{
378 bool success = false;
379
380 if (fileName != NULL)
381 {
382 if (saveFileText)
383 {
384 return saveFileText(fileName, text);
385 }
386#if defined(SUPPORT_STANDARD_FILEIO)
387 FILE *file = fopen(fileName, "wt");
388
389 if (file != NULL)
390 {
391 int count = fprintf(file, "%s", text);
392
393 if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
394 else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
395
396 int result = fclose(file);
397 if (result == 0) success = true;
398 }
399 else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
400#else
401 TRACELOG(LOG_WARNING, "FILEIO: Standard file io not supported, use custom file callback");
402#endif
403 }
404 else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
405
406 return success;
407}
408
409#if defined(PLATFORM_ANDROID)
410// Initialize asset manager from android app
411void InitAssetManager(AAssetManager *manager, const char *dataPath)
412{
413 assetManager = manager;
414 internalDataPath = dataPath;
415}
416
417// Replacement for fopen()
418// Ref: https://developer.android.com/ndk/reference/group/asset
419FILE *android_fopen(const char *fileName, const char *mode)
420{
421 if (mode[0] == 'w')
422 {
423 // fopen() is mapped to android_fopen() that only grants read access to
424 // assets directory through AAssetManager but we want to also be able to
425 // write data when required using the standard stdio FILE access functions
426 // Ref: https://stackoverflow.com/questions/11294487/android-writing-saving-files-from-native-code-only
427 #undef fopen
428 return fopen(TextFormat("%s/%s", internalDataPath, fileName), mode);
429 #define fopen(name, mode) android_fopen(name, mode)
430 }
431 else
432 {
433 // NOTE: AAsset provides access to read-only asset
434 AAsset *asset = AAssetManager_open(assetManager, fileName, AASSET_MODE_UNKNOWN);
435
436 if (asset != NULL)
437 {
438 // Get pointer to file in the assets
439 return funopen(asset, android_read, android_write, android_seek, android_close);
440 }
441 else
442 {
443 #undef fopen
444 // Just do a regular open if file is not found in the assets
445 return fopen(TextFormat("%s/%s", internalDataPath, fileName), mode);
446 #define fopen(name, mode) android_fopen(name, mode)
447 }
448 }
449}
450#endif // PLATFORM_ANDROID
451
452//----------------------------------------------------------------------------------
453// Module specific Functions Definition
454//----------------------------------------------------------------------------------
455#if defined(PLATFORM_ANDROID)
456static int android_read(void *cookie, char *buf, int size)
457{
458 return AAsset_read((AAsset *)cookie, buf, size);
459}
460
461static int android_write(void *cookie, const char *buf, int size)
462{
463 TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");
464
465 return EACCES;
466}
467
468static fpos_t android_seek(void *cookie, fpos_t offset, int whence)
469{
470 return AAsset_seek((AAsset *)cookie, offset, whence);
471}
472
473static int android_close(void *cookie)
474{
475 AAsset_close((AAsset *)cookie);
476 return 0;
477}
478#endif // PLATFORM_ANDROID
#define MAX_TRACELOG_MSG_LENGTH
Definition: config.h:244
#define NULL
Definition: miniaudio.h:3718
#define RL_FREE(p)
Definition: raudio.h:67
#define RL_MALLOC(sz)
raudio v1.0 - A simple and easy-to-use audio library based on miniaudio
Definition: raudio.h:61
#define RL_CALLOC(n, sz)
Definition: raudio.h:64
#define TRACELOG(level,...)
Definition: raygui.h:222
RLAPI const char * TextFormat(const char *text,...)
Definition: rtext.c:1278
bool(* SaveFileDataCallback)(const char *fileName, void *data, unsigned int bytesToWrite)
Definition: raylib.h:892
unsigned char *(* LoadFileDataCallback)(const char *fileName, unsigned int *bytesRead)
Definition: raylib.h:891
@ LOG_ERROR
Definition: raylib.h:516
@ LOG_TRACE
Definition: raylib.h:512
@ LOG_INFO
Definition: raylib.h:514
@ LOG_WARNING
Definition: raylib.h:515
@ LOG_DEBUG
Definition: raylib.h:513
@ LOG_FATAL
Definition: raylib.h:517
#define RL_REALLOC(ptr, sz)
Definition: raylib.h:120
char *(* LoadFileTextCallback)(const char *fileName)
Definition: raylib.h:893
bool(* SaveFileTextCallback)(const char *fileName, char *text)
Definition: raylib.h:894
RLAPI const char * GetFileNameWithoutExt(const char *filePath)
Definition: rcore.c:2911
void(* TraceLogCallback)(int logLevel, const char *text, va_list args)
Definition: raylib.h:890
void UnloadFileText(char *text)
Definition: utils.c:370
char * LoadFileText(const char *fileName)
Definition: utils.c:318
void SetLoadFileTextCallback(LoadFileTextCallback callback)
Definition: utils.c:77
void SetTraceLogCallback(TraceLogCallback callback)
Definition: utils.c:74
unsigned char * LoadFileData(const char *fileName, unsigned int *bytesRead)
Definition: utils.c:182
void UnloadFileData(unsigned char *data)
Definition: utils.c:231
void MemFree(void *ptr)
Definition: utils.c:176
bool ExportDataAsCode(const char *data, unsigned int size, const char *fileName)
Definition: utils.c:272
void SetTraceLogLevel(int logType)
Definition: utils.c:104
void SetLoadFileDataCallback(LoadFileDataCallback callback)
Definition: utils.c:75
void TraceLog(int logType, const char *text,...)
Definition: utils.c:107
void * MemRealloc(void *ptr, int size)
Definition: utils.c:169
#define TEXT_BYTES_PER_LINE
bool SaveFileText(const char *fileName, char *text)
Definition: utils.c:376
void * MemAlloc(int size)
Definition: utils.c:162
void SetSaveFileTextCallback(SaveFileTextCallback callback)
Definition: utils.c:78
void SetSaveFileDataCallback(SaveFileDataCallback callback)
Definition: utils.c:76
bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
Definition: utils.c:237