357 lines
9.2 KiB
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;
|
|
}
|