-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmru.c
More file actions
131 lines (117 loc) · 3.75 KB
/
mru.c
File metadata and controls
131 lines (117 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* See LICENSE file for copyright and license details. */
#include <dirent.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "mru.h"
/********/
/* LIST */
/********/
/**
* Free memory for one list entry. Null entries will be silently ignored.
*/
void _list_entry_destroy(ListEntry* e) {
if (e != NULL) {
free(e->val); /* Remember to free the value */
free(e);
}
}
ListEntry *list_create() {
ListEntry *e = (ListEntry*) malloc(sizeof(ListEntry*)); /* Allocate new entry */
e->next = e; /* This is the root entry so next and previous are set to self */
e->previous = e;
e->val = NULL; /* No value in the root entry, it will remain null */
return e;
}
void list_add(ListEntry *root, char *val) {
ListEntry *n = (ListEntry*) malloc(sizeof(ListEntry*)); /* Allocate new entry */
n->val = strdup(val); /* Copy and set the value */
n->next = root; /* Insert before root which is the last item */
n->previous = root->previous;
root->previous->next = n;
root->previous = n;
}
ListEntry *list_insert(ListEntry *e, char *val) {
ListEntry *n = (ListEntry*) malloc(sizeof(ListEntry*)); /* Allocate new entry */
n->val = strdup(val); /* Copy and set the value */
n->previous = e;
n->next = e->next;
e->next = n;
return n;
}
void list_remove(ListEntry *e) {
ListEntry *p = e->previous; /* Get previous and next entries */
ListEntry *n = e->next;
p->next = e->next;
n->previous = e->previous;
_list_entry_destroy(e); /* Remember to free memory */
}
void list_destroy(ListEntry *root) {
ListEntry* p = NULL; /* Save previous value for each iteration, since we can't free
memory for the current entry before moving to the next */
ListEntry *e = NULL;
for(e = root->next; e != root; p = e, e = e->next) {
_list_entry_destroy(p);
}
_list_entry_destroy(p); /* Remember to free the last element */
}
/*************/
/* HASHTABLE */
/*************/
/**
* Calculate hash value for the given string.
*/
unsigned _hash(char *s, unsigned size) {
unsigned hashval;
for (hashval = 0; *s != '\0'; ++s)
hashval = *s + 31 * hashval;
return hashval % size;
}
HashEntry **hash_create(unsigned size, ListEntry *root) {
HashEntry **hashtable = (HashEntry**) malloc(size * sizeof(HashEntry*));
ListEntry *e;
for(e = root->next; e != root; e = e->next) {
hash_put(hashtable, size, e->val, e);
}
return hashtable;
}
void hash_destroy(HashEntry **hashtable, unsigned size) {
int i;
for (i = 0; i < size; ++i) {
if (hashtable[i] != NULL) {
free(hashtable[i]->key);
free(hashtable[i]);
}
}
free(hashtable);
}
HashEntry *hash_get(HashEntry **hashtable, unsigned size, char *key) {
HashEntry *e = NULL;
for (e = hashtable[_hash(key, size)]; e != NULL; e = e->next) {
if (strcmp(key, e->key) == 0)
return e;
}
return NULL;
}
HashEntry *hash_put(HashEntry **hashtable, unsigned size, char *key, ListEntry *val) {
HashEntry *e = NULL;
unsigned h;
if (key == NULL) {
return NULL; /* Will not add empty keys */
}
e = hash_get(hashtable, size, key);
if (e != NULL) { /* Existing entry found. We'll just update it */
e->val = val;
} else { /* Entry not found. Need a new one */
e = (HashEntry*) malloc(sizeof(*e)); /* Allocate new Entry */
e->key = strdup(key); /* Update entry's key */
h = _hash(key, size); /* Calculate the hash value */
e->next = hashtable[h]; /* Push this entry to the top of the list */
e->val = val;
hashtable[h] = e; /* Add new entry */
}
return e;
}