├── .gitignore ├── LICENSE ├── README.md ├── logo └── mic_logo.png └── src └── mic.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ray 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # mic (make-it-c) 4 | A simple and easy-to-use library to build pipelines in C 5 | 6 |
7 | 8 | This library provides a set of platform-independant functions intended to be used for pipelines definition. The goal of the project is allow to define pipelines just coding them in plain C, using all the benefits provided by the language itself (variables definition, conditional branching, loops, preprocessor...) and combine that with some useful functions to deal with the file system, with text files, with timming and other elements related to processes automation. 9 | 10 | **WARNING: This project is a work-in-progress, not usable yet** 11 | 12 | ## Features 13 | 14 | - Plain C library 15 | - Self-contained: No external dependencies 16 | - Portable: Single-file header-only 17 | - Multi-platform 18 | 19 | ## Functionality provided 20 | 21 | - Log system 22 | - Environment 23 | - Processes execution 24 | - Timming management 25 | - File system management 26 | - String management 27 | - Others 28 | 29 | ## License 30 | 31 | mic (make-it-c) is licensed under an unmodified MIT license, which is an OSI-certified, BSD-like license that allows static linking with closed source software. Check [LICENSE](LICENSE) for further details. 32 | -------------------------------------------------------------------------------- /logo/mic_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raysan5/mic/27b4a6bc44ecf501efc8da31571f14b7189ec44a/logo/mic_logo.png -------------------------------------------------------------------------------- /src/mic.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * mic (make-it-c) - A simple and easy-to-use library to build pipelines in C 4 | * 5 | * NOTES: 6 | * Memory footprint of this library is aproximately xxx bytes (global variables) 7 | * 8 | * CONFIGURATION: 9 | * 10 | * #define MIC_IMPLEMENTATION 11 | * Generates the implementation of the library into the included file. 12 | * If not defined, the library is in header only mode and can be included in other headers 13 | * or source files without problems. But only ONE file should hold the implementation. 14 | * 15 | * #define MIC_xxxx 16 | * If defined, the library can... 17 | * 18 | * DEPENDENCIES: 19 | * None. 20 | * 21 | * CONTRIBUTORS: 22 | * Ramon Santamaria: Main developer, maintainer 23 | * 24 | * 25 | * LICENSE: MIT License 26 | * 27 | * Copyright (c) 2021 Ramon Santamaria (@raysan5) 28 | * 29 | * Permission is hereby granted, free of charge, to any person obtaining a copy 30 | * of this software and associated documentation files (the "Software"), to deal 31 | * in the Software without restriction, including without limitation the rights 32 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 | * copies of the Software, and to permit persons to whom the Software is 34 | * furnished to do so, subject to the following conditions: 35 | * 36 | * The above copyright notice and this permission notice shall be included in all 37 | * copies or substantial portions of the Software. 38 | * 39 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 45 | * SOFTWARE. 46 | * 47 | **********************************************************************************************/ 48 | 49 | #ifndef MIC_H 50 | #define MIC_H 51 | 52 | #ifndef MICAPI 53 | #define MICAPI // We are building or using the library as a static library (or Linux shared library) 54 | #endif 55 | 56 | #if defined(_WIN32) 57 | #if defined(BUILD_LIBTYPE_SHARED) 58 | #define MICAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) 59 | #elif defined(USE_LIBTYPE_SHARED) 60 | #define MICAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) 61 | #endif 62 | #endif 63 | 64 | // Support TRACELOG macros 65 | #ifndef TRACELOG 66 | #define TRACELOG(level, ...) micTraceLog(level, __VA_ARGS__) 67 | #define TRACELOGD(...) (void)0 68 | #endif 69 | 70 | // Allow custom memory allocators 71 | #ifndef MIC_MALLOC 72 | #define MIC_MALLOC(sz) malloc(sz) 73 | #endif 74 | #ifndef MIC_CALLOC 75 | #define MIC_CALLOC(n,sz) calloc(n,sz) 76 | #endif 77 | #ifndef MIC_REALLOC 78 | #define MIC_REALLOC(n,sz) realloc(n,sz) 79 | #endif 80 | #ifndef MIC_FREE 81 | #define MIC_FREE(p) free(p) 82 | #endif 83 | 84 | #define MIC_STRING_STATIC_MAX_SIZE 2048 85 | 86 | 87 | //---------------------------------------------------------------------------------- 88 | // Defines and Macros 89 | //---------------------------------------------------------------------------------- 90 | //... 91 | 92 | //---------------------------------------------------------------------------------- 93 | // Types and Structures Definition 94 | //---------------------------------------------------------------------------------- 95 | // Trace log level 96 | // NOTE: Organized by priority level 97 | typedef enum { 98 | MIC_LOG_ALL = 0, // Display all logs 99 | MIC_LOG_TRACE, // Trace logging, intended for internal use only 100 | MIC_LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds 101 | MIC_LOG_INFO, // Info logging, used for program execution info 102 | MIC_LOG_WARNING, // Warning logging, used on recoverable failures 103 | MIC_LOG_ERROR, // Error logging, used on unrecoverable failures 104 | MIC_LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE) 105 | MIC_LOG_NONE // Disable logging 106 | } micTraceLogLevel; 107 | 108 | // Environment info 109 | typedef enum { 110 | MIC_ENV_INFO_OS, 111 | MIC_ENV_INFO_OS_VERSION, 112 | MIC_ENV_INFO_PLATFORM, 113 | MIC_ENV_INFO_MACHINE_NAME, 114 | } micEnvInfo; 115 | 116 | // Callbacks to hook some internal functions 117 | typedef void (*micTraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages 118 | 119 | //---------------------------------------------------------------------------------- 120 | // Module Functions Declaration 121 | //---------------------------------------------------------------------------------- 122 | 123 | #ifdef __cplusplus 124 | extern "C" { // Prevents name mangling of functions 125 | #endif 126 | 127 | // Log System 128 | MICAPI void micTraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) 129 | MICAPI void micSetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level 130 | MICAPI void micSetTraceLogCallback(micTraceLogCallback callback); // Set custom trace log 131 | 132 | // Environment 133 | MICAPI void micSetEnvironmentFlags(unsigned int flags); // Setup environment config flags 134 | MICAPI void micSetEnvironmentPath(const char *path); // Set environment path (added to system PATH) 135 | MICAPI const char *micGetEnvironmentInfo(int info); // Get environment info: enum micEnvInfo 136 | 137 | // Processes execution 138 | MICAPI void micBeginProcess(const char *description, int level); // [!] Begin a new process -> Not sure yet how use this, maybe just for logging... 139 | MICAPI void micEndProcess(void); // End current process 140 | MICAPI void micBeginStep(const char *description, int level); // [!] Begin a new process step -> Not sure yet how use it 141 | MICAPI void micEndStep(void); // End current step 142 | 143 | MICAPI int micExecuteCommand(const char *command, ...); // Execute command line command, parameters passed as additional arguments 144 | MICAPI int micExecuteMIC(const char *micFile); // Compile and execute another mic file 145 | //MICAPI void micPrintMessage(const char *message, ...); // [!] Probably not required -> Just use printf() 146 | 147 | // Timming 148 | MICAPI void micInitTimer(void); // [!] Initialize internal timer -> Support multiple timers? 149 | MICAPI double micGetTime(void); // Get elapsed time in seconds since micInitTimer() 150 | MICAPI long micGetTimeStamp(void); // Get current date and time (now) 151 | MICAPI const char *micGetTimeStampString(long timestamp); // [!] Get timestamp as a string -> format? or just let the user manage it? 152 | MICAPI int micWaitTime(int milliseconds); // Wait (sleep) a specific amount of time 153 | 154 | // File system: Edition 155 | MICAPI int micCreateFile(const char *fileName); // Create an empty file, useful for further filling 156 | MICAPI int micDeleteFile(const char *fileName); // Delete an existing file 157 | MICAPI int micRenameFile(const char *fileName); // Rename an existing file 158 | MICAPI int micCopyFile(const char *srcFileName, const char *dstPathFileName); // Copy an existing file to a new path and filename 159 | MICAPI int micMoveFile(const char *srcFileName, const char *dstpathFileName); // Move an existing file to a new path and filename 160 | 161 | MICAPI int micMakeDirectory(const char *dirPathName); // Create an empty directory 162 | MICAPI int micDeleteDirectory(const char *dirPath); // Delete an existing and empty directory 163 | MICAPI int micRenameDirectory(const char *dirPath); // Rename an existing directory 164 | MICAPI int micCopyDirectory(const char *srcDirPath, const char *dstDirPath); // Copy an existing directory to a new path 165 | MICAPI int micMoveDirectory(const char *srcDirPath, const char *dstDirPath); // Move an existing directory to a new path 166 | 167 | // File system: Query 168 | MICAPI bool micIsFileAvailable(const char *fileName); // Check if a file exists 169 | MICAPI bool micIsDirectoryAvailable(const char *dirPath); // Check if a directory path exists 170 | 171 | MICAPI const char *micGetWorkingDirectory(void); // Get current working directory (uses static string) 172 | MICAPI bool micChangeDirectory(const char *dirPath); // Change working directory, return true on success 173 | 174 | MICAPI int micGetFileSize(const char *fileName); 175 | MICAPI long micGetFileModTime(const char *fileName); // Get file modification time (last write time) 176 | MICAPI bool micIsFileExtension(const char *fileName, const char *ext); // Check file extension (including point: .png, .wav) 177 | MICAPI const char *micGetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png') 178 | MICAPI const char *micGetFileName(const char *filePath); // Get pointer to filename for a path string 179 | MICAPI const char *micGetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string) 180 | MICAPI const char *micGetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string) 181 | MICAPI const char *micGetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) 182 | MICAPI const char *micGetFileFullPath(const char *fileName); // Get full path for a file 183 | MICAPI const char *micGetFileRelativePath(const char *fileName, const char *refPath); 184 | MICAPI long micGetFileInfo(int info) // MIC_FILE_INFO_TIME_CREATION, MIC_FILE_INFO_TIME_LAST_ACCESS, MIC_FILE_INFO_TIME_LAST_WRITE 185 | 186 | MICAPI int micGetDirectorySize(const char *dirPath); // Get directory byte size (for all files contained) 187 | MICAPI char **micGetDirectoryFiles(const char *dirPath, int *count); // Get filenames in a directory path (memory should be freed) 188 | MICAPI void micClearDirectoryFiles(void); // Clear directory files paths buffers (free memory) 189 | 190 | // String management (no UTF-8 strings, only byte chars) 191 | // NOTE: Some strings allocate memory internally for returned strings -> REVIEW 192 | MICAPI int micStringCopy(char *dstStr, const char *srcStr); // Copy one string to another, returns bytes copied 193 | MICAPI bool micStringEqual(const char *str1, const char *str2); // Check if two string are equal 194 | MICAPI unsigned int micStringSize(const char *str); // Get string size in bytes, checks for '\0' ending 195 | MICAPI const char *micStringFormat(const char *str, ...); // String formatting with variables (sprintf() style) 196 | MICAPI const char *micStringSubstring(const char *str, int position, int length); // Get a piece of a string 197 | MICAPI char *micStringReplace(char *str, const char *replace, const char *by); // Replace string (WARNING: memory must be freed!) 198 | MICAPI char *micStringInsert(const char *str, const char *insert, int position); // Insert string in a position (WARNING: memory must be freed!) 199 | MICAPI const char *micStringJoin(const char **strList, int count, const char *delimiter); // Join strings with delimiter 200 | MICAPI const char **micStringSplit(const char *str, char delimiter, int *count); // Split string into multiple strings 201 | MICAPI void micStringAppend(char *str, const char *append, int *position); // Append string at specific position and move cursor! 202 | MICAPI int micStringFindIndex(const char *str, const char *find); // Find first string occurrence within a string 203 | MICAPI const char *micStringToUpper(const char *str); // Get upper case version of provided string 204 | MICAPI const char *micStringToLower(const char *str); // Get lower case version of provided string 205 | MICAPI const char *micStringToPascal(const char *str); // Get Pascal case notation version of provided string 206 | MICAPI int micStringToInteger(const char *str); // Get integer value from string (negative values not supported) 207 | MICAPI bool micStringContains(const char *str, const char *contain); // Check if a string contains another string 208 | MICAPI bool micStringStartsWith(const char *str, const char *start); // Check if a string starts with another prefix string 209 | 210 | // Misc functions 211 | MICAPI bool micSaveStorageValue(unsigned int position, int value); // Save integer value to storage file (to defined position), returns true on success 212 | MICAPI int micLoadStorageValue(unsigned int position); // Load integer value from storage file (from defined position) 213 | 214 | MICAPI int micGetRandomValue(int min, int max); // Get a random value between min and max (both included) 215 | MICAPI void micSetRandomSeed(unsigned int seed); // Set the seed for the random number generator 216 | 217 | MICAPI unsigned char *micLoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read) 218 | MICAPI void micUnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() 219 | MICAPI bool micSaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success 220 | MICAPI char *micLoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string 221 | MICAPI void micUnloadFileText(char *text); // Unload file text data allocated by LoadFileText() 222 | MICAPI bool micSaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success 223 | 224 | MICAPI int micZipFile(const char *srcFileName, const char *dstFileName); // Compress file into a .zip 225 | MICAPI int micZipDirectory(const char *srcPath, const char *dstFileName); // Compress directory into a .zip 226 | 227 | MICAPI unsigned char *micCompressData(unsigned char *data, int dataLength, int *compDataLength); // Compress data (DEFLATE algorithm) 228 | MICAPI unsigned char *micDecompressData(unsigned char *compData, int compDataLength, int *dataLength); // Decompress data (DEFLATE algorithm) 229 | 230 | #ifdef __cplusplus 231 | } 232 | #endif 233 | 234 | #endif // MIC_H 235 | 236 | 237 | /*********************************************************************************** 238 | * 239 | * MIC IMPLEMENTATION 240 | * 241 | ************************************************************************************/ 242 | 243 | #if defined(MIC_IMPLEMENTATION) 244 | 245 | #include 246 | #include // Required for: setenv() 247 | #include // Required for: sinf(), cosf(), sqrtf() 248 | 249 | #include // Required for: execv() 250 | 251 | #include 252 | #include 253 | #include 254 | 255 | #if defined(_WIN32) 256 | #include // Required for: _getch(), _chdir() 257 | #define GETCWD _getcwd // NOTE: MSDN recommends not to use getcwd(), chdir() 258 | #define CHDIR _chdir 259 | #include // Required for: _access() [Used in FileExists()] 260 | #else 261 | #include // Required for: getch(), chdir() (POSIX), access() 262 | #define GETCWD getcwd 263 | #define CHDIR chdir 264 | #endif 265 | 266 | #if defined(_WIN32) 267 | #if defined(__cplusplus) 268 | extern "C" { // Prevents name mangling of functions 269 | #endif 270 | // Functions required to query time on Windows 271 | int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); 272 | int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); 273 | #if defined(__cplusplus) 274 | } 275 | #endif 276 | #elif defined(__linux__) 277 | #if _POSIX_C_SOURCE < 199309L 278 | #undef _POSIX_C_SOURCE 279 | #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. 280 | #endif 281 | #include // Required for: timespec 282 | #include // Required for: clock_gettime() 283 | 284 | #include // Required for: sqrtf(), atan2f() 285 | #endif 286 | #if defined(__APPLE__) // macOS also defines __MACH__ 287 | #include // Required for: clock_get_time() 288 | #include // Required for: mach_timespec_t 289 | #endif 290 | 291 | //---------------------------------------------------------------------------------- 292 | // Defines and Macros 293 | //---------------------------------------------------------------------------------- 294 | //... 295 | 296 | //---------------------------------------------------------------------------------- 297 | // Types and Structures Definition (internal) 298 | //---------------------------------------------------------------------------------- 299 | typedef struct micData { 300 | int logTypeLevel; 301 | TraceLogCallback traceLog; 302 | 303 | 304 | } micData; 305 | 306 | //---------------------------------------------------------------------------------- 307 | // Global Variables Definition 308 | //---------------------------------------------------------------------------------- 309 | micData MIC = { 0 }; 310 | 311 | //---------------------------------------------------------------------------------- 312 | // Module internal Functions Declaration 313 | //---------------------------------------------------------------------------------- 314 | //... 315 | 316 | //---------------------------------------------------------------------------------- 317 | // Module Functions Definition 318 | //---------------------------------------------------------------------------------- 319 | 320 | // Log System 321 | //---------------------------------------------------------------------------------- 322 | 323 | // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...) 324 | void micTraceLog(int logLevel, const char *text, ...) 325 | { 326 | // Message has level below current threshold, don't emit 327 | if (logLevel < MIC.logTypeLevel) return; 328 | 329 | va_list args; 330 | va_start(args, text); 331 | 332 | if (MIC.traceLog) 333 | { 334 | Mic.traceLog(logLevel, text, args); 335 | va_end(args); 336 | return; 337 | } 338 | 339 | char buffer[MAX_TRACELOG_MSG_LENGTH] = { 0 }; 340 | 341 | switch (logLevel) 342 | { 343 | case MIC_LOG_TRACE: strcpy(buffer, "TRACE: "); break; 344 | case MIC_LOG_DEBUG: strcpy(buffer, "DEBUG: "); break; 345 | case MIC_LOG_INFO: strcpy(buffer, "INFO: "); break; 346 | case MIC_LOG_WARNING: strcpy(buffer, "WARNING: "); break; 347 | case MIC_LOG_ERROR: strcpy(buffer, "ERROR: "); break; 348 | case MIC_LOG_FATAL: strcpy(buffer, "FATAL: "); break; 349 | default: break; 350 | } 351 | 352 | strcat(buffer, text); 353 | strcat(buffer, "\n"); 354 | vprintf(buffer, args); 355 | 356 | va_end(args); 357 | 358 | if (logLevel == LOG_FATAL) exit(EXIT_FAILURE); // If fatal logging, exit program 359 | } 360 | 361 | // Set the current threshold (minimum) log level 362 | void micSetTraceLogLevel(int logLevel) 363 | { 364 | MIC.logTypeLevel = logLevel; 365 | } 366 | 367 | // Set custom trace log 368 | void micSetTraceLogCallback(micTraceLogCallback callback) 369 | { 370 | MIC.traceLog = callback; 371 | } 372 | 373 | // Environment 374 | //---------------------------------------------------------------------------------- 375 | 376 | // Setup environment config flags 377 | void micSetEnvironmentFlags(unsigned int flags) 378 | { 379 | //setenv("VARNAME", "VARVALUE", 1); // overwrite = 1 380 | //int setenv(const char *envname, const char *envval, int overwrite); 381 | //EINVAL: The name argument is a null pointer, points to an empty string, or points to a string containing an '=' character. 382 | //ENOMEM: Insufficient memory was available to add a variable or its value to the environment. 383 | 384 | //char *getenv(const char *name); 385 | //If the specified name cannot be found in the environment of the calling process, a null pointer shall be returned. 386 | } 387 | 388 | // Set environment path (added to system PATH) 389 | void micSetEnvironmentPath(const char *path) 390 | { 391 | 392 | } 393 | 394 | // Get environment info: enum micEnvInfo 395 | const char *micGetEnvironmentInfo(int info) 396 | { 397 | static char buffer[256] = { 0 }; 398 | 399 | switch (info) 400 | { 401 | case MIC_ENV_INFO_OS: break; 402 | case MIC_ENV_INFO_OS_VERSION: break; 403 | case MIC_ENV_INFO_PLATFORM: break; 404 | case MIC_ENV_INFO_MACHINE_NAME: break; 405 | default: break; 406 | } 407 | 408 | return buffer; 409 | } 410 | 411 | // Processes execution 412 | //---------------------------------------------------------------------------------- 413 | 414 | // [!] Begin a new process -> Not sure yet how use this, maybe just for logging... 415 | void micBeginProcess(const char *description, int level) 416 | { 417 | 418 | } 419 | 420 | // End current process 421 | void micEndProcess(void) 422 | { 423 | 424 | } 425 | 426 | // [!] Begin a new process step -> Not sure yet how use it 427 | void micBeginStep(const char *description, int level) 428 | { 429 | 430 | } 431 | 432 | // End current step 433 | void micEndStep(void) 434 | { 435 | 436 | } 437 | 438 | // Execute command line command, parameters passed as additional arguments 439 | int micExecuteCommand(const char *command, ...) 440 | { 441 | static char fullCmd[256] = { 0 }; //(char *)MIC_CALLOC(256, sizeof(char)); 442 | 443 | va_list args; 444 | va_start(args, text); 445 | 446 | strcpy(fullCmd, "%s ", command); 447 | vprintf(buffer, args); 448 | 449 | va_end(args); 450 | 451 | system(cmd); 452 | //MIC_FREE(cmd); 453 | 454 | //execv(args[0], args); 455 | } 456 | 457 | // Compile and execute another mic file 458 | int micExecuteMIC(const char *micFile) 459 | { 460 | 461 | } 462 | 463 | // Timming 464 | //---------------------------------------------------------------------------------- 465 | // [!] Initialize internal timer -> Support multiple timers? 466 | void micInitTimer(void) 467 | { 468 | // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. 469 | // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. 470 | // High resolutions can also prevent the CPU power management system from entering power-saving modes. 471 | // Setting a higher resolution does not improve the accuracy of the high-resolution performance counter. 472 | #if defined(_WIN32) && defined(SUPPORT_WINMM_HIGHRES_TIMER) && !defined(SUPPORT_BUSY_WAIT_LOOP) 473 | timeBeginPeriod(1); // Setup high-resolution timer to 1ms (granularity of 1-2 ms) 474 | #endif 475 | 476 | #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) 477 | struct timespec now = { 0 }; 478 | 479 | if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success 480 | { 481 | MIC.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; 482 | } 483 | else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available"); 484 | #endif 485 | 486 | MIC.Time.previous = micGetTime(); // Get time as double 487 | } 488 | 489 | // Get elapsed time in seconds since micInitTimer() 490 | // Time measure returned are milliseconds 491 | double micGetTime(void) 492 | { 493 | double time = 0; 494 | 495 | #if defined(_WIN32) 496 | unsigned long long int clockFrequency, currentTime; 497 | 498 | QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! 499 | QueryPerformanceCounter(¤tTime); 500 | 501 | time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds 502 | #endif 503 | 504 | #if defined(__linux__) 505 | // NOTE: Only for Linux-based systems 506 | struct timespec now; 507 | clock_gettime(CLOCK_MONOTONIC, &now); 508 | unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds 509 | 510 | time = ((double)nowTime/1000000.0); // Time in miliseconds 511 | #endif 512 | 513 | #if defined(__APPLE__) 514 | //#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01 515 | //#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time 516 | 517 | clock_serv_t cclock; 518 | mach_timespec_t now; 519 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); 520 | 521 | // NOTE: OS X does not have clock_gettime(), using clock_get_time() 522 | clock_get_time(cclock, &now); 523 | mach_port_deallocate(mach_task_self(), cclock); 524 | unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds 525 | 526 | time = ((double)nowTime/1000000.0); // Time in miliseconds 527 | #endif 528 | 529 | return time; 530 | } 531 | 532 | // Get current date and time (now) 533 | long micGetTimeStamp(void) 534 | { 535 | 536 | } 537 | 538 | // [!] Get timestamp as a string -> format? or just let the user manage it? 539 | const char *micGetTimeStampString(long timestamp) 540 | { 541 | 542 | } 543 | 544 | // Wait (sleep) a specific amount of time 545 | int micWaitTime(int milliseconds) 546 | { 547 | #if defined(SUPPORT_BUSY_WAIT_LOOP) 548 | double previousTime = micGetTime(); 549 | double currentTime = 0.0; 550 | 551 | // Busy wait loop 552 | while ((currentTime - previousTime) < ms/1000.0f) currentTime = GetTime(); 553 | #else 554 | #if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP) 555 | double busyWait = ms*0.05; // NOTE: We are using a busy wait of 5% of the time 556 | ms -= (float)busyWait; 557 | #endif 558 | 559 | // System halt functions 560 | #if defined(_WIN32) 561 | Sleep((unsigned int)ms); 562 | #endif 563 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) 564 | struct timespec req = { 0 }; 565 | time_t sec = (int)(ms/1000.0f); 566 | ms -= (sec*1000); 567 | req.tv_sec = sec; 568 | req.tv_nsec = ms*1000000L; 569 | 570 | // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated. 571 | while (nanosleep(&req, &req) == -1) continue; 572 | #endif 573 | #if defined(__APPLE__) 574 | usleep(ms*1000.0f); 575 | #endif 576 | 577 | #if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP) 578 | double previousTime = micGetTime(); 579 | double currentTime = 0.0; 580 | 581 | // Partial busy wait loop (only a fraction of the total wait time) 582 | while ((currentTime - previousTime) < busyWait/1000.0f) currentTime = micGetTime(); 583 | #endif 584 | #endif 585 | } 586 | 587 | // File system: Edition 588 | //---------------------------------------------------------------------------------- 589 | 590 | // Create an empty file, useful for further filling 591 | int micCreateFile(const char *fileName) 592 | { 593 | 594 | } 595 | 596 | // Delete an existing file 597 | int micDeleteFile(const char *fileName) 598 | { 599 | int result = remove(fileName); 600 | 601 | switch (result) 602 | { 603 | case 0: micTraceLog(MIC_LOG_INFO, "[%s] File deleted successfully", fileName); 604 | // case ENAMETOOLONG: This error is used when either the total length of a file name is greater than PATH_MAX, or when an individual file name component has a length greater than NAME_MAX. See Limits for Files. 605 | // case ENOTDIR: A file that is referenced as a directory component in the file name exists, but it isn’t a directory. 606 | // case ELOOP: Too many symbolic links were resolved while trying to look up the file name. 607 | // case EACCES: micTraceLog(MIC_LOG_ERROR, "[%s] Write permission is denied for the directory", fileName); break; 608 | // case EBUSY: This error indicates that the file is being used by the system in such a way that it can’t be unlinked. For example, you might see this error if the file name specifies the root directory or a mount point for a file system. 609 | // case ENOENT: The file name to be deleted doesn’t exist. 610 | // case EPERM: On some systems unlink cannot be used to delete the name of a directory, or at least can only be used this way by a privileged user. To avoid such problems, use rmdir to delete directories. (On GNU/Linux and GNU/Hurd systems unlink can never delete the name of a directory.) 611 | // case EROFS: The directory containing the file name to be deleted is on a read-only file system and can’t be modified. 612 | default: micTraceLog(MIC_LOG_ERROR, "[%s] File can not be deleted", fileName); break; 613 | } 614 | 615 | return result; 616 | } 617 | 618 | // Rename an existing file 619 | int micRenameFile(const char *fileName, const char *newFileName) 620 | { 621 | int result = rename(fileName, newFileName); 622 | 623 | switch (result) 624 | { 625 | case 0: micTraceLog(MIC_LOG_INFO, "[%s] File renamed successfully", newFileName); break; 626 | // case EACCES: One of the directories containing newname or oldname refuses write permission; or newname and oldname are directories and write permission is refused for one of them. 627 | // case EBUSY: A directory named by oldname or newname is being used by the system in a way that prevents the renaming from working. This includes directories that are mount points for filesystems, and directories that are the current working directories of processes. 628 | // case ENOTEMPTY: 629 | // case EEXIST: The directory newname isn’t empty. GNU/Linux and GNU/Hurd systems always return ENOTEMPTY for this, but some other systems return EEXIST. 630 | // case EINVAL: oldname is a directory that contains newname. 631 | // case EISDIR: newname is a directory but the oldname isn’t. 632 | // case EMLINK: The parent directory of newname would have too many links (entries). 633 | // case ENOENT: The file oldname doesn’t exist. 634 | // case ENOSPC: The directory that would contain newname has no room for another entry, and there is no space left in the file system to expand it. 635 | // case EROFS: The operation would involve writing to a directory on a read-only file system. 636 | // case EXDEV: The two file names newname and oldname are on different file systems. 637 | default: micTraceLog(MIC_LOG_ERROR, "[%s] File can not be renamed", fileName); break; 638 | } 639 | 640 | return result; 641 | } 642 | 643 | // Copy an existing file to a new path and filename 644 | int micCopyFile(const char *srcFileName, const char *dstPathFileName) 645 | { 646 | 647 | } 648 | 649 | // Move an existing file to a new path and filename 650 | int micMoveFile(const char *srcFileName, const char *dstpathFileName) 651 | { 652 | 653 | } 654 | 655 | int micCheckFileAccess() 656 | { 657 | //int access(const char *filename, int how) // how: R_OK, W_OK, X_OK, or the existence test F_OK 658 | // EACCES: The access specified by how is denied. 659 | // ENOENT: The file doesn’t exist. 660 | // EROFS:Write permission was requested for a file on a read-only file system. 661 | } 662 | 663 | // Create an empty directory 664 | int micCreateDirectory(const char *dirPathName) 665 | { 666 | // Mode: Read + Write + eXecute: S_IRWXU (User), S_IRWXG (Group), S_IRWXO (Others) 667 | int result = mkdir(dirPathName, S_IRWXU | S_IRWXG | S_IRWXO); 668 | 669 | //struct stat st = { 0 }; 670 | //if (stat("/some/directory", &st) == -1) // Check if directory exist 671 | 672 | switch (result) 673 | { 674 | case 0: micTraceLog(MIC_LOG_INFO, "[%s] Directory created successfully", dirPathName); 675 | case EEXIST: micTraceLog(MIC_LOG_WARNING, "[%s] Directory already exist", dirPathName); 676 | case EACCES: micTraceLog(MIC_LOG_ERROR, "[%s] Write permission denied by parent directory", dirPathName); 677 | case EMLINK: micTraceLog(MIC_LOG_ERROR, "[%s] Parent directory has too many links (entries)", dirPathName); 678 | case ENOSPC: micTraceLog(MIC_LOG_ERROR, "[%s] File system doesn't have enough space", dirPathName); 679 | case EROFS: micTraceLog(MIC_LOG_ERROR, "[%s] Parent directory is read-only", dirPathName); 680 | default: break; 681 | } 682 | 683 | return result; 684 | } 685 | 686 | // Delete an existing and empty directory 687 | int micDeleteDirectory(const char *dirPath) 688 | { 689 | int result = remove(dirPath); // stdio.h 690 | //int result = rmdir(dirPath); // unistd.h 691 | 692 | switch (result) 693 | { 694 | case 0: micTraceLog(MIC_LOG_INFO, "[%s] Directory deleted successfully", dirPathName); 695 | case EEXIST: 696 | case ENOTEMPTY: micTraceLog(MIC_LOG_ERROR, "[%s] Directory to be deleted is not empty", dirPathName); 697 | default: break; 698 | } 699 | 700 | return result; 701 | } 702 | 703 | // Rename an existing directory 704 | int micRenameDirectory(const char *dirPath, const char *newDirPath) 705 | { 706 | //int rename (const char *oldname, const char *newname) // both must be directories, only empty dir can be renamed 707 | } 708 | 709 | // Copy an existing directory to a new path 710 | int micCopyDirectory(const char *srcDirPath, const char *dstDirPath) 711 | { 712 | 713 | } 714 | 715 | // Move an existing directory to a new path 716 | int micMoveDirectory(const char *srcDirPath, const char *dstDirPath) 717 | { 718 | 719 | } 720 | 721 | // File system: Query 722 | //---------------------------------------------------------------------------------- 723 | 724 | // Check if a file exists 725 | bool micIsFileAvailable(const char *fileName) 726 | { 727 | //FILE *fopen(const char *filename, const char *mode) 728 | //int access(const char *path, int amode); function is defined in unistd.h 729 | //int stat (const char *filename, struct stat *buf) 730 | //ENOENT: The file named by filename doesn’t exist. 731 | // EACCES: The process does not have search permission for a directory component of the file name. 732 | // ENAMETOOLONG: This error is used when either the total length of a file name is greater than PATH_MAX, or when an individual file name component has a length greater than NAME_MAX. See Limits for Files. 733 | // ENOENT: This error is reported when a file referenced as a directory component in the file name doesn’t exist, or when a component is a symbolic link whose target file does not exist. See Symbolic Links. 734 | // ENOTDIR: A file that is referenced as a directory component in the file name exists, but it isn’t a directory. 735 | // ELOOP: Too many symbolic links were resolved while trying to look up the file name. 736 | } 737 | 738 | // Check if a directory path exists 739 | bool micIsDirectoryAvailable(const char *dirPath) 740 | { 741 | 742 | } 743 | 744 | // Get current working directory (uses static string) 745 | const char *micGetWorkingDirectory(void) 746 | { 747 | static char currentDir[MAX_FILEPATH_LENGTH] = { 0 }; 748 | memset(currentDir, 0, MAX_FILEPATH_LENGTH); 749 | 750 | char *path = GETCWD(currentDir, MAX_FILEPATH_LENGTH - 1); 751 | 752 | return path; 753 | } 754 | 755 | // Change working directory, return true on success 756 | bool micChangeDirectory(const char *dirPath) 757 | { 758 | 759 | } 760 | 761 | // Get file size 762 | int micGetFileSize(const char *fileName) 763 | { 764 | 765 | } 766 | 767 | // Get file modification time (last write time) 768 | long micGetFileModTime(const char *fileName) 769 | { 770 | 771 | } 772 | 773 | // Check file extension (including point: .png, .wav) 774 | bool micIsFileExtension(const char *fileName, const char *ext) 775 | { 776 | 777 | } 778 | 779 | // Get pointer to extension for a filename string (includes dot: '.png') 780 | const char *micGetFileExtension(const char *fileName) 781 | { 782 | 783 | } 784 | 785 | // Get pointer to filename for a path string 786 | const char *micGetFileName(const char *filePath) 787 | { 788 | 789 | } 790 | 791 | // Get filename string without extension (uses static string) 792 | const char *micGetFileNameWithoutExt(const char *filePath) 793 | { 794 | 795 | } 796 | 797 | // Get full path for a given fileName with path (uses static string) 798 | const char *micGetDirectoryPath(const char *filePath) 799 | { 800 | 801 | } 802 | 803 | // Get previous directory path for a given path (uses static string) 804 | const char *micGetPrevDirectoryPath(const char *dirPath) 805 | { 806 | 807 | } 808 | 809 | // Get full path for a file 810 | const char *micGetFileFullPath(const char *fileName) 811 | { 812 | 813 | } 814 | 815 | // Get file path relative to another path 816 | const char *micGetFileRelativePath(const char *fileName, const char *refPath) 817 | { 818 | 819 | } 820 | 821 | // Get file info: MIC_FILE_INFO_TIME_CREATION, MIC_FILE_INFO_TIME_LAST_ACCESS, MIC_FILE_INFO_TIME_LAST_WRITE 822 | long micGetFileInfo(const char *fileName, int info) 823 | { 824 | 825 | } 826 | 827 | // Get directory byte size (for all files contained) 828 | int micGetDirectorySize(const char *dirPath) 829 | { 830 | 831 | } 832 | 833 | // Get filenames in a directory path (memory should be freed) 834 | char **micGetDirectoryFiles(const char *dirPath, int *count) 835 | { 836 | 837 | } 838 | 839 | 840 | // String management (no UTF-8 strings, only byte chars) 841 | // NOTE: Some strings allocate memory internally for returned strings -> REVIEW 842 | //---------------------------------------------------------------------------------- 843 | 844 | // Copy one string to another, returns bytes copied 845 | int micStringCopy(char *dstStr, const char *srcStr) 846 | { 847 | 848 | } 849 | 850 | // Check if two string are equal 851 | bool micStringEqual(const char *str1, const char *str2) 852 | { 853 | 854 | } 855 | 856 | // Get string size in bytes, checks for '\0' ending 857 | unsigned int micStringSize(const char *str) 858 | { 859 | 860 | } 861 | 862 | // String formatting with variables (sprintf() style) 863 | const char *micStringFormat(const char *str, ...) 864 | { 865 | 866 | } 867 | 868 | // Get a piece of a string 869 | const char *micStringSubstring(const char *str, int position, int length) 870 | { 871 | 872 | } 873 | 874 | // Replace string (WARNING: memory must be freed!) 875 | char *micStringReplace(char *str, const char *replace, const char *by) 876 | { 877 | 878 | } 879 | 880 | // Insert string in a position (WARNING: memory must be freed!) 881 | char *micStringInsert(const char *str, const char *insert, int position) 882 | { 883 | 884 | } 885 | 886 | // Join strings with delimiter 887 | const char *micStringJoin(const char **strList, int count, const char *delimiter) 888 | { 889 | 890 | } 891 | 892 | // Split string into multiple strings 893 | const char **micStringSplit(const char *str, char delimiter, int *count) 894 | { 895 | 896 | } 897 | 898 | // Append string at specific position and move cursor 899 | void micStringAppend(char *str, const char *append, int *position) 900 | { 901 | 902 | } 903 | 904 | // Find first string occurrence within a string 905 | int micStringFindIndex(const char *str, const char *find) 906 | { 907 | 908 | } 909 | 910 | // Get upper case version of provided string 911 | const char *micStringToUpper(const char *str) 912 | { 913 | 914 | } 915 | 916 | // Get lower case version of provided string 917 | const char *micStringToLower(const char *str) 918 | { 919 | 920 | } 921 | 922 | // Get Pascal case notation version of provided string 923 | const char *micStringToPascal(const char *str) 924 | { 925 | 926 | } 927 | 928 | // Get integer value from string (negative values not supported) 929 | int micStringToInteger(const char *str) 930 | { 931 | 932 | } 933 | 934 | // Check if a string contains another string 935 | bool micStringContains(const char *str, const char *contain) 936 | { 937 | 938 | } 939 | 940 | // Check if a string starts with another prefix string 941 | bool micStringStartsWith(const char *str, const char *start) 942 | { 943 | 944 | } 945 | 946 | // Misc functions 947 | //---------------------------------------------------------------------------------- 948 | 949 | // Save integer value to storage file (to defined position), returns true on success 950 | bool micSaveStorageValue(unsigned int position, int value) 951 | { 952 | 953 | } 954 | 955 | // Load integer value from storage file (from defined position) 956 | int micLoadStorageValue(unsigned int position) 957 | { 958 | 959 | } 960 | 961 | // Get a random value between min and max (both included) 962 | int micGetRandomValue(int min, int max) 963 | { 964 | 965 | } 966 | 967 | // Set the seed for the random number generator 968 | void micSetRandomSeed(unsigned int seed) 969 | { 970 | 971 | } 972 | 973 | // Load file data as byte array (read) 974 | unsigned char *micLoadFileData(const char *fileName, unsigned int *bytesRead) 975 | { 976 | 977 | } 978 | 979 | // Unload file data allocated by LoadFileData() 980 | void micUnloadFileData(unsigned char *data) 981 | { 982 | 983 | } 984 | 985 | // Save data to file from byte array (write), returns true on success 986 | bool micSaveFileData(const char *fileName, void *data, unsigned int bytesToWrite) 987 | { 988 | 989 | } 990 | 991 | // Load text data from file (read), returns a '\0' terminated string 992 | char *micLoadFileText(const char *fileName) 993 | { 994 | 995 | } 996 | 997 | // Unload file text data allocated by LoadFileText() 998 | void micUnloadFileText(char *text) 999 | { 1000 | 1001 | } 1002 | 1003 | // Save text data to file (write), string must be '\0' terminated, returns true on success 1004 | bool micSaveFileText(const char *fileName, char *text) 1005 | { 1006 | 1007 | } 1008 | 1009 | // Compress file into a .zip 1010 | int micZipFile(const char *srcFileName, const char *dstFileName) 1011 | { 1012 | 1013 | } 1014 | 1015 | // Compress directory into a .zip 1016 | int micZipDirectory(const char *srcPath, const char *dstFileName) 1017 | { 1018 | 1019 | } 1020 | 1021 | // Compress data (DEFLATE algorithm) 1022 | unsigned char *micCompressData(unsigned char *data, int dataLength, int *compDataLength) 1023 | { 1024 | 1025 | } 1026 | 1027 | // Decompress data (DEFLATE algorithm) 1028 | unsigned char *micDecompressData(unsigned char *compData, int compDataLength, int *dataLength) 1029 | { 1030 | 1031 | } 1032 | 1033 | #endif // MIC_IMPLEMENTATION 1034 | --------------------------------------------------------------------------------