blob: 0f61519e63bfc024ab65b256b58965dc006c5a33 [file] [log] [blame]
Hisham Muhammadd6231ba2006-03-04 18:16:49 +00001/*
Hisham Muhammad84281bd2011-12-26 21:35:57 +00002htop - Hashtable.c
Hisham Muhammad300caa02011-05-26 16:35:07 +00003(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammadd6231ba2006-03-04 18:16:49 +00004Released under the GNU GPL, see the COPYING file
5in the source distribution for its full text.
6*/
7
8#include "Hashtable.h"
9
Hisham Muhammad84281bd2011-12-26 21:35:57 +000010#include <stdlib.h>
11#include <assert.h>
12
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000013/*{
Hisham Muhammad84281bd2011-12-26 21:35:57 +000014#include <stdbool.h>
15
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000016typedef struct Hashtable_ Hashtable;
17
18typedef void(*Hashtable_PairFunction)(int, void*, void*);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000019
20typedef struct HashtableItem {
Hisham Muhammada227b202007-04-05 19:53:23 +000021 unsigned int key;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000022 void* value;
23 struct HashtableItem* next;
24} HashtableItem;
25
26struct Hashtable_ {
27 int size;
28 HashtableItem** buckets;
29 int items;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000030 bool owner;
31};
32}*/
33
Hisham Muhammad110ce712006-11-08 20:09:48 +000034#ifdef DEBUG
35
Hisham Muhammadda23c8c2008-03-09 08:58:38 +000036static bool Hashtable_isConsistent(Hashtable* this) {
Hisham Muhammad110ce712006-11-08 20:09:48 +000037 int items = 0;
38 for (int i = 0; i < this->size; i++) {
39 HashtableItem* bucket = this->buckets[i];
40 while (bucket) {
41 items++;
42 bucket = bucket->next;
43 }
44 }
45 return items == this->items;
46}
47
Hisham Muhammad36848492006-11-12 21:52:14 +000048int Hashtable_count(Hashtable* this) {
49 int items = 0;
50 for (int i = 0; i < this->size; i++) {
51 HashtableItem* bucket = this->buckets[i];
52 while (bucket) {
53 items++;
54 bucket = bucket->next;
55 }
56 }
57 assert(items == this->items);
58 return items;
59}
60
Hisham Muhammad110ce712006-11-08 20:09:48 +000061#endif
62
Hisham Muhammadda23c8c2008-03-09 08:58:38 +000063static HashtableItem* HashtableItem_new(unsigned int key, void* value) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000064 HashtableItem* this;
65
66 this = (HashtableItem*) malloc(sizeof(HashtableItem));
67 this->key = key;
68 this->value = value;
69 this->next = NULL;
70 return this;
71}
72
73Hashtable* Hashtable_new(int size, bool owner) {
74 Hashtable* this;
75
76 this = (Hashtable*) malloc(sizeof(Hashtable));
Hisham Muhammad110ce712006-11-08 20:09:48 +000077 this->items = 0;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000078 this->size = size;
Hisham Muhammad76a715e2014-01-16 18:51:16 -020079 this->buckets = (HashtableItem**) calloc(size, sizeof(HashtableItem*));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000080 this->owner = owner;
Hisham Muhammad110ce712006-11-08 20:09:48 +000081 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000082 return this;
83}
84
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000085void Hashtable_delete(Hashtable* this) {
Hisham Muhammad110ce712006-11-08 20:09:48 +000086 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000087 for (int i = 0; i < this->size; i++) {
88 HashtableItem* walk = this->buckets[i];
89 while (walk != NULL) {
90 if (this->owner)
91 free(walk->value);
92 HashtableItem* savedWalk = walk;
93 walk = savedWalk->next;
94 free(savedWalk);
95 }
96 }
97 free(this->buckets);
98 free(this);
99}
100
Hisham Muhammada227b202007-04-05 19:53:23 +0000101void Hashtable_put(Hashtable* this, unsigned int key, void* value) {
102 unsigned int index = key % this->size;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000103 HashtableItem** bucketPtr = &(this->buckets[index]);
104 while (true)
105 if (*bucketPtr == NULL) {
106 *bucketPtr = HashtableItem_new(key, value);
107 this->items++;
108 break;
109 } else if ((*bucketPtr)->key == key) {
110 if (this->owner)
111 free((*bucketPtr)->value);
112 (*bucketPtr)->value = value;
113 break;
114 } else
115 bucketPtr = &((*bucketPtr)->next);
Hisham Muhammad110ce712006-11-08 20:09:48 +0000116 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000117}
118
Hisham Muhammada227b202007-04-05 19:53:23 +0000119void* Hashtable_remove(Hashtable* this, unsigned int key) {
120 unsigned int index = key % this->size;
Hisham Muhammad110ce712006-11-08 20:09:48 +0000121
122 assert(Hashtable_isConsistent(this));
123
124 HashtableItem** bucket;
125 for (bucket = &(this->buckets[index]); *bucket; bucket = &((*bucket)->next) ) {
126 if ((*bucket)->key == key) {
127 void* value = (*bucket)->value;
128 HashtableItem* next = (*bucket)->next;
129 free(*bucket);
130 (*bucket) = next;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000131 this->items--;
132 if (this->owner) {
Hisham Muhammad110ce712006-11-08 20:09:48 +0000133 free(value);
134 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000135 return NULL;
136 } else {
Hisham Muhammad110ce712006-11-08 20:09:48 +0000137 assert(Hashtable_isConsistent(this));
138 return value;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000139 }
Hisham Muhammad110ce712006-11-08 20:09:48 +0000140 }
141 }
142 assert(Hashtable_isConsistent(this));
143 return NULL;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000144}
Hisham Muhammad110ce712006-11-08 20:09:48 +0000145
Hisham Muhammada227b202007-04-05 19:53:23 +0000146inline void* Hashtable_get(Hashtable* this, unsigned int key) {
147 unsigned int index = key % this->size;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000148 HashtableItem* bucketPtr = this->buckets[index];
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000149 while (true) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000150 if (bucketPtr == NULL) {
Hisham Muhammad110ce712006-11-08 20:09:48 +0000151 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000152 return NULL;
153 } else if (bucketPtr->key == key) {
Hisham Muhammad110ce712006-11-08 20:09:48 +0000154 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000155 return bucketPtr->value;
156 } else
157 bucketPtr = bucketPtr->next;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000158 }
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000159}
160
161void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
Hisham Muhammad110ce712006-11-08 20:09:48 +0000162 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000163 for (int i = 0; i < this->size; i++) {
164 HashtableItem* walk = this->buckets[i];
165 while (walk != NULL) {
166 f(walk->key, walk->value, userData);
167 walk = walk->next;
168 }
169 }
Hisham Muhammad110ce712006-11-08 20:09:48 +0000170 assert(Hashtable_isConsistent(this));
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000171}