(file) Return to hashmap.c CVS log (file) (dir) Up to [OMI] / omi / pal

  1 krisbash 1.1 /*
  2              **==============================================================================
  3              **
  4              ** Open Management Infrastructure (OMI)
  5              **
  6              ** Copyright (c) Microsoft Corporation
  7              ** 
  8              ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  9              ** use this file except in compliance with the License. You may obtain a copy 
 10              ** of the License at 
 11              **
 12              **     http://www.apache.org/licenses/LICENSE-2.0 
 13              **
 14              ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15              ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
 16              ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
 17              ** MERCHANTABLITY OR NON-INFRINGEMENT. 
 18              **
 19              ** See the Apache 2 License for the specific language governing permissions 
 20              ** and limitations under the License.
 21              **
 22 krisbash 1.1 **==============================================================================
 23              */
 24              
 25              #include "hashmap.h"
 26              
 27              int HashMap_Init(
 28                  _Out_ HashMap* self,
 29                  size_t numLists,
 30                  _In_ HashMapHashProc hash,
 31                  _In_ HashMapEqualProc equal,
 32                  _In_ HashMapReleaseProc release)
 33              {
 34                  /* Allocate array of hash chains */
 35              
 36                  self->lists = SystemCalloc(numLists, sizeof(HashBucket*));
 37                  if (!self->lists)
 38                      return -1;
 39                  self->listsOwnedByHashMap = PAL_TRUE;
 40              
 41                  /* Save the function arguments */
 42              
 43 krisbash 1.1     self->numLists = numLists;
 44                  self->hash = hash;
 45                  self->equal = equal;
 46                  self->release = release;
 47              
 48                  return 0;
 49              }
 50              
 51              void HashMap_Construct(
 52                  _Out_ HashMap* self,
 53                  size_t numLists,
 54                  _Out_writes_(numLists) void** buckets,
 55                  _In_ HashMapHashProc hash,
 56                  _In_ HashMapEqualProc equal,
 57                  _In_ HashMapReleaseProc release)
 58              {
 59                  /* Remember pointer to the array of hash chains */
 60              
 61                  self->lists = (HashBucket**) buckets;
 62                  memset(self->lists, 0, sizeof(void*) * numLists);
 63                  self->listsOwnedByHashMap = PAL_FALSE;
 64 krisbash 1.1 
 65                  /* Save the function arguments */
 66              
 67                  self->numLists = numLists;
 68                  self->hash = hash;
 69                  self->equal = equal;
 70                  self->release = release;
 71              }
 72              
 73              void HashMap_Destroy(
 74                  _In_ _Post_invalid_ HashMap* self)
 75              {
 76                  size_t i;
 77              
 78                  for (i = 0; i < self->numLists; i++)
 79                  {
 80                      HashBucket* p;
 81              
 82                      for (p = self->lists[i]; p; )
 83                      {
 84                          HashBucket* next = p->next;
 85 krisbash 1.1             self->release(p);
 86                          p = next;
 87                      }
 88                  }
 89              
 90                  if (self->listsOwnedByHashMap)
 91                  {
 92                      SystemFree(self->lists);
 93                  }
 94              }
 95              
 96              _Ret_maybenull_ HashBucket* HashMap_Find(
 97                  _In_ HashMap* self,
 98                  _In_ const HashBucket* keyBucket)
 99              {
100                  size_t index;
101                  HashBucket* p;
102              
103                  /* Hash the key */
104              
105                  index = self->hash(keyBucket) % self->numLists;
106 krisbash 1.1 
107                  /* Search for matching bucket */
108              
109                  for (p = self->lists[index]; p; p = p->next)
110                  {
111                      if (self->equal(p, keyBucket))
112                      {
113                          return p;
114                      }
115                  }
116              
117                  /* Not found */
118                  return 0;
119              }
120              
121              int HashMap_Insert(
122                  _In_ HashMap* self,
123                  _Pre_notnull_ HashBucket* bucket)
124              {
125                  size_t index;
126                  HashBucket* p;
127 krisbash 1.1 
128                  /* Hash the key */
129              
130                  index = self->hash(bucket) % self->numLists;
131              
132                  /* Search for matching bucket */
133              
134                  for (p = self->lists[index]; p; p = p->next)
135                  {
136                      if (self->equal(p, bucket))
137                      {
138                          /* Already exists */
139                          return 1;
140                      }
141                  }
142              
143                  /* Insert at front of hash list */
144              
145                  bucket->next = self->lists[index];
146                  self->lists[index] = bucket;
147              
148 krisbash 1.1     return 0;
149              }
150              
151              int HashMap_Remove(
152                  _In_ HashMap* self,
153                  _In_ const HashBucket* keyBucket)
154              {
155                  size_t index;
156                  HashBucket* p;
157              
158                  /* Hash the key */
159              
160                  index = self->hash(keyBucket) % self->numLists;
161              
162                  /* Search for matching bucket */
163                  {
164                      HashBucket* prev = 0;
165              
166                      for (p = self->lists[index]; p; p = p->next)
167                      {
168                          if (self->equal(p, keyBucket))
169 krisbash 1.1             {
170                              if (prev)
171                                  prev->next = p->next;
172                              else
173                                  self->lists[index] = p->next;
174              
175                              self->release(p);
176                              return 0;
177                          }
178              
179                          prev = p;
180                      }
181                  }
182              
183                  /* Not found */
184                  return -1;
185              }
186              
187              void HashMap_BeginIteration(
188                  _In_ HashMap* self,
189                  _Out_ HashMapIterator* iterator)
190 krisbash 1.1 {
191                  if (self->numLists > 0) 
192                  {
193                      iterator->index = 0;
194                      iterator->current = self->lists[0];
195                  } 
196                  else 
197                  {
198                      iterator->index = 0;
199                      iterator->current = NULL;
200                  }
201              }
202              
203              _Ret_maybenull_ 
204              const HashBucket* HashMap_Iterate(
205                  _In_ HashMap* self,
206                  _Inout_ HashMapIterator* iterator)
207              {
208                  const HashBucket *result;
209              
210                  if (iterator->index >= self->numLists)
211 krisbash 1.1         return NULL;
212              
213                  while (!iterator->current) 
214                  {
215                      size_t index = ++iterator->index;
216              
217                      if (index >= self->numLists)
218                          return NULL;
219              
220                      iterator->current = self->lists[index];
221                  }
222              
223                  result = iterator->current;
224                  iterator->current = result->next;
225              
226                  return result;
227              }
228              
229              _Ret_maybenull_ 
230              const HashBucket* HashMap_Top(
231                  _In_ HashMap* self,
232 krisbash 1.1     _Inout_ size_t *iter)
233              {
234                  for (; *iter < self->numLists; ++*iter)
235                  {
236                      HashBucket *bucket = self->lists[*iter];
237                      if (bucket)
238                      {
239                          return bucket;
240                      }
241                  }
242                  return NULL;
243              }
244              

ViewCVS 0.9.2