Files
2026-06-25 00:09:09 +08:00

172 lines
5.3 KiB
C

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include "HashFile.h"
#include <stdlib.h>
#include <string.h>
int hashfile_creat(const char *filename, mode_t mode, int reclen, int total_rec_num) {
struct HashFileHeader hfh;
int fd, rtn;
char *buf;
hfh.sig = 31415926;
hfh.reclen = reclen;
hfh.total_rec_num = total_rec_num;
hfh.current_rec_num = 0;
fd = creat(filename, mode);
if (fd != -1) {
rtn = write(fd, &hfh, sizeof(struct HashFileHeader));
if (rtn != -1) {
buf = (char *)malloc((reclen + sizeof(struct CFTag)) * total_rec_num);
memset(buf, 0, (reclen + sizeof(struct CFTag)) * total_rec_num);
rtn = write(fd, buf, (reclen + sizeof(struct CFTag)) * total_rec_num);
free(buf);
}
close(fd);
return rtn;
}
close(fd);
return -1;
}
int hashfile_open(const char *filename, int flags, mode_t mode) {
int fd = open(filename, flags, mode);
struct HashFileHeader hfh;
if (read(fd, &hfh, sizeof(struct HashFileHeader)) != -1) {
lseek(fd, 0, SEEK_SET);
if (hfh.sig == 31415926)
return fd;
}
return -1;
}
int hashfile_close(int fd) {
return close(fd);
}
int hashfile_read(int fd, int keyoffset, int keylen, void *buf) {
struct HashFileHeader hfh;
readHashFileHeader(fd, &hfh);
int offset = hashfile_findrec(fd, keyoffset, keylen, buf);
if (offset != -1) {
lseek(fd, offset + sizeof(struct CFTag), SEEK_SET);
return read(fd, buf, hfh.reclen);
}
return -1;
}
int hashfile_write(int fd, int keyoffset, int keylen, void *buf) {
return hashfile_saverec(fd, keyoffset, keylen, buf);
}
int hashfile_delrec(int fd, int keyoffset, int keylen, void *buf) {
int offset = hashfile_findrec(fd, keyoffset, keylen, buf);
if (offset != -1) {
struct CFTag tag;
read(fd, &tag, sizeof(struct CFTag));
tag.free = 0;
lseek(fd, offset, SEEK_SET);
write(fd, &tag, sizeof(struct CFTag));
struct HashFileHeader hfh;
readHashFileHeader(fd, &hfh);
int addr = hash(keyoffset, keylen, buf, hfh.total_rec_num);
offset = sizeof(struct HashFileHeader) + addr * (hfh.reclen + sizeof(struct CFTag));
lseek(fd, offset, SEEK_SET);
read(fd, &tag, sizeof(struct CFTag));
tag.collision--;
lseek(fd, offset, SEEK_SET);
write(fd, &tag, sizeof(struct CFTag));
hfh.current_rec_num--;
lseek(fd, 0, SEEK_SET);
write(fd, &hfh, sizeof(struct HashFileHeader));
return 0;
}
return -1;
}
int hashfile_findrec(int fd, int keyoffset, int keylen, void *buf) {
struct HashFileHeader hfh;
readHashFileHeader(fd, &hfh);
int addr = hash(keyoffset, keylen, buf, hfh.total_rec_num);
int offset = sizeof(struct HashFileHeader) + addr * (hfh.reclen + sizeof(struct CFTag));
lseek(fd, offset, SEEK_SET);
struct CFTag tag;
read(fd, &tag, sizeof(struct CFTag));
char count = tag.collision;
if (count == 0) return -1;
recfree:
if (tag.free == 0) {
offset += hfh.reclen + sizeof(struct CFTag);
lseek(fd, offset, SEEK_SET);
read(fd, &tag, sizeof(struct CFTag));
goto recfree;
}
char *p = (char *)malloc(hfh.reclen);
read(fd, p, hfh.reclen);
char *p1 = (char *)buf + keyoffset;
char *p2 = p + keyoffset;
int j = 0;
while (*p1 == *p2 && j < keylen) {
p1++; p2++; j++;
}
if (j == keylen) {
free(p);
return offset;
}
free(p);
offset += hfh.reclen + sizeof(struct CFTag);
lseek(fd, offset, SEEK_SET);
read(fd, &tag, sizeof(struct CFTag));
goto recfree;
}
int hashfile_saverec(int fd, int keyoffset, int keylen, void *buf) {
if (checkHashFileFull(fd)) return -1;
struct HashFileHeader hfh;
readHashFileHeader(fd, &hfh);
int addr = hash(keyoffset, keylen, buf, hfh.total_rec_num);
int offset = sizeof(struct HashFileHeader) + addr * (hfh.reclen + sizeof(struct CFTag));
lseek(fd, offset, SEEK_SET);
struct CFTag tag;
read(fd, &tag, sizeof(struct CFTag));
tag.collision++;
lseek(fd, sizeof(struct CFTag) * (-1), SEEK_CUR);
write(fd, &tag, sizeof(struct CFTag));
while (tag.free != 0) {
offset += hfh.reclen + sizeof(struct CFTag);
if (offset >= lseek(fd, 0, SEEK_END))
offset = sizeof(struct HashFileHeader);
lseek(fd, offset, SEEK_SET);
read(fd, &tag, sizeof(struct CFTag));
}
tag.free = 1;
lseek(fd, sizeof(struct CFTag) * (-1), SEEK_CUR);
write(fd, &tag, sizeof(struct CFTag));
write(fd, buf, hfh.reclen);
hfh.current_rec_num++;
lseek(fd, 0, SEEK_SET);
return write(fd, &hfh, sizeof(struct HashFileHeader));
}
int hash(int keyoffset, int keylen, void *buf, int total_rec_num) {
int i = 0, addr = 0;
char *p = (char *)buf + keyoffset;
for (i = 0; i < keylen; i++) {
addr += (int)(*p);
p++;
}
return addr % (int)(total_rec_num * COLLISIONFACTOR);
}
int readHashFileHeader(int fd, struct HashFileHeader *hfh) {
lseek(fd, 0, SEEK_SET);
return read(fd, hfh, sizeof(struct HashFileHeader));
}
int checkHashFileFull(int fd) {
struct HashFileHeader hfh;
readHashFileHeader(fd, &hfh);
return hfh.current_rec_num >= hfh.total_rec_num;
}