kettek2/wiki/games/newsboy/Newsboy_0x00/engine/fifo.c

357 lines
9.2 KiB
C

#include "fifo.h"
#if _WIN32 | _WIN64
#include <Winsock2.h>
#include <Strsafe.h>
#else
#include <arpa/inet.h> // hah
#endif
#include <stdio.h> // remove()
#include <stdint.h> // uint32_t
#include <string.h>
#include <stdlib.h>
#include <dirent.h> // scandir
#include <sys/stat.h> // stat
#include <unistd.h> // access()
#include "string.h"
#include <errno.h>
/*
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Data Serialization, etc.
````````````````````````````````
Newsboy uses a mock-XDR style data xfer syntax. All data types are at least 32 bits long (4 bytes) and must always be a multiple of four. If the number of bytes in the data to be written is not a multiple of four, then additional padding is added.
*/
char *type_name[] = {
"char",
"int",
"float",
"string",
"magic"
};
int getType(const char *name) {
int i;
for (i = 0; i < 5; i++) {
if (strcmp(name, type_name[i]) == 0) {
return i;
}
}
return T_INT; // return int default
}
char *getTypeName(int type) {
if (type < 0 || type >= T_COUNT) return NULL;
return type_name[type];
}
void *readData(FILE *input, int type, void *storage) {
uint32_t val;
int i = 0;
switch (type) {
case T_MAGIC:
fread(&val, sizeof(char)*4, 1, input);
//storage = realloc(storage, sizeof(char)*4);
memcpy(storage, &val, sizeof(char)*4);
break;
case T_CHAR:
fread(&val, sizeof(char)*4, 1, input);
val = ntohl(val);
//storage = realloc(storage, sizeof(char)*4);
memcpy(storage, &val, sizeof(char));
break;
case T_FLOAT:
fread(&val, sizeof(char)*4, 1, input);
val = ntohf((float)val);
//storage = realloc(storage, sizeof(char)*4);
memcpy(storage, &val, sizeof(char)*4);
break;
case T_INT:
fread(&val, sizeof(char)*4, 1, input);
val = ntohl(val);
//storage = realloc(storage, sizeof(char)*4);
memcpy(storage, &val, sizeof(char)*4);
break;
case T_STRING:
// get length
fread(&val, sizeof(char)*4, 1, input);
val = ntohl(val);
// allocate passed storage to new size
storage = realloc(storage, sizeof(char)*val);
// get chunk count
int chunk = val / sizeof(char)*4; // chunk count
int ch; // chunk char offset
int offset = 0; // storage offset
// copy chunks to storage
for (i = 0; i < chunk; i++) {
// read chunk into val
fread(&val, sizeof(char), 4, input);
// read this chunk char by char into storage
for (ch = 0; ch < 4; ch++) {
((char *)storage)[offset++] = ((char*)&val)[ch];
if (((char *)&val)[ch] == '\0') {
chunk = 0;
ch = 4;
}
}
//memcpy(&((char*)storage)[0], (char*)&val, sizeof(char)*4);
}
break;
}
return storage;
}
int writeData(FILE *output, int type, void *data) {
uint32_t val;
int i;
switch (type) {
case T_MAGIC:
val = *(int*)data;
fwrite(&val, sizeof(char)*4, 1, output);
break;
case T_CHAR:
val = htonl(*(int*)(char*)data);
fwrite(&val, sizeof(char)*4, 1, output);
break;
case T_INT:
val = htonl(*(int*)data);
fwrite(&val, sizeof(char)*4, 1, output);
break;
case T_FLOAT:
// WROOOONG
{}
float fl = *(float*)data;
val = htonf(fl);
//val = *(float*)data;
fwrite(&fl, sizeof(char)*4, 1, output);
break;
case T_STRING:
i = strlen(*(char **)data)+1;
// write size, including \0
val = htonl(i);
fwrite(&val, sizeof(char)*4, 1, output);
int offset = 0;
int ch = 0;
int chunk = i / sizeof(char)*4;
for (i = 0; i < chunk; i++) {
val = 0; // clear out last chunk
ch = 0; // reset position
while (ch < 4) {
((char *)&val)[ch++] = (*(char**)data)[offset++];
if ((*(char**)data)[offset-1] == '\0') {
chunk = 0;
ch = 4;
}
}
fwrite(&val, sizeof(char)*4, 1, output);
}
break;
}
return 0;
}
struct Dir *openDir(const char *path, int order) {
if (path == NULL) return NULL;
struct Dir *dir = malloc(sizeof(struct Dir));
if (dir == NULL) {
printf("malloc failed\n");
return NULL;
}
dir->current = NULL;
dir->start = NULL;
dir->order = order;
int size = strlen(path)+2; // +2 to add trailed '/' for winderps
dir->dirname = malloc(size+1);
memcpy(dir->dirname, path, size);
dir->dirname[size-2] = '/'; // hi, winderps
dir->dirname[size-1] = '\0';
#if _WIN32 | _WIN64
WIN32_FIND_DATA ffd;
HANDLE h_find = INVALID_HANDLE_VALUE;
char crappy_windows_dir[MAX_PATH];
StringCbCopyN(crappy_windows_dir, MAX_PATH, dir->dirname, size);
StringCbCatN(crappy_windows_dir, MAX_PATH, "*", 2);
h_find = FindFirstFile(crappy_windows_dir, &ffd);
if (h_find == INVALID_HANDLE_VALUE) {
// some sort of rubbish windows error
}
struct DirEntry *last_entry = NULL;
do {
struct DirEntry *entry = malloc(sizeof(struct DirEntry));
// copy over filename
int new_size = strlen(ffd.cFileName)+1;
entry->d_name = malloc(new_size);
memcpy(entry->d_name, ffd.cFileName, new_size);
// NULL it!
entry->next = NULL;
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
entry->d_type = F_DIR;
} else {
entry->d_type = F_REG;
}
// initial linked list if not yet done
if (dir->start == NULL) {
dir->start = entry;
dir->current = entry;
}
// assign this entry to last_entry's next if possible
if (last_entry != NULL) {
last_entry->next = entry;
}
// set this entry to last entry
last_entry = entry;
} while (FindNextFile(h_find, &ffd));
FindClose(h_find);
#else
struct dirent **files;
int n;
n = scandir(dir->dirname, &files, NULL, alphasort);
if (n < 0) {
perror("openDir");
return NULL;
} else {
struct DirEntry *last_entry = NULL;
int i;
for(i = 0; i < n; i++) {
struct DirEntry *entry = malloc(sizeof(struct DirEntry));
// copy over filename
entry->d_name = malloc(1);
entry->d_name = copyString(entry->d_name, files[i]->d_name);
// NULL it!
entry->next = NULL;
// build full path name
int dir_length = strlen(dir->dirname);
int file_length = strlen(files[i]->d_name);
char filepath[dir_length+file_length+2];
memcpy(filepath, dir->dirname, dir_length);
filepath[dir_length] = '/';
memcpy(filepath+dir_length+1, files[i]->d_name, file_length+1);
// get file info
struct stat file_stat;
stat(filepath, &file_stat);
switch(file_stat.st_mode & S_IFMT) {
case S_IFDIR:
entry->d_type = F_DIR;
break;
case S_IFREG:
entry->d_type = F_REG;
break;
case S_IFLNK:
entry->d_type = F_LNK;
break;
default:
entry->d_type = F_UKN;
break;
}
// initial linked list if not yet done
if (dir->start == NULL) {
dir->start = entry;
dir->current = entry;
}
// assign this entry to last_entry's next if possible
if (last_entry != NULL) {
last_entry->next = entry;
}
// set this entry to last entry
last_entry = entry;
free(files[i]);
}
free(files);
}
#endif
return dir;
}
int closeDir(struct Dir *dir) {
if (dir == NULL) return 1;
struct DirEntry *entry = dir->start;
while(entry != NULL) {
struct DirEntry *last_entry = entry;
entry = entry->next;
free(last_entry->d_name);
free(last_entry);
}
free(dir->dirname);
free(dir);
return 0;
}
struct DirEntry *readDir(struct Dir *dir) {
if (dir == NULL) return NULL;
if (dir->current == NULL) return NULL;
struct DirEntry *entry = dir->current;
dir->current = entry->next;
return entry;
}
int fileExists(const char *filename) {
if (access(filename, F_OK) == 0) {
return 1;
}
return 0;
}
int deleteFile(const char *filename) {
if (filename == NULL) return 1;
if (!fileExists(filename)) {
return 2;
}
return remove(filename);
}
int fileToBuffer(char **buffer, const char *filename) {
int i, n, pos = 0;
char t_buf[16];
FILE *file = fopen(filename, "r");
if (file == NULL) {
return -1;
}
// get file size for realloc() and future return
fseek(file, 0, SEEK_END);
int size = ftell(file)+1;
fseek(file, 0, SEEK_SET);
*buffer = realloc(*buffer, size);
while ((n = fread(t_buf, 1, 16, file))) {
for (i = 0; i < n; i++) {
(*buffer)[pos++] = t_buf[i];
}
}
(*buffer)[size-1] = '\0';
fclose(file);
return size;
}
int hasExtension(const char *name, const char *extension) {
if (name == NULL || extension == NULL) return 0;
char *exten;
if ((exten = strrchr(name, '.')) == NULL) {
return 0;
}
if (strcmp(exten, extension) != 0) {
return 0;
}
return 1;
}
// hah, this doesn't really remove it, but w/e
char *remExtension(char *name, const char *extension) {
if (name == NULL || extension == NULL) return 0;
char *exten;
if ((exten = strrchr(name, '.')) == NULL) {
return name;
}
if (strcmp(exten, extension) != 0) {
return name;
}
*exten = '\0';
return name;
}
float htonf(float fl) {
uint32_t swap = htonl(*(int*)&fl);
return *(float *)&swap;
}
float ntohf(float fl) {
uint32_t swap = ntohl(*(int*)&fl);
return *(float *)&swap;
}