Skip to content
Snippets Groups Projects
Commit 8f3bf07b authored by Toby Murray's avatar Toby Murray
Browse files

list and save implemented

parent 63176d77
No related branches found
No related tags found
No related merge requests found
......@@ -5,11 +5,6 @@
#include "debug.h"
/**
The idea is to eventually implement state dumping by writing a series
of commands to a file <file> that we can then reload next time by doing
cat <file> - | ./passbook
**/
const char INSTRUCTION_PUT[] = "put";
......@@ -19,6 +14,8 @@ const char INSTRUCTION_GET[] = "get";
const char INSTRUCTION_SAVE[] = "save";
const char INSTRUCTION_LIST[] = "list";
typedef struct {
char * username;
char * password;
......@@ -196,35 +193,55 @@ node_t * map = NULL;
is used to implement stacks/queues of nodes so we can implement various
tree traversal algorithms without using recursion (to avoid stack overflow
for very large trees). */
typedef struct nodeptr_list {
typedef struct nodeptr_list_elem {
const node_t *p;
struct nodeptr_list *next;
struct nodeptr_list *prev;
struct nodeptr_list_elem *next;
struct nodeptr_list_elem *prev;
} nodeptr_list_elem_t;
typedef struct nodeptr_list {
nodeptr_list_elem_t *head;
nodeptr_list_elem_t *last;
} nodeptr_list_t;
nodeptr_list_t * list_push(nodeptr_list_t *lst, const node_t *p){
nodeptr_list_t *n = malloc(sizeof(nodeptr_list_t));
nodeptr_list_t list_push(nodeptr_list_t lst, const node_t *p){
nodeptr_list_elem_t *n = malloc(sizeof(nodeptr_list_elem_t));
assert(n != NULL && "push: malloc failed");
n->p = p;
n->next = lst;
if (lst != NULL){
lst->prev = n;
}
n->next = lst.head;
n->prev = NULL;
return n;
if (lst.head != NULL){
assert(lst.last != NULL);
lst.head->prev = n;
}else{
assert(lst.last == NULL);
lst.last = n;
}
lst.head = n;
return lst;
}
/* when out is non-NULL we place a pointer to the first node into it */
nodeptr_list_t * list_pop(nodeptr_list_t *lst, const node_t **out){
if (lst != NULL){
nodeptr_list_t list_pop(nodeptr_list_t lst, const node_t **out){
if (lst.head != NULL){
assert(lst.last != NULL);
if (out != NULL){
*out = lst->p;
*out = lst.head->p;
}
if (lst.last == lst.head){
free(lst.head);
lst.head = NULL;
lst.last = NULL;
}else{
nodeptr_list_elem_t *ret = lst.head->next;
free(lst.head);
lst.head = ret;
}
nodeptr_list_t *ret = lst->next;
free(lst);
return ret;
return lst;
}else{
assert(lst.last == NULL);
if (out != NULL){
*out = (const node_t *)NULL;
}
......@@ -232,15 +249,43 @@ nodeptr_list_t * list_pop(nodeptr_list_t *lst, const node_t **out){
}
}
void list_destroy(nodeptr_list_t *lst){
while (lst != NULL){
nodeptr_list_t list_dequeue(nodeptr_list_t lst, const node_t **out){
if (lst.last != NULL){
assert(lst.head != NULL);
if (out != NULL){
*out = lst.last->p;
}
if (lst.last == lst.head){
free(lst.head);
lst.head = NULL;
lst.last = NULL;
}else{
nodeptr_list_elem_t *ret = lst.last->prev;
free(lst.last);
lst.last = ret;
}
return lst;
}else{
assert(lst.head == NULL);
if (out != NULL){
*out = (const node_t *)NULL;
}
return lst;
}
}
nodeptr_list_t list_destroy(nodeptr_list_t lst){
while (lst.head != NULL){
lst = list_pop(lst,NULL);
}
return lst;
}
void list_print(nodeptr_list_t *lst){
void list_print(nodeptr_list_t lst){
printf("\nBegin list print:\n");
while (lst != NULL){
while (lst.head != NULL){
const node_t *p;
lst = list_pop(lst,&p);
node_print(p);
......@@ -248,13 +293,24 @@ void list_print(nodeptr_list_t *lst){
printf("End list print.\n\n");
}
void list_print_rev(nodeptr_list_t lst){
printf("\nBegin list reverse print:\n");
while (lst.last != NULL){
const node_t *p;
lst = list_dequeue(lst,&p);
node_print(p);
}
printf("End list reverse print.\n\n");
}
void print_all(const node_t *p){
nodeptr_list_t *lst = NULL;
/* in order traversal to print out nodes in sorted order */
void print_inorder(const node_t *p){
nodeptr_list_t lst = {.head = NULL, .last = NULL};
if (p != NULL){
lst = list_push(lst,p);
while(lst != NULL){
while(lst.head != NULL){
// keep recursing left until we can go no further
while (p->left != NULL){
lst = list_push(lst,p->left);
......@@ -277,6 +333,46 @@ void print_all(const node_t *p){
}
}
void node_save(const node_t *p, FILE *f){
fprintf(f,"%s",INSTRUCTION_PUT);
fprintf(f," ");
fprintf(f,"%s",p->url);
fprintf(f," ");
fprintf(f,"%s",p->cred.username);
fprintf(f," ");
fprintf(f,"%s",p->cred.password);
fprintf(f,"\n");
}
/* level order (i.e. breadth-first) traversal to print nodes out in the
order that they would need to be put back in to an empty tree to ensure
that the resulting tree has the same structure as the original one that
was printed out. Returns 0 on success; nonzero on failure */
int save_levelorder(const node_t *p, const char * filename){
FILE *f = fopen(filename,"w");
if (f == NULL){
debug_printf("Couldn't open file %s for writing.\n",filename);
return -1;
}
nodeptr_list_t lst = {.head = NULL, .last = NULL};
if (p != NULL){
lst = list_push(lst,p);
while(lst.last != NULL){
lst = list_dequeue(lst,&p);
node_save(p,f);
if (p->left != NULL){
lst = list_push(lst,p->left);
}
if (p->right != NULL){
lst = list_push(lst,p->right);
}
}
}
fclose(f);
return 0;
}
/* returns 0 on successful execution of the instruction in inst */
static int execute(void){
char * toks[4]; /* these are pointers to start of different tokens */
......@@ -288,10 +384,6 @@ static int execute(void){
return 0;
}
if (numToks < 2){
return -1;
}
if (strcmp(toks[0],INSTRUCTION_GET) == 0){
if (numToks != 2){
return -1;
......@@ -325,7 +417,16 @@ static int execute(void){
return -1;
}
debug_printf("Saving to: %s\n",toks[1]);
print_all(map);
if (save_levelorder(map,toks[1]) != 0){
return -1;
}
debug_printf("---\n");
} else if (strcmp(toks[0],INSTRUCTION_LIST) == 0){
if (numToks != 1){
return -1;
}
print_inorder(map);
}else{
debug_printf("Unrecognised instruction\n");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment