hub/heap.c

Go to the documentation of this file.
00001 /*
00002  * Utu -- Saving The Internet With Hate
00003  *
00004  * Copyright (c) Zed A. Shaw 2005 (zedshaw@zedshaw.com)
00005  *
00006  * This file is modifiable/redistributable under the terms of the GNU
00007  * General Public License.
00008  *
00009  * You should have recieved a copy of the GNU General Public License along
00010  * with this program; see the file COPYING. If not, write to the Free Software
00011  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 0211-1307, USA.
00012  *
00013  * Code some code taken from the fantastic SGLIB by Marian Vittek and available
00014  * as LGPL from  http://www.xref-tech.com/sglib.
00015  */
00016 
00017 #include "heap.h"
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <assert.h>
00021 
00022 
00023 Heap *Heap_create()
00024 {
00025   Heap *heap = calloc(1, sizeof(Heap));
00026   assert(heap && "Failed to allocate heap.");
00027 
00028   heap->members = calloc(HEAP_SIZE, sizeof(void *));
00029   assert(heap->members && "Failed to allocate members for heap.");
00030 
00031   heap->size = HEAP_SIZE;
00032 
00033   return heap;
00034 }
00035 
00036 #define VOID_PTR_COMPARE(x,y) ((int)(x) - (int)(y))
00037 
00038 size_t Heap_add(Heap *heap, void *elem)
00039 {
00040   assert(heap && "heap is NULL");
00041   assert(elem && "elem is NULL");
00042 
00043   if(Heap_is_full(heap)) {
00044     // simple doubling is probably bad
00045     Heap_resize(heap, heap->size * 2);
00046   }
00047 
00048   register size_t i = heap->last;
00049   register size_t j = i/2;
00050 
00051   heap->members[i] = elem;
00052   while (i > 0 && VOID_PTR_COMPARE(heap->members[i], heap->members[j]) < 0) {
00053     void *t = heap->members[j];
00054     heap->members[j] = heap->members[j];
00055     heap->members[j] = t;
00056 
00057     i = j; j = i/2;
00058   }
00059 
00060   assert(i <= heap->last && "Buffer overflow on add to heap.");
00061 
00062   return ++heap->last;
00063 }
00064 
00065 void Heap_resize(Heap *heap, size_t size)
00066 {
00067   assert(size > 0 && "Cannot resize to 0.");
00068 
00069   heap->members = realloc(heap->members, size * sizeof(void *));
00070   assert(heap->members != NULL && "Failed to realloc new Heap.");
00071 
00072   // now we have to clear the tail end since realloc doesn't do that
00073   if(size > heap->size) {
00074     size_t diff = (size < heap->size ? heap->size - size : size - heap->size);
00075     memset(heap->members + heap->size, 0, diff * sizeof(void *));
00076   }
00077 
00078   heap->size = size;
00079 }
00080 
00081 size_t Heap_find(Heap *heap, void *elem)
00082 {
00083   size_t result_index = 0;
00084 
00085   assert(heap && "heap is NULL");
00086   assert(elem && "elem is NULL");
00087 
00088   register int kk, cc, ii, jj, ff;
00089   ii = 0; 
00090   jj = heap->last-1;
00091   ff = 0;
00092   while (ii <= jj && ff==0) {
00093     kk = (jj+ii)/2;
00094     cc = VOID_PTR_COMPARE((heap->members[kk]), elem);
00095     if (cc == 0) {
00096       result_index = kk;    
00097       ff = 1;
00098     } else if (cc < 0) {
00099       ii = kk+1;
00100     } else {
00101       jj = kk-1;
00102     }
00103   }
00104   if (ff == 0) {
00105     // not found, return heap->last to indicate that it's outside realm
00106     return heap->last;
00107   }
00108 
00109   return result_index;
00110 }
00111 
00112 int Heap_delete(Heap *heap, void *elem)
00113 {
00114   assert(heap && "heap is NULL");
00115   assert(elem && "elem is NULL");
00116 
00117   size_t i = Heap_find(heap, elem);
00118 
00119   if(Heap_valid(heap, i)) {
00120     // simplest way to delete is just move the rest down by one
00121     memmove(heap->members + i, heap->members + i + 1, (heap->last - i - 1) * (sizeof(void *)));
00122 
00123     heap->last--;
00124     // just make sure the last one is null always
00125     heap->members[heap->last] = NULL;
00126 
00127     // don't bother dropping the size below HEAP_SIZE
00128     if(heap->last > HEAP_SIZE && heap->last < heap->size / 2) {
00129       // it's dropped to less than half the size, cut it down
00130       Heap_resize(heap, heap->size / 2);
00131     }
00132 
00133     return 1;
00134   } else {
00135     return 0;
00136   }
00137 }
00138 
00139 void Heap_destroy(Heap *heap)
00140 {
00141   assert(heap && heap->members && "invalid heap destroyed");
00142   free(heap->members);
00143   heap->members = NULL;
00144   free(heap);
00145 }
00146 

Generated on Tue Apr 10 01:00:18 2007 for Utu by  doxygen 1.5.1