├── .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 |
--------------------------------------------------------------------------------