/*
* Copyright 2011 Steven Gribble
*
* This file is part of the UW CSE 333 course project sequence
* (333proj).
*
* 333proj is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 333proj is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 333proj. If not, see .
*/
#include
#include
#include
#include
#include
#include "ll_file.h"
#include "ll_priv.h"
int WriteToFile(LinkedList list,
char *filename,
PayloadToByteArrayFnPtr f) {
FILE *outf = NULL;
LLIter it = NULL;
// Open up the file.
outf = fopen(filename, "wb+");
if (f == NULL)
return 0;
// Test a corner case.
if (NumElementsInLinkedList(list) == 0)
goto done;
// Prepare our iterator.
it = LinkedListMakeIterator(list, 0);
if (it == NULL) {
fclose(outf);
unlink(filename);
return 0;
}
// Loop through the list items.
while (1) {
// Get the byte array.
void *payload;
unsigned char *arr = NULL;
uint32_t arrlen, outlen;
// get the list item payload.
assert(LLIteratorGetPayload(it, &payload) == 1);
// convert the list item payload to a writable byte array.
arr = (unsigned char *) f(payload, &arrlen);
assert(arrlen > 0);
// write a record, with len in network order. a record
// is a network order 32 bit int representing the payload
// length, followed by the payload bytes.
outlen = htonl(arrlen);
assert(fwrite(&outlen,
1,
sizeof(uint32_t),
outf) == sizeof(uint32_t));
assert(fwrite(arr, 1, arrlen, outf) == arrlen);
// free the writable byte array.
free(arr);
// go to the next item in the list and loop around.
if (LLIteratorNext(it) == 0)
goto done;
}
done:
// All done; clean up and return.
if (f != NULL)
fclose(outf);
if (it != NULL)
LLIteratorFree(it);
return 1;
}
LinkedList ReadFromFile(char *filename,
ByteArrayToPayloadFnPtr f) {
FILE *inf = NULL;
LinkedList list = NULL;
// Open up the file.
inf = fopen(filename, "rb");
if (inf == NULL)
goto done;
// Create the list.
list = AllocateLinkedList();
if (list == NULL)
goto done;
// Loop through the file.
while (1) {
uint32_t nextlen;
unsigned char *buf;
void *payload;
// Read the length, convert from network to host order.
if (fread(&nextlen,
1,
sizeof(uint32_t),
inf) != sizeof(uint32_t)) {
goto done;
}
nextlen = ntohl(nextlen);
// Allocate a buffer for the next record, read it in.
buf = (unsigned char *) malloc(nextlen * sizeof(char));
assert(buf != NULL);
assert(fread(buf, 1, nextlen, inf) == nextlen);
// Great! Convert the payload, add it in.
payload = f(buf, sizeof(uint32_t));
assert(AppendLinkedList(list, payload) == 1);
// Free the buf we read in, loop around.
free(buf);
}
done:
// All done! Clean up and return the list.
if (inf != NULL)
fclose(inf);
return list;
}