Last active
April 19, 2022 22:45
-
-
Save sonich2401/d57813d46a82f3263a3af8569ca815d0 to your computer and use it in GitHub Desktop.
FileUtils.h: A simple to use single file solution for all file processing needs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*RenDev#2616 File Utilites v1.2 | |
Copyright (C) 2021 RenDev | |
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. | |
Permission is also granted to not credit the author in any way as long as you do not take credit | |
for this piece of software. | |
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. | |
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
IF YOU DO THE HOKEY POKEY YOU TURN YOURSELF AROUND. | |
Contact me at vgngamingnetwork@gmail.com if you need to contact me about this licence*/ | |
/*********************** README ******************************** | |
What is this?: | |
This is a single file solution to all of your file accessing needs. | |
Why C? | |
Because it can work in both C++ and C code. | |
How do I use it? | |
Define FU_IMP in ONLY one .c/.cpp file. | |
I would recommend that you define it in a separate .c/.cpp file so that if you make changes | |
to your other .c files it will not have to recompile this. | |
If you do not care about compile times, staticly compile this file with the settings flags | |
If you want better performance in C++ then compile this file as C code. This header | |
will automaticly make it compatible with C++ | |
!!! NOTICE: MAKE SURE TO LOOK AT THE AVAILABLE SETTINGS LOCATED BELOW THIS README!!! | |
How does memory management work? | |
You will have to remember to free up any lists or bin files | |
that you have laying around that you are no longer using. | |
You can do this by doing | |
fu_free_<NAME OF TYPE>(object); | |
How do Lists work? | |
Lists, Text, and Bin files all use the same struct. | |
There are 2 members | |
text / bin | |
size | |
text / bin is a pointer to raw memory | |
size is the amount of elements stored at that raw memory. | |
for text it will tell you how many lines there are and for | |
bin it will tell you how many bytes are in the file. | |
Can I use this in multiple files? | |
Yes. Because it is a single file solution it can only be defined once but you can include | |
this as a header anywhere in your programs. | |
Am I allowed to use this without crediting you? | |
YES | |
Open source all the way. | |
You do not have to credit me but I would appreciate it :) | |
If you would like AND ONLY if you want to credit me, either | |
Link my GH: github.com/sonich2401 | |
Link my Discord: RenDev#2616 | |
or | |
Link my email: vgngamingnetwork@gmail.com | |
v1.2 | |
- Added text file append | |
- Added text line insert | |
- Added text line delete | |
- Added better header definitions | |
v1.1 | |
- Added wildcard functionality | |
- Added file find functionality (working on a GNU backend soon) | |
- Added way to staticly compile the code #define FU_STATIC_COMPILE | |
- Added access time to FileStats | |
- Added file extension to FileStats | |
- Renamed all structs to include the 'fu_' prefix | |
- FileStats now includes file type | |
- Faster file time retrieval | |
- General performance increases + less RAM used | |
- 0 Warnings with -Wall using both gcc and g++ (except for -Wunused-function) | |
- Made using '__restrict__' optional with FU_NO_RESTRICT | |
- Moved C++ only features to default off. | |
v1.0 | |
- Inital release | |
*********************************** END OF README ***********************************/ | |
//$$$$ DEFINE SETTINGS HERE $$$$ | |
//Uncomment to force struct functions (decreases performance (EXPERIMENTAL C++ ONLY)) | |
//#define FU_USE_STRUCT_FUNCTIONS | |
//Uncomment line below to disable restrict (helps compiling on old C++ compilers but helps performance if you do not disable restrict) | |
//#define FU_NO_RESTRICT | |
//Uncomment to enable debugging messages | |
#define FU_DEBUG true | |
//Uncomment to staticly compile all functions which allows you not to use #define FU_IMP | |
//#define FU_STATIC_COMPILE | |
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ | |
#ifndef FILE_UTILS_H | |
#define FILE_UTILS_H | |
#ifndef __cplusplus | |
#define FU_NULL NULL | |
#include <stdbool.h> //bool, true, false | |
#else | |
#define FU_NULL nullptr | |
#endif | |
//[Use/Do not use] restrict to increase performance (might break old C++ compilers) | |
#ifdef FU_NO_RESTRICT | |
#define FU_RESTRICT | |
#else | |
#define FU_RESTRICT __restrict__ | |
#endif | |
#define FU_COMPILE_MODE | |
//Staticly compile the code | |
#ifdef FU_STATIC_COMPILE | |
#undef FU_COMPILE_MODE | |
#define FU_COMPILE_MODE static | |
#ifndef FU_IMP //Define the implement flag if it hasn't already | |
#define FU_IMP | |
#endif | |
#endif | |
#ifdef FU_INLINE_COMPILE | |
#undef FU_COMPILE_MODE | |
#define FU_COMPILE_MODE inline | |
#ifndef FU_IMP //Define the implement flag if it hasn't already | |
#define FU_IMP | |
#endif | |
#endif | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
//A standard type that is used to index things like lists | |
typedef unsigned long long int fu_index; | |
//A standard type for a string | |
typedef char* fu_string; | |
//A standard type for binary | |
typedef fu_string fu_hexarray; | |
//A special struct to hold a bin file | |
//fu_List.bin is an array of bytes. | |
//You can access the data by doing myBinFile.bin[index]; | |
//You can get the number of bytes in the bin file by doing myBinFile.size; | |
#ifndef FU_USE_STRUCT_FUNCTIONS | |
typedef struct{ | |
fu_index size; | |
fu_hexarray bin; | |
}fu_BinFile; | |
#else | |
struct fu_BinFile{ | |
fu_BinFile(); | |
fu_BinFile(const fu_string path); | |
fu_BinFile(fu_index bsize, fu_hexarray buffer); | |
fu_index size; | |
fu_hexarray bin; | |
fu_index get_hash(); | |
char operator[](fu_index index); | |
~fu_BinFile(); | |
}; | |
#endif | |
//A special struct to hold a list of items. Namely text. | |
//fu_List.text is a 2D array of text that stores the lines of the list. | |
//You can access the data by doing myList.text[index]; | |
//You can get the number of items in the list by doing myList.size; | |
#ifndef FU_USE_STRUCT_FUNCTIONS | |
typedef struct { | |
fu_index size; | |
fu_string* text; | |
}fu_List; | |
#else | |
struct fu_List { | |
fu_List(); | |
fu_List(const fu_string path); | |
fu_List(fu_index lines, fu_string* items); | |
fu_index size; | |
fu_string* text; | |
void load_text_file(const fu_string path); | |
fu_BinFile to_bin(); | |
fu_stringoperator[](fu_index index); | |
~fu_List(); | |
}; | |
#endif | |
//A special struct to hold a list of items. Namely text. | |
//fu_List.text is a 2D array of text that stores the lines of the list. | |
//You can access the data by doing myList.text[index]; | |
//You can get the number of items in the list by doing myList.size; | |
typedef fu_List fu_TextFile; | |
//A timestamp that is derived from a file | |
typedef struct{ | |
char hour; | |
char minute; | |
char second; | |
char day; | |
unsigned char month; | |
unsigned short year; | |
}fu_Timestamp; | |
//This union/struct will allow you to get the rwx status of a file. The names are self explainitory | |
typedef union{ | |
struct{ | |
bool exists : 1; | |
bool not_accessible : 1; | |
bool readable : 1; | |
bool writeable : 1; | |
bool read_only : 1; | |
bool executable : 1; | |
}; | |
unsigned char chr_form; | |
}fu_FilePerms; | |
typedef enum{ | |
FU_UNKOWN = 0, | |
FU_BLOCK_DEVICE = 1, | |
FU_CHARACTER_DEVICE = 2, | |
FU_DIRECTORY = 3, | |
FU_FIFO = 4, | |
FU_PIPE = 4, | |
FU_SYSLINK = 5, | |
FU_SYSTEM_LINK = 5, | |
FU_FILE = 6, | |
FU_SOCKET = 7 | |
}fu_FileType; | |
//This struct will contain all information for a given file. | |
//It includes modified and created time, permissions, file name, and the size of the file | |
#ifndef FU_USE_STRUCT_FUNCTIONS | |
typedef struct { | |
#else | |
struct fu_FileStats{ | |
#endif | |
fu_Timestamp modified; | |
fu_Timestamp created; | |
fu_Timestamp accessed; | |
fu_string file_name; | |
fu_string file_extension; | |
fu_FileType type; | |
fu_FilePerms perms; | |
unsigned long bytes; | |
#ifdef FU_USE_STRUCT_FUNCTIONS | |
~fu_FileStats(); | |
}; | |
#else | |
}fu_FileStats; | |
#endif | |
//This function will return a list of all files and folders contained in the directory given. | |
//Use the `show_hidden` flag to see hidden files | |
FU_COMPILE_MODE fu_List fu_get_dir_contents(fu_string FU_RESTRICT folder, bool full_path, bool show_hidden); | |
//This function will return a list of all files contained in the directory given. | |
//Use the `show_hidden` flag to see hidden files | |
FU_COMPILE_MODE fu_List fu_get_dir_files(fu_string FU_RESTRICT folder, bool full_path, bool show_hidden); | |
//This function will return a list of all folders contained in the directory given. | |
//Use the `show_hidden` flag to see hidden files | |
FU_COMPILE_MODE fu_List fu_get_dir_folders(fu_string FU_RESTRICT folder, bool full_path, bool show_hidden); | |
//Get a struct containing all info about a file. See the FileStats struct for more info | |
FU_COMPILE_MODE fu_FileStats fu_get_file_info(const fu_string FU_RESTRICT file_path); | |
//Get the type of file located at file_path. Returns a fu_FileType enum value | |
FU_COMPILE_MODE fu_FileType fu_get_file_type(const fu_string FU_RESTRICT file_path); | |
//Get a timestamp for when a given file was created | |
FU_COMPILE_MODE fu_Timestamp fu_get_file_created_time(const fu_string FU_RESTRICT file_path); | |
//Get a timestamp for when a given file was modified | |
FU_COMPILE_MODE fu_Timestamp fu_get_file_modified_time(const fu_string FU_RESTRICT file_path); | |
//Get a timestamp for when a given file was modified | |
FU_COMPILE_MODE fu_Timestamp fu_get_file_accessed_time(const fu_string FU_RESTRICT file_path); | |
//Get the size of a given file | |
FU_COMPILE_MODE fu_index fu_get_file_size(const fu_string FU_RESTRICT file_path); | |
//Get file / folder permissions | |
FU_COMPILE_MODE fu_FilePerms fu_get_file_perms(const fu_string FU_RESTRICT file_path); | |
//Load a binary file into a fu_List struct. See fu_List for more info on how to use | |
FU_COMPILE_MODE fu_BinFile fu_load_bin_file(const fu_string FU_RESTRICT file_path); | |
//Load a text file into a fu_List struct. See fu_List for more info on how to use | |
FU_COMPILE_MODE fu_TextFile fu_load_text_file(const fu_string FU_RESTRICT file_path); | |
//Save a binary file to the disk. | |
FU_COMPILE_MODE void fu_save_bin_file(const fu_string FU_RESTRICT file_path, fu_BinFile bin); | |
//Save a text file to the disk. | |
FU_COMPILE_MODE void fu_save_text_file(const fu_string FU_RESTRICT file_path, fu_TextFile text); | |
//Allocate lines for a text file | |
FU_COMPILE_MODE fu_TextFile fu_alloc_text_file(fu_index line_count); | |
//Allocate lines for a List | |
FU_COMPILE_MODE fu_List fu_alloc_list(fu_index element_count); | |
//Allocate lines for a bin file | |
FU_COMPILE_MODE fu_BinFile fu_alloc_bin_file(fu_index byte_count); | |
//Duplicate contents from src to dest | |
FU_COMPILE_MODE fu_BinFile* fu_memcpy_bin_file(fu_BinFile * dest, fu_BinFile* FU_RESTRICT src); | |
//Duplicate contents from src to dest | |
FU_COMPILE_MODE fu_TextFile* fu_memcpy_text_file(fu_TextFile * dest, fu_TextFile* FU_RESTRICT src); | |
//Duplicate contents from src to dest | |
FU_COMPILE_MODE fu_List* fu_memcpy_list(fu_List * dest, fu_List* FU_RESTRICT src); | |
//Duplicate contents from src to dest | |
FU_COMPILE_MODE fu_BinFile fu_create_bin_copy(fu_BinFile src); | |
//Duplicate contents from src to dest | |
FU_COMPILE_MODE fu_TextFile fu_create_text_copy(fu_TextFile src); | |
//Duplicate contents from src to dest | |
FU_COMPILE_MODE fu_List fu_create_list_copy(fu_List src); | |
//Join 2 Lists together and returns a new list contaning a + b | |
FU_COMPILE_MODE fu_List fu_join_list_copy(fu_List a, fu_List b); | |
//Join 2 bin files together and returns a new bin contaning a + b | |
FU_COMPILE_MODE fu_BinFile fu_join_bin_copy(fu_BinFile a, fu_BinFile b); | |
//Join 2 Lists together and stores resulting data in 'a' | |
FU_COMPILE_MODE fu_List fu_join_list(fu_List * a, fu_List b); | |
//Join 2 bin files together and stores resulting data in 'a' | |
FU_COMPILE_MODE fu_BinFile fu_join_bin(fu_BinFile * a, fu_BinFile b); | |
//Append text to the end of a text file | |
FU_COMPILE_MODE fu_TextFile fu_append_text(fu_TextFile * ptr, fu_string FU_RESTRICT str); | |
//Append text to the end of a list | |
FU_COMPILE_MODE fu_TextFile fu_append_item(fu_List * ptr, fu_string FU_RESTRICT str); | |
//Insert text line at line 'i' | |
FU_COMPILE_MODE fu_TextFile fu_insert_text(fu_TextFile * ptr, fu_index i, fu_string FU_RESTRICT str); | |
//Insert text line at line 'i' | |
FU_COMPILE_MODE fu_TextFile fu_insert_item(fu_List * ptr, fu_index i, fu_string FU_RESTRICT str); | |
//Deletes text line at line 'i' | |
FU_COMPILE_MODE fu_TextFile fu_delete_text(fu_TextFile * ptr, fu_index i); | |
//Deletes text line at line 'i' | |
FU_COMPILE_MODE fu_TextFile fu_delete_item(fu_List * ptr, fu_index i); | |
//Gets a new struct that contants elements 'b' to 'e' | |
FU_COMPILE_MODE fu_TextFile fu_sub_text(fu_TextFile file, fu_index b, fu_index e); | |
//Gets a new struct that contants elements 'b' to 'e' | |
FU_COMPILE_MODE fu_List fu_sub_list(fu_List list, fu_index b, fu_index e); | |
//Gets a new struct that contants elements 'b' to 'e' | |
FU_COMPILE_MODE fu_BinFile fu_sub_bin(fu_BinFile file, fu_index b, fu_index e); | |
//Get a hash for a bin file | |
FU_COMPILE_MODE fu_index fu_get_hash(fu_BinFile file); | |
//Convert a fu_TextFile into a fu_BinFile. This will allocate more memory so make sure to free this | |
FU_COMPILE_MODE fu_BinFile fu_to_bin(fu_TextFile text_file); | |
//Free memory inside of a fu_List object | |
FU_COMPILE_MODE void fu_free_list(fu_List list); | |
//Free memory inside of a fu_TextFile object | |
FU_COMPILE_MODE void fu_free_text_file(fu_TextFile txt_file); | |
//Free memory inside of a fu_BinFile object | |
FU_COMPILE_MODE void fu_free_bin_file(fu_BinFile bin_file); | |
//Free memory inside of a FileStats object | |
FU_COMPILE_MODE void fu_free_FileStats(fu_FileStats filestat); | |
//Convert a Windows text file to a UNIX text file. | |
FU_COMPILE_MODE void fu_text_file_convert_unix(fu_TextFile txt_file); | |
//Update the modified time of a file and create it if it does not exist | |
FU_COMPILE_MODE void fu_touch_file(const fu_string FU_RESTRICT file_path); | |
//Return a string containing the name of the user. | |
FU_COMPILE_MODE fu_string fu_get_current_user(); | |
//Get list of all files with a given wildcard | |
FU_COMPILE_MODE fu_List fu_wildcard(fu_List path, const fu_string FU_RESTRICT format); | |
//Find files | |
FU_COMPILE_MODE fu_List fu_find(const fu_string FU_RESTRICT path, const fu_string FU_RESTRICT name, bool show_hidden, bool recursive); | |
#ifdef __cplusplus | |
} | |
#endif | |
#ifdef FU_IMP | |
#include <stdlib.h> | |
#include <string.h> //malloc(), strcpy(), free() | |
#include <time.h> //time struct, localtime() | |
#include <unistd.h> //access() | |
#include <dirent.h> //dirent, opendir(), closedir(), readdir() | |
#include <errno.h> //errno | |
#include <stdio.h> //perror(), printf(), fopen(), fseek(), fwrite(), ftell() | |
#include <sys/stat.h> //File stating, lstat() | |
#define FU_STRDUP(src) ((fu_string)strcpy(((fu_string)malloc(strlen(src) + 1)), ((fu_string)src))) | |
FU_COMPILE_MODE void fu_helper__init_timestamp(fu_Timestamp * FU_RESTRICT ts){ | |
ts->day = 0; | |
ts->month = 0; | |
ts->year = 0; | |
ts->hour = 0; | |
ts->minute = 0; | |
ts->second = 0; | |
} | |
FU_COMPILE_MODE fu_Timestamp fu_helper__to_timestamp(struct timespec * FU_RESTRICT ts){ | |
fu_Timestamp ret; | |
struct tm *conv_tm = (struct tm*)localtime(&ts->tv_sec); | |
ret.second = conv_tm->tm_sec; | |
ret.minute = conv_tm->tm_min; | |
ret.hour = conv_tm->tm_hour; | |
ret.day = conv_tm->tm_mday; | |
ret.month = conv_tm->tm_mon; | |
ret.year = conv_tm->tm_year + 1900; | |
return ret; | |
} | |
FU_COMPILE_MODE fu_FileType fu_helper__get_file_type(struct stat * FU_RESTRICT st){ | |
switch(st->st_mode & S_IFMT){ | |
case S_IFBLK: | |
return FU_BLOCK_DEVICE; | |
case S_IFCHR: | |
return FU_CHARACTER_DEVICE; | |
case S_IFDIR: | |
return FU_DIRECTORY; | |
case S_IFIFO: | |
return FU_FIFO; | |
case S_IFLNK: | |
return FU_SYSLINK; | |
case S_IFREG: | |
return FU_FILE; | |
case S_IFSOCK: | |
return FU_SOCKET; | |
default: | |
return FU_UNKOWN; | |
} | |
return FU_UNKOWN; | |
} | |
FU_COMPILE_MODE void fu_helper__init_fstat(fu_FileStats * FU_RESTRICT fstat){ | |
fstat->bytes = 0; | |
fu_helper__init_timestamp(&fstat->created); | |
fu_helper__init_timestamp(&fstat->modified); | |
fstat->type = FU_UNKOWN; | |
} | |
FU_COMPILE_MODE void fu_helper__set_timestamp(fu_Timestamp * FU_RESTRICT ts, int sec, int min, int h){ | |
ts->second = sec; | |
ts->minute = min; | |
ts->hour = h; | |
} | |
FU_COMPILE_MODE char fu_helper__isDir(struct dirent* FU_RESTRICT dir){ | |
//printf("TYPE = %i, TEST = %i, NAME = \"%s\", BOOL = %i\n", dir->d_type, DT_DIR, dir->d_name, dir->d_type == DT_DIR); | |
if(dir->d_type == DT_UNKNOWN){ | |
struct stat sbuff; | |
lstat(dir->d_name, &sbuff); | |
return S_ISDIR(sbuff.st_mode) && !S_ISLNK(sbuff.st_mode); | |
} | |
#if 0 | |
return dir->d_type == DT_DIR || dir->d_type == DT_LNK; | |
#else | |
return dir->d_type == DT_DIR && dir->d_type != DT_LNK; | |
#endif | |
} | |
FU_COMPILE_MODE char fu_helper__isFile(struct dirent* FU_RESTRICT dir){ | |
struct stat sbuff; | |
lstat(dir->d_name, &sbuff); | |
if(dir->d_type == DT_UNKNOWN){ | |
return S_ISREG(sbuff.st_mode) && !S_ISLNK(sbuff.st_mode); | |
} | |
if(S_ISLNK(sbuff.st_mode)){ | |
return 0; | |
} | |
return dir->d_type == DT_REG && dir->d_type != DT_LNK; | |
} | |
//If folder is true then include folders in the list | |
//If files is true then include files in the list | |
//if show_hidden is true then show the hidden files | |
FU_COMPILE_MODE fu_List fu_helper__get_dir_contents(fu_string FU_RESTRICT folder, bool folders, bool files, bool full_path, bool show_hidden){ | |
fu_string* ret = NULL; | |
fu_index folder_strlen = strlen(folder); | |
DIR * d = opendir(folder); | |
struct dirent* dir; | |
fu_index element_count = 0; | |
if(d == NULL){ | |
#ifdef FU_DEBUG | |
fprintf(stderr, "WARNING: fu_helper__get_dir_contents() failed to stat file/directory path"); | |
#endif | |
fu_List err_ret; | |
err_ret.text = FU_NULL; | |
err_ret.size = 0; | |
return err_ret; | |
} | |
while((dir = readdir(d)) != NULL){ | |
//Get rid of "." and ".." directory entries | |
if(dir->d_name[0] == '.'){ | |
if(!show_hidden) | |
continue; | |
if(strlen(dir->d_name) == 1) | |
continue; | |
if(dir->d_name[1] == '.'){ | |
if(strlen(dir->d_name) == 2) | |
continue; | |
} | |
} | |
if(fu_helper__isDir(dir) & !folders){ | |
continue; | |
} | |
if(fu_helper__isFile(dir) & !files){ | |
continue; | |
} | |
if(ret == NULL){ | |
ret = (fu_string*)malloc(sizeof(fu_string)); | |
}else{ | |
ret = (fu_string*)realloc(ret, sizeof(fu_string) * (element_count + 1)); | |
} | |
if(full_path){ | |
ret[element_count] = (fu_string)malloc(256 + folder_strlen + 2); | |
sprintf(ret[element_count], "%s/%s", folder, dir->d_name); | |
}else{ | |
ret[element_count] = (fu_string)malloc(256); | |
strcpy(ret[element_count], dir->d_name); | |
} | |
element_count++; | |
} | |
closedir(d); | |
fu_List return_struct; | |
return_struct.size = (fu_index)element_count; | |
return_struct.text = ret; | |
return return_struct; | |
} | |
FU_COMPILE_MODE fu_List fu_get_dir_contents(fu_string FU_RESTRICT folder, bool full_path, bool show_hidden){ | |
return fu_helper__get_dir_contents(folder, 1, 1, full_path, show_hidden); | |
} | |
FU_COMPILE_MODE fu_List fu_get_dir_files(fu_string FU_RESTRICT folder, bool full_path, bool show_hidden){ | |
return fu_helper__get_dir_contents(folder, 0, 1, full_path, show_hidden); | |
} | |
FU_COMPILE_MODE fu_List fu_get_dir_folders(fu_string FU_RESTRICT folder, bool full_path, bool show_hidden){ | |
return fu_helper__get_dir_contents(folder, 1, 0, full_path, show_hidden); | |
} | |
FU_COMPILE_MODE void fu_free_list(fu_List list){ | |
for(fu_index i = 0; i < list.size; i++){ | |
free(list.text[i]); | |
} | |
list.text = NULL; | |
} | |
FU_COMPILE_MODE void fu_free_text_file(fu_TextFile txt_file){ | |
fu_free_list(txt_file); | |
} | |
FU_COMPILE_MODE void fu_free_bin_file(fu_BinFile bin_file){ | |
#ifdef FU_USE_STRUCT_FUNCTIONS | |
if(bin_file.bin == nullptr) | |
return; | |
#endif | |
free(bin_file.bin); | |
} | |
FU_COMPILE_MODE void fu_free_FileStats(fu_FileStats filestat){ | |
free(filestat.file_name); | |
} | |
FU_COMPILE_MODE fu_FileStats fu_get_file_info(const fu_string FU_RESTRICT file_path){ | |
struct stat futil__st; | |
lstat(file_path, &futil__st); | |
fu_FileStats ret; | |
ret.file_name = (fu_string)malloc(strlen(file_path)); | |
ret.file_name = strcpy(ret.file_name, file_path); | |
fu_string last = FU_NULL; | |
fu_string cur = ret.file_name; | |
while((cur = strstr(cur, ".")) != FU_NULL){ | |
cur++; | |
last = cur; | |
}; | |
if(last != FU_NULL){ | |
cur = (fu_string)malloc(strlen(last) + 1); | |
last = strcpy(cur, last); | |
last = cur; | |
} | |
ret.file_extension = last; | |
ret.bytes = futil__st.st_size; | |
ret.type = fu_helper__get_file_type(&futil__st); | |
ret.modified = fu_helper__to_timestamp(&futil__st.st_mtim); | |
ret.created = fu_helper__to_timestamp(&futil__st.st_ctim); | |
ret.accessed = fu_helper__to_timestamp(&futil__st.st_atim); | |
return ret; | |
} | |
FU_COMPILE_MODE fu_Timestamp fu_get_file_created_time(const fu_string FU_RESTRICT file_path){ | |
struct stat tmp; | |
lstat(file_path, &tmp); | |
return fu_helper__to_timestamp(&tmp.st_ctim); | |
} | |
FU_COMPILE_MODE fu_Timestamp fu_get_file_modified_time(const fu_string FU_RESTRICT file_path){ | |
struct stat tmp; | |
lstat(file_path, &tmp); | |
return fu_helper__to_timestamp(&tmp.st_mtim); | |
} | |
FU_COMPILE_MODE fu_Timestamp fu_get_file_accessed_time(const fu_string FU_RESTRICT file_path){ | |
struct stat tmp; | |
lstat(file_path, &tmp); | |
return fu_helper__to_timestamp(&tmp.st_atim); | |
} | |
FU_COMPILE_MODE fu_index fu_get_file_size(const fu_string FU_RESTRICT file_path){ | |
struct stat tmp; | |
lstat(file_path, &tmp); | |
return tmp.st_size; | |
} | |
FU_COMPILE_MODE fu_string fu_helper__resolve_tabs(fu_string FU_RESTRICT str){ | |
const int TAB_SIZE = 4; | |
fu_string og_str = str; | |
fu_index tab_count = 0; | |
for(fu_index i = 0; i < strlen(str); i++){ | |
tab_count += str[i] == '\t'; | |
} | |
fu_index new_size = strlen(str) - tab_count + (tab_count * TAB_SIZE) + 1; | |
fu_string new_buff = (fu_string)malloc(new_size); | |
fu_string new_buff_og = new_buff; | |
for(fu_index i = 0; i <= new_size; i++){ | |
if(str > og_str + strlen(og_str)){ | |
break; | |
} | |
if(*str == '\t'){ | |
for(unsigned char i1 = 0; i1 < TAB_SIZE; i1++){ | |
*new_buff = ' '; | |
new_buff++; | |
} | |
str++; | |
}else{ | |
*new_buff = *str; | |
new_buff++; | |
str++; | |
} | |
} | |
new_buff_og[new_size - 1] = '\0'; | |
free(og_str); | |
return new_buff_og; | |
} | |
FU_COMPILE_MODE fu_BinFile fu_load_bin_file(const fu_string FU_RESTRICT file_path){ | |
FILE *f = fopen(file_path, "r"); | |
#ifdef FU_DEBUG | |
if(f == FU_NULL){ | |
fprintf(stderr, "ERR: fu_load_bin_file(): Couldn't load file \"%s\"\n", file_path); | |
exit(-1); | |
} | |
#endif | |
fseek(f, 0, SEEK_END); | |
int fsize = ftell(f); | |
fseek(f, 0, SEEK_SET); | |
#ifdef FU_DEBUG | |
if(fsize <= 0){ | |
fprintf(stderr, "ERR: fu_load_bin_file(%s): File size = 0!\n", file_path); | |
fclose(f); | |
exit(-1); | |
} | |
#endif | |
fu_string ret_buffer = (fu_string)malloc(fsize); | |
#ifdef FU_DEBUG | |
if(ret_buffer == FU_NULL){ | |
fprintf(stderr, "ERR: fu_load_bin_file(%s): Out of memory! or Block too big\n", file_path); | |
fclose(f); | |
f = FU_NULL; | |
} | |
#endif | |
//fsize = fread(ret_buffer, fsize, fsize, f); | |
size_t fcharsread = fread(ret_buffer, 1, fsize, f); | |
#ifdef FU_DEBUG | |
if(fcharsread != fsize){ | |
fprintf(stderr, "ERR: fu_load_bin_file(%s): Bytes read is not equal to size of file! %i != %li\n", file_path, fsize, fcharsread); | |
} | |
#endif | |
fclose(f); | |
fu_BinFile ret; | |
ret.bin = ret_buffer; | |
ret.size = fsize; | |
return ret; | |
} | |
FU_COMPILE_MODE fu_TextFile fu_load_text_file(const fu_string FU_RESTRICT file_path){ | |
fu_BinFile binfile = fu_load_bin_file(file_path); | |
binfile.bin = (fu_string)realloc(binfile.bin, binfile.size + 1); | |
fu_string buffer = binfile.bin; | |
*(buffer + binfile.size) = '\0'; | |
binfile.size++; | |
//Get total amount of lines | |
fu_index nline_count = 1; | |
for(fu_index i = 0; i < strlen(buffer); i++){ | |
if(buffer[i] == '\n'){ | |
nline_count++; | |
} | |
} | |
//was there text at the end that we missed? | |
if(buffer[strlen(buffer) - 1] != '\n') | |
nline_count++; | |
//create string array | |
fu_string* ret_buff = (fu_string*)malloc(sizeof(fu_string) * nline_count); | |
fu_index chars_processed = 0; | |
for(fu_index i = 0; i + 1 < nline_count; i++){ | |
fu_index nline_strlen = 0; | |
fu_index i1 = 0; | |
while(1){ | |
if(chars_processed + 1 < binfile.size){ | |
if(buffer[i1] == '\n') | |
break; | |
nline_strlen++; | |
i1++; | |
chars_processed++; | |
continue; | |
} | |
break; | |
} | |
ret_buff[i] = (fu_string)malloc(nline_strlen + 1); | |
memcpy(ret_buff[i], buffer, nline_strlen); | |
ret_buff[i][nline_strlen] = '\0'; | |
ret_buff[i] = fu_helper__resolve_tabs(ret_buff[i]); | |
buffer += (nline_strlen + 1); | |
} | |
#ifndef FU_USE_STRUCT_FUNCTIONS | |
fu_free_bin_file(binfile); | |
#endif | |
fu_TextFile ret; | |
ret.text = ret_buff; | |
ret.size = nline_count - 1; | |
return ret; | |
} | |
FU_COMPILE_MODE fu_FilePerms fu_get_file_perms(const fu_string FU_RESTRICT file_path){ | |
fu_FilePerms ret; | |
ret.chr_form = 0; | |
errno = 0; | |
int opcode = access(file_path, F_OK); | |
ret.exists = (opcode == 0) && (errno != ENOENT); | |
ret.not_accessible = (errno == EACCES); | |
opcode = access(file_path, R_OK); | |
ret.readable = (opcode == 0); | |
opcode = access(file_path, W_OK); | |
ret.writeable = (opcode == 0) && (errno != EACCES); | |
ret.read_only = (opcode != 0) && (errno == EROFS); | |
opcode = access(file_path, X_OK); | |
ret.executable = (opcode == 0) && (errno != EACCES); | |
return ret; | |
} | |
FU_COMPILE_MODE fu_FileType fu_get_file_type(const fu_string FU_RESTRICT file_path){ | |
struct stat fu_stat; | |
lstat(file_path, &fu_stat); | |
return fu_helper__get_file_type(&fu_stat); | |
} | |
FU_COMPILE_MODE void fu_save_bin_file(const fu_string FU_RESTRICT file_path, fu_BinFile bin){ | |
FILE* f = fopen(file_path, "wb"); | |
#ifdef FU_DEBUG | |
if(!f){ | |
fprintf(stderr, "ERR: File could not open (fu_save_bin_file)"); | |
exit(-1); | |
} | |
#endif | |
fwrite(bin.bin, sizeof(char), bin.size, f); | |
fclose(f); | |
} | |
FU_COMPILE_MODE void fu_save_text_file(const fu_string FU_RESTRICT file_path, fu_TextFile text){ | |
FILE* f = fopen(file_path, "wb"); | |
#ifdef FU_DEBUG | |
if(!f){ | |
fprintf(stderr, "ERR: File could not open (fu_save_text_file)"); | |
exit(-1); | |
} | |
#endif | |
for(fu_index i = 0; i < text.size; i++){ | |
fwrite(text.text[i], sizeof(char), strlen(text.text[i]), f); | |
fwrite("\n", sizeof(char), 1, f); | |
} | |
fclose(f); | |
} | |
//Allocate lines for a List | |
FU_COMPILE_MODE fu_List fu_alloc_list(fu_index element_count){ | |
fu_List ret; | |
ret.size = element_count; | |
ret.text = (fu_string*)malloc(sizeof(fu_string) * ret.size); | |
return ret; | |
} | |
//Allocate lines for a text file | |
FU_COMPILE_MODE fu_TextFile fu_alloc_text_file(fu_index line_count){ | |
return (fu_TextFile)fu_alloc_list(line_count); | |
} | |
//Allocate lines for a bin file | |
FU_COMPILE_MODE fu_BinFile fu_alloc_bin_file(fu_index byte_count){ | |
fu_BinFile ret; | |
ret.size = byte_count; | |
ret.bin = (fu_string)malloc(byte_count); | |
return ret; | |
} | |
FU_COMPILE_MODE fu_BinFile* fu_memcpy_bin_file(fu_BinFile * dest, fu_BinFile* FU_RESTRICT src){ | |
dest->size = src->size; | |
dest->bin = (fu_string)malloc(src->size); | |
dest->bin = (fu_string)memcpy(dest->bin, src->bin, src->size); | |
return dest; | |
} | |
FU_COMPILE_MODE fu_TextFile* fu_memcpy_text_file(fu_TextFile * dest, fu_TextFile* FU_RESTRICT src){ | |
dest->size = src->size; | |
dest->text = (fu_string*)malloc(sizeof(fu_string) * src->size); | |
for(fu_index i = 0; i < src->size; i++){ | |
dest->text[i] = (fu_string)malloc(strlen(src->text[i]) + 1); | |
strcpy(dest->text[i], src->text[i]); | |
} | |
return dest; | |
} | |
FU_COMPILE_MODE fu_List* fu_memcpy_list(fu_List * dest, fu_List* FU_RESTRICT src){ | |
return (fu_List*)(void*)fu_memcpy_text_file(dest, src); | |
} | |
FU_COMPILE_MODE fu_BinFile fu_create_bin_copy(fu_BinFile src){ | |
fu_BinFile ret; | |
fu_memcpy_bin_file(&ret, &src); | |
return ret; | |
} | |
FU_COMPILE_MODE fu_List fu_create_list_copy(fu_List src){ | |
fu_List ret; | |
fu_memcpy_list(&ret, &src); | |
return ret; | |
} | |
FU_COMPILE_MODE fu_TextFile fu_create_text_copy(fu_TextFile src){ | |
return (fu_TextFile)fu_create_list_copy(src); | |
} | |
FU_COMPILE_MODE fu_List fu_join_list(fu_List * a, fu_List b){ | |
fu_List ret = *a; | |
if(b.size == 0) | |
return ret; | |
if(b.text == FU_NULL) | |
return ret; | |
ret.text = (fu_string*)realloc(ret.text, sizeof(fu_string) * (ret.size + b.size)); | |
fu_index i = ret.size; | |
fu_index beg_cursor = ret.size; | |
ret.size += b.size; | |
for(; i < ret.size; i++){ | |
ret.text[i] = FU_STRDUP(b.text[i - beg_cursor]); | |
} | |
*a = ret; | |
return ret; | |
} | |
FU_COMPILE_MODE fu_List fu_join_list_copy(fu_List a, fu_List b){ | |
fu_List cpy = fu_create_list_copy(a); | |
return fu_join_list(&cpy, b); | |
} | |
//Join 2 bin files together | |
FU_COMPILE_MODE fu_BinFile fu_join_bin(fu_BinFile* a, fu_BinFile b){ | |
fu_BinFile ret = *a; | |
ret.size = a->size + b.size; | |
ret.bin = (fu_string)realloc(ret.bin, ret.size); | |
fu_string cursor = ret.bin + a->size; | |
cursor = (fu_string)memcpy(cursor, b.bin, b.size); | |
return ret; | |
} | |
FU_COMPILE_MODE fu_BinFile fu_join_bin_copy(fu_BinFile a, fu_BinFile b){ | |
fu_BinFile cpy = fu_create_bin_copy(a); | |
return fu_join_bin(&cpy, b); | |
} | |
//Append text to the end of a text file | |
FU_COMPILE_MODE fu_TextFile fu_append_text(fu_TextFile * ptr, fu_string FU_RESTRICT str){ | |
return (fu_TextFile)fu_append_item(((fu_List*)ptr), str); | |
} | |
//Append text to the end of a list | |
FU_COMPILE_MODE fu_List fu_append_item(fu_List * ptr, fu_string FU_RESTRICT str){ | |
fu_List txt; | |
txt.text = (fu_string*)malloc(sizeof(fu_string) * ptr->size); | |
#ifdef FU_DEBUG | |
if(txt.text == FU_NULL){ | |
fprintf(stderr, "WARNING: fu_append_text(ptr = %p, str = \"%s\"): Not enough RAM!! Aborting function ...\n", ptr, str); | |
return *ptr; | |
} | |
#endif | |
txt.text[0] = (fu_string)FU_STRDUP(str); | |
#ifdef FU_DEBUG | |
if(txt.text[0] == FU_NULL){ | |
fprintf(stderr, "WARNING: fu_append_text(ptr = %p, str = \"%s\"): Not enough RAM!! Aborting function ...\n", ptr, str); | |
return *ptr; | |
} | |
#endif | |
txt.size = 1; | |
return (fu_List)fu_join_list(((fu_List*)ptr), txt); | |
} | |
//Insert text line at line 'i' | |
FU_COMPILE_MODE fu_TextFile fu_insert_text(fu_TextFile * ptr, fu_index i, fu_string FU_RESTRICT str){ | |
return fu_insert_item(((fu_List*)ptr), ((fu_index)i), ((fu_string)str)); | |
} | |
//Insert text line at line 'i' | |
FU_COMPILE_MODE fu_List fu_insert_item(fu_List * ptr, fu_index i, fu_string FU_RESTRICT str){ | |
#ifdef FU_DEBUG | |
if(str == FU_NULL){ | |
fprintf(stderr, "ERR: fu_insert_item(ptr = %p, i = %llu, str = %p): 'str' == NULL!!!\n", ptr, i, str); | |
abort(); | |
} | |
if(ptr == FU_NULL){ | |
fprintf(stderr, "ERR: fu_insert_item(ptr = %p, i = %llu, str = \"%s\"): ptr is NULL!!!\n", ptr, i, str); | |
abort(); | |
} | |
if(i >= ptr->size){ | |
fprintf(stderr, "ERR: fu_insert_item(ptr = %p, i = %llu, str = \"%s\"): 'i' is way to big!!!\n", ptr, i, str); | |
abort(); | |
} | |
if(ptr->size == 0){ | |
fprintf(stderr, "ERR: fu_insert_item(ptr = %p, i = %llu, str = \"%s\"): ptr list size is 0!!!\n", ptr, i, str); | |
abort(); | |
} | |
if((ptr->size + 1) == 0){ | |
fprintf(stderr, "ERR: fu_insert_item(ptr = %p, i = %llu, str = \"%s\"): ptr->list size rolled over to 0!!!\n", ptr, i, str); | |
abort(); | |
} | |
#endif | |
fu_string* strarray = (fu_string*)malloc(sizeof(fu_string*) * (ptr->size + 1)); | |
#ifdef FU_DEBUG | |
if(strarray == FU_NULL){ | |
fprintf(stderr, "WARNING: fu_insert_item(ptr = %p, i = %llu, str = \"%s\"): Not enough RAM!!! Function Aborting ...\n", ptr, i, str); | |
return *ptr; | |
} | |
#endif | |
strarray = (fu_string*)memcpy(strarray, ptr->text, sizeof(fu_string*) * ptr->size); //only copy pointers | |
#ifdef FU_DEBUG | |
if(strarray == FU_NULL){ | |
fprintf(stderr, "WARNING: fu_insert_item(ptr = %p, i = %llu, str = \"%s\"): Not enough RAM!!! Function Aborting ...\n", ptr, i, str); | |
return *ptr; | |
} | |
#endif | |
free(ptr->text); | |
ptr->text = (fu_string*)strarray; | |
for(fu_index index = ptr->size; index > i; index--){ | |
ptr->text[index] = (fu_string)ptr->text[index - 1]; | |
} | |
ptr->text[i] = str; | |
return *ptr; | |
} | |
//Deletes text line at line 'i' | |
FU_COMPILE_MODE fu_TextFile fu_delete_text(fu_TextFile * ptr, fu_index i){ | |
return (fu_TextFile)fu_delete_item(((fu_List*)ptr), i); | |
} | |
//Deletes text line at line 'i' | |
FU_COMPILE_MODE fu_List fu_delete_item(fu_List * ptr, fu_index i){ | |
#ifdef FU_DEBUG | |
if(ptr == FU_NULL){ | |
fprintf(stderr, "ERR: fu_delete_item(ptr = %p, i = %llu): ptr is NULL!!!\n", ptr, i); | |
abort(); | |
} | |
if(i >= ptr->size){ | |
fprintf(stderr, "ERR: fu_delete_item(ptr = %p, i = %llu): 'i' is way to big!!!\n", ptr, i); | |
abort(); | |
} | |
if(ptr->size == 0){ | |
fprintf(stderr, "ERR: fu_delete_item(ptr = %p, i = %llu): ptr list size is 0!!!\n", ptr, i); | |
abort(); | |
} | |
if((ptr->size - 1) == 0){ | |
fprintf(stderr, "ERR: fu_delete_item(ptr = %p, i = %llu): ptr->list size rolled over to 0!!!\n", ptr, i); | |
abort(); | |
} | |
#endif | |
fu_string* strarray = (fu_string*)malloc(sizeof(fu_string*) * (ptr->size - 1)); | |
#ifdef FU_DEBUG | |
if(strarray == FU_NULL){ | |
fprintf(stderr, "WARNING: fu_delete_item(ptr = %p, i = %llu): Not enough RAM!!! Function Aborting ...\n", ptr, i); | |
return *ptr; | |
} | |
#endif | |
for(fu_index index = i; index < ptr->size; index++){ | |
ptr->text[index] = (fu_string)ptr->text[index + 1]; | |
} | |
strarray = (fu_string*)memcpy(strarray, ptr->text, sizeof(fu_string*) * (ptr->size - 1)); //only copy pointers | |
#ifdef FU_DEBUG | |
if(strarray == FU_NULL){ | |
fprintf(stderr, "WARNING: fu_delete_item(ptr = %p, i = %llu): Not enough RAM!!! Function Aborting ...\n", ptr, i); | |
return *ptr; | |
} | |
#endif | |
free(ptr->text); | |
ptr->text = (fu_string*)strarray; | |
ptr->size--; | |
return *ptr; | |
} | |
//Gets a new struct that contants elements 'b' to 'e' | |
FU_COMPILE_MODE fu_TextFile fu_sub_text(fu_TextFile file, fu_index b, fu_index e){ | |
return (fu_TextFile)fu_sub_list(*((fu_List*)&file), b, e); | |
} | |
//Gets a new struct that contants elements 'b' to 'e' | |
FU_COMPILE_MODE fu_List fu_sub_list(fu_List list, fu_index b, fu_index e){ | |
#ifdef FU_DEBUG | |
if(list.text == FU_NULL){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): List is not allocated!!\n", list.text, b, e); | |
abort(); | |
} | |
if(list.size <= b){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): 'b' is too big (file.size = %llu)\n", list.text, b, e, list.size); | |
abort(); | |
} | |
if(list.size < e){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): 'e' is too big (file.size = %llu)\n", list.text, b, e, list.size); | |
abort(); | |
} | |
if(b >= e){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): 'b' is bigger than 'e'!!!\n", list.text, b, e); | |
abort(); | |
} | |
#endif | |
fu_List ret; | |
ret.size = e - b + 1; | |
ret.text = (fu_string*)malloc(sizeof(fu_string*) * ret.size); | |
#ifdef FU_DEBUG | |
if(ret.text == FU_NULL){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): Out of RAM!!!\n", list.text, b, e); | |
abort(); | |
} | |
#endif | |
for(fu_index i = b; i < b + ret.size; i++){ | |
#ifdef FU_DEBUG | |
if(list.text[i] == FU_NULL){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): List element list.text[%llu] = NULL!!!\n", list.text, b, e, i); | |
abort(); | |
} | |
#endif | |
ret.text[i - b] = (fu_string)malloc(sizeof(char) * strlen(list.text[i]) + 1); | |
#ifdef FU_DEBUG | |
if(ret.text[i - b] == FU_NULL){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): Out of RAM!!!\n", list.text, b, e); | |
abort(); | |
} | |
#endif | |
ret.text[i - b] = (fu_string)strcpy(ret.text[i - b], list.text[i]); | |
#ifdef FU_DEBUG | |
if(ret.text[i - b] == FU_NULL){ | |
fprintf(stderr, "ERR: fu_sub_list(file.text = %p, b = %llu, e = %llu): Uknown strcpy error (i = %llu)!!!\n", list.text, b, e, i); | |
abort(); | |
} | |
#endif | |
} | |
return ret; | |
} | |
//Gets a new struct that contants elements 'b' to 'e' | |
FU_COMPILE_MODE fu_BinFile fu_sub_bin(fu_BinFile file, fu_index b, fu_index e){ | |
#ifdef FU_DEBUG | |
if(file.bin == FU_NULL){ | |
fprintf(stderr, "ERR: fu_sub_bin(file.bin= %p, b = %llu, e = %llu): List is not allocated!!\n", file.bin, b, e); | |
abort(); | |
} | |
if(file.size <= b){ | |
fprintf(stderr, "ERR: fu_sub_bin(file.bin = %p, b = %llu, e = %llu): 'b' is too big (file.size = %llu)\n", file.bin, b, e, file.size); | |
abort(); | |
} | |
if(file.size <= e){ | |
fprintf(stderr, "ERR: fu_sub_bin(file.bin = %p, b = %llu, e = %llu): 'e' is too big (file.size = %llu)\n", file.bin, b, e, file.size); | |
abort(); | |
} | |
if(b >= e){ | |
fprintf(stderr, "ERR: fu_sub_bin(file.bin = %p, b = %llu, e = %llu): 'b' is bigger than 'e'!!!\n", file.bin, b, e); | |
abort(); | |
} | |
#endif | |
fu_BinFile ret; | |
ret.size = e - b; | |
ret.bin = (fu_hexarray)malloc(sizeof(char) * ret.size); | |
#ifdef FU_DEBUG | |
if(ret.bin == FU_NULL){ | |
fprintf(stderr, "ERR: fu_sub_bin(file.bin = %p, b = %llu, e = %llu): Out of RAM!!!\n", file.bin, b, e); | |
abort(); | |
} | |
#endif | |
for(fu_index i = b; i < b + ret.size; i++){ | |
ret.bin[i - b] = file.bin[i]; | |
} | |
return ret; | |
} | |
FU_COMPILE_MODE fu_index fu_get_hash(fu_BinFile file){ | |
fu_index ret = 0x12345; | |
for(fu_index i = 0; i < file.size; i++){ | |
srandom(ret - i); | |
ret = (ret + (random() % (file.bin[i] | 1))) << (random() % ((i | 1) % 100)); | |
ret |= ret + 0x20; | |
ret -= file.bin[i]; | |
} | |
return ret; | |
} | |
FU_COMPILE_MODE fu_BinFile fu_to_bin(fu_TextFile text_file){ | |
fu_index byte_buffer_size = 0; | |
for(fu_index i = 0; i < text_file.size; i++){ | |
byte_buffer_size += strlen(text_file.text[i]) + (i + 1 < text_file.size); | |
} | |
fu_BinFile ret; | |
ret.size = byte_buffer_size; | |
ret.bin = (fu_string)malloc(byte_buffer_size); | |
fu_string buffer = ret.bin; | |
for(fu_index i = 0; i < text_file.size; i++){ | |
memcpy(buffer, text_file.text[i], strlen(text_file.text[i])); | |
if(i + 1 < text_file.size){ | |
buffer[strlen(text_file.text[i])] = '\n'; | |
} | |
buffer += strlen(text_file.text[i]) + (i + 1 < text_file.size); | |
} | |
return ret; | |
} | |
FU_COMPILE_MODE void fu_text_file_convert_unix(fu_TextFile txt_file){ | |
for(fu_index i = 0; i < txt_file.size; i++){ | |
fu_string tmp = txt_file.text[i]; | |
while (*tmp != '\0'){ | |
if(*tmp == '\r') | |
*tmp = '\0'; | |
tmp++; | |
} | |
} | |
} | |
FU_COMPILE_MODE void fu_touch_file(const fu_string FU_RESTRICT file_path){ | |
#define CMD_STR "touch \"" | |
fu_string cmd = (fu_string)malloc(strlen(CMD_STR) + strlen(file_path) + 1); | |
strcat(cmd, file_path); | |
strcat(cmd, "\""); | |
system(cmd); | |
free(cmd); | |
} | |
FU_COMPILE_MODE fu_string fu_get_current_user(){ | |
return getenv("USER"); | |
} | |
//Get list of all files with a given wildcard | |
FU_COMPILE_MODE fu_List fu_wildcard(fu_List contents, const fu_string FU_RESTRICT __format__){ | |
fu_List ret; | |
ret.text = FU_NULL; | |
ret.size = 0; | |
//Dupe string | |
fu_string format = FU_STRDUP(__format__); | |
//fu_stringformat = (fu_string)malloc(strlen(__format__) + 1); | |
//format = (fu_string)strcpy(format, __format__); | |
fu_string before = format; | |
fu_string after = FU_NULL; | |
bool is_wildcard = false; | |
for(fu_index i = 0; i < strlen(__format__); i++){ | |
if(format[i] == '*'){ | |
//Abuse how strings work to create 2 strings in one string | |
format[i] = '\0'; | |
after = format + i + 1; | |
is_wildcard = true; | |
break; | |
} | |
} | |
if(!is_wildcard){ | |
ret.text = FU_NULL; | |
ret.size = 0; | |
return ret; | |
} | |
fu_index wildcard_count = 0; | |
fu_string cursor; | |
fu_index before_strlen = strlen(before); | |
fu_index after_strlen = strlen(after); | |
for(fu_index i =0; i < contents.size; i++){ | |
if((cursor = strstr(contents.text[i], before)) != contents.text[i]) //begining string wasnt found | |
continue; | |
if((cursor = strstr(contents.text[i] + before_strlen, after)) == NULL) //ending string was not found | |
continue; | |
if(cursor + after_strlen < contents.text[i] + strlen(contents.text[i])) | |
continue; | |
wildcard_count++; | |
} | |
//Allocate string array | |
if(contents.size > 0 && wildcard_count > 0){ | |
ret.text = (fu_string*)malloc(sizeof(fu_string) * wildcard_count); | |
int wildcard_cusor = 0; | |
for(fu_index i =0; i < contents.size; i++){ | |
if((cursor = strstr(contents.text[i], before)) != contents.text[i]) //begining string wasnt found | |
continue; | |
if((cursor = strstr(contents.text[i] + strlen(before), after)) == NULL) //ending string was not found | |
continue; | |
if(cursor + after_strlen < contents.text[i] + strlen(contents.text[i])) | |
continue; | |
ret.text[wildcard_cusor] = FU_STRDUP(contents.text[i]); | |
wildcard_cusor++; | |
} | |
ret.size = wildcard_count; | |
} | |
free(format); | |
return ret; | |
} | |
//Find files | |
FU_COMPILE_MODE fu_List fu_find(const fu_string FU_RESTRICT path, const fu_string FU_RESTRICT name, bool show_hidden, bool recursive){ | |
fu_List ret; | |
fu_List empty; | |
empty.size=0; | |
empty.text = FU_NULL; | |
fu_List dircontents = fu_get_dir_files((fu_string)path, false, show_hidden); | |
ret = fu_wildcard(dircontents, name); | |
fu_index element_count = 0; | |
fu_index element_cursor = 0; | |
if(ret.text != FU_NULL){ | |
//Add full path behind string | |
for(fu_index i = 0; i < ret.size; i++){ | |
fu_string og_text = ret.text[i]; | |
ret.text[i] = (fu_string)malloc(strlen(path) + strlen(ret.text[i]) + 2); | |
sprintf(ret.text[i], "%s/%s", path, og_text); | |
//printf("%s\n", ret.text[i]); | |
free(og_text); | |
} | |
fu_free_list(dircontents); | |
goto fu_find__HELPER; | |
} | |
ret = empty; | |
//Failed to find any wildcards | |
for(fu_index i = 0; i < dircontents.size; i++){ | |
if(strstr(dircontents.text[i], name) == dircontents.text[i]){ //Found string | |
element_count++; | |
} | |
} | |
//Allocate array | |
if(element_count > 0){ | |
ret.text = (fu_string*)malloc(sizeof(fu_string) * element_count); | |
} | |
for(fu_index i = 0; i < dircontents.size; i++){ | |
if(strstr(dircontents.text[i], name) == dircontents.text[i]){ //Found string | |
ret.text[element_cursor] = (fu_string)malloc(strlen(dircontents.text[i]) + strlen(path) + 1 + 1); | |
ret.text[element_cursor] = (fu_string)strcpy(ret.text[element_cursor], path); | |
ret.text[element_cursor] = (fu_string)strcat(ret.text[element_cursor], "/"); | |
ret.text[element_cursor] = (fu_string)strcat(ret.text[element_cursor], dircontents.text[i]); | |
element_cursor++; | |
} | |
} | |
fu_free_list(dircontents); | |
if(element_cursor <= 0){ | |
ret.text = FU_NULL; | |
} | |
fu_find__HELPER: | |
if(recursive){ | |
fu_List folders = fu_get_dir_folders((fu_string)path, true, show_hidden); | |
for(fu_index i = 0; i < folders.size; i++){ | |
fu_string buffer = FU_STRDUP(folders.text[i]); | |
struct stat sbuff; | |
lstat(buffer, &sbuff); | |
if(S_ISLNK(sbuff.st_mode)){ //Do not follow links | |
free(buffer); | |
continue; | |
} | |
if(fu_get_file_perms((const fu_string)buffer).not_accessible){ //Do we not have permissions? | |
free(buffer); | |
continue; | |
} | |
fu_List files = fu_find(buffer, name, show_hidden, recursive); //Get file names (no full path) | |
if(ret.text != FU_NULL && ret.size != 0){ | |
fu_join_list(&ret, files); | |
fu_free_list(files); | |
}else{ | |
fu_free_list(ret); | |
ret = files; | |
} | |
free(buffer); | |
} | |
fu_free_list(folders); | |
} | |
return ret; | |
} | |
#ifdef FU_USE_STRUCT_FUNCTIONS //CPP features | |
//fu_BinFile | |
fu_BinFile::fu_BinFile(){ | |
this->size = 0; | |
this->bin = nullptr; | |
} | |
fu_BinFile::fu_BinFile(fu_index bsize, fu_stringbuffer){ | |
this->size = 0; | |
this->bin = nullptr; | |
} | |
fu_BinFile::fu_BinFile(const fu_stringpath){ | |
*this = fu_load_bin_file(path); | |
} | |
fu_index fu_BinFile::get_hash(){ | |
return fu_get_hash(*this); | |
} | |
char fu_BinFile::operator[](fu_index index){ | |
return this->bin[index]; | |
} | |
fu_BinFile::~fu_BinFile(){ | |
if(this->bin == nullptr){ | |
free(this->bin); | |
this->bin = nullptr; | |
} | |
} | |
//fu_List | |
fu_List::fu_List(){ | |
this->size = 0; | |
this->text = nullptr; | |
} | |
fu_List::fu_List(const fu_stringpath){ | |
this->load_text_file(path); | |
} | |
fu_List::fu_List(fu_index lines, fu_string* items){ | |
this->size = lines; | |
this->text = items; | |
} | |
void fu_List::load_text_file(const fu_string path){ | |
if(this->text != nullptr){ | |
fu_free_list(*this); | |
} | |
fu_List tmp = fu_load_text_file(path); | |
*this = tmp; | |
tmp.text = nullptr; | |
} | |
fu_BinFile fu_List::to_bin(){ | |
fu_List& reference = *this; | |
return fu_to_bin(reference); | |
} | |
fu_stringfu_List::operator[](fu_index index){ | |
return this->text[index]; | |
} | |
fu_List::~fu_List(){ | |
if(this->text != nullptr){ | |
fu_List& reference = *this; | |
fu_free_list(reference); | |
reference.text = nullptr; | |
} | |
} | |
//FileStats | |
fu_FileStats::~fu_FileStats(){ | |
if(file_name != nullptr) | |
free(this->file_name); | |
} | |
#endif | |
#endif | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment