I'm writing a little library for some undocumented file formats. The original program uses a path string to find files in an archive and this function tries to do the same.
The archive contains a magic string, an offset into the file list, the data in the files and the file list itself. A entry in the filelist consists of a path (256 bytes long, 0-padded) and three numbers, the second one being the offset from the archive start to the entry file. The entries are sorted alphabetically respecting case; here are some mockup paths to demonstrate the ordering:
Entry/Graphics/Sprite.cgf
Entry/Sound/Ding.wav
Quit/Graphics/exit.cgf
_RAW8123
Here are the relevant utility functions and defines. These are defined in Utils.h
and Utils.c
, I've put them here together for context.
#define BYTESZE sizeof(char)
typedef unsigned int uint;
typedef unsigned char byte;
uint readU4L(FILE* file) {
byte buf[4];
fread(buf, BYTESZE, 4, file);
return buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
}
Finally, here's the "library":
// ====== BIGfile.h
#define BIG_MAGIC_LEN 7
#define BIG_SEEK_SUCC 1
#define BIG_SEEK_FAIL 0
typedef struct BIGFile {
char magic[BIG_MAGIC_LEN];
uint offset;
FILE* read;
} BIGFile;
BIGFile* load_BIGFile(char* fpath);
int seekToEntry(BIGFile* bigfile, char* path);
// ====== BIGFile.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Utils.h"
#include "BIGFile.h"
BIGFile* load_BIGFile(char* fpath) {
BIGFile* bigfile = malloc(sizeof(BIGFile));
fopen_s(&(bigfile->read), fpath, "rb");
if (!bigfile->read) {
printf("Can't open file.\n");
return 0;
}
fread(bigfile->magic, BYTESZE, BIG_MAGIC_LEN, bigfile->read);
bigfile->offset = readU4L(bigfile->read);
return bigfile;
}
int seekToEntry(BIGFile* bigfile, char* path) {
fseek(bigfile->read, bigfile->offset, SEEK_SET);
byte buf[256];
int pos = 0;
// while not EOF, read string part
while (fread(buf, BYTESZE, 256, bigfile->read)) {
// seek over entry data
fseek(bigfile->read, 12, SEEK_CUR);
// loop until given path != read path
while (path[pos]==buf[pos]) {
pos++;
// path has ended, so buf == path
if (!path[pos]) {
// seek back into entry data
fseek(bigfile->read, -8, SEEK_CUR);
// read unsigned little endian 4-byte int
uint res = readU4L(bigfile->read);
// seek there and return success
fseek(bigfile->read, res, SEEK_SET);
//printf("found at %d\n", res);
return BIG_SEEK_SUCC;
}
}
// path char is smaller than buf char
// we seeked past where the entry could bem return failure
if (path[pos]<buf[pos]) {
return BIG_SEEK_FAIL;
}
}
// EOF, return failure
return BIG_SEEK_FAIL;
}
I'd like some feedback on general style, as well as on the seekToEntry
function, perhaps this can be improved somehow? Thanks in advance!