#if defined(__unix__)
# define _POSIX_SOURCE
# include<unistd.h>
# include<fcntl.h>
# include<sys/stat.h>
# include<sys/mman.h>
#elif defined(_WIN32)
# include<windows.h>
# include<io.h>
#endif
#include<lexlib/defines.h>
#include<internal/misc.h>
#include<lexlib/cfile.h>
#include<stdio.h>
void *lexlibCFileMap(FILE *file){
#if defined(__unix__)
int fd = fileno(file);
if(fd == -1)
return NULL;
uint64_t filesize = lexlibCFileSize(file);
int prot;
int flag;
int mode = fcntl(fd, F_GETFL) & O_ACCMODE;
switch(mode){
case O_RDONLY:
prot = PROT_READ;
flag = MAP_PRIVATE;
break;
case O_WRONLY:
prot = PROT_WRITE;
flag = MAP_SHARED;
break;
case O_RDWR:
prot = PROT_READ | PROT_WRITE;
flag = MAP_SHARED;
break;
default:
return NULL;
}
void* mem = mmap(NULL, filesize, prot, flag, fd, 0);
if(mem == MAP_FAILED)
return NULL;
return mem;
#elif defined(_WIN32)
HANDLE handle = (HANDLE)_get_osfhandle(_fileno(file));
if(handle == INVALID_HANDLE_VALUE)
return NULL;
DWORD flagPage;
DWORD flagMap;
switch(lexlibCFileMode(file) & LEXLIB_RDWR){
case LEXLIB_RD:
flagPage = PAGE_READONLY;
flagMap = FILE_MAP_READ;
break;
case LEXLIB_WR:
flagPage = PAGE_WRITECOPY;
flagMap = FILE_MAP_WRITE;
break;
case LEXLIB_RDWR:
flagPage = PAGE_READWRITE;
flagMap = FILE_MAP_ALL_ACCESS;
break;
default:
return NULL;
}
HANDLE map = CreateFileMapping(handle, NULL, flagPage, 0, 0, NULL);
void* mem = MapViewOfFile(map, flagMap, 0, 0, 0);
CloseHandle(map);
return mem;
#endif
}
uint8_t lexlibCFileMode(FILE *file){
#if defined(__unix__)
int fmode = fcntl(fileno(file), F_GETFL);
uint8_t mode = LEXLIB_NONE;
switch(fmode & O_ACCMODE){
case O_RDONLY:
mode |= LEXLIB_RD;
break;
case O_WRONLY:
mode |= LEXLIB_WR;
break;
case O_RDWR:
mode |= LEXLIB_RDWR;
break;
}
if(!mode)
return LEXLIB_NONE;
if(fmode & O_CREAT)
mode |= LEXLIB_CREATE;
if(fmode & O_APPEND)
mode |= LEXLIB_APPEND;
return mode;
#elif defined(_WIN32)
if(file->_flag & 0x01)
return LEXLIB_RD;
if(file->_flag & 0x02)
return LEXLIB_WR;
if(file->_flag & 0x80)
return LEXLIB_RDWR;
return LEXLIB_NONE;
#endif
}
int64_t lexlibCFileSize(FILE *file){
#if defined(__unix__)
struct stat info;
int state = fstat(fileno(file), &info);
if(state != 0)
return -1;
return (int64_t)info.st_size;
#elif defined(__WIN32)
HANDLE handle = (HANDLE)_get_osfhandle(_fileno(file));
if(handle == INVALID_HANDLE_VALUE)
return -1;
LARGE_INTEGER size;
DWORD state = GetFileSizeEx(handle, &size);
if(state == 0)
return -1;
return (int64_t)size.QuadPart;
#endif
}
uint16_t lexlibCFileType(FILE *file){
#define RETURN(X) { fsetpos(file, &fileOffset); return X; }
fpos_t fileOffset;
if(fgetpos(file, &fileOffset) != 0)
RETURN(LEXLIB_FILETYPE_UNKNOWN);
rewind(file);
uint8_t mem[16];
uint16_t type = LEXLIB_FILETYPE_UNKNOWN;
if(fread(mem, 2, 1, file) != 1)
RETURN(LEXLIB_FILETYPE_UNKNOWN);
type = lexlibInternalFileTypeSig(mem, 2);
if(type){RETURN(type);}
if(fread(mem+2, 6, 1, file) != 1)
RETURN(LEXLIB_FILETYPE_UNKNOWN);
type = lexlibInternalFileTypeSig(mem, 8);
if(type){RETURN(type);}
RETURN(LEXLIB_FILETYPE_UNKNOWN);
#undef RETURN
}