]> code.citadel.org Git - citadel.git/blobdiff - libcitadel/lib/hash.c
* *grml* always tried to avoid this, but can't live without...
[citadel.git] / libcitadel / lib / hash.c
index d6c5b474535f18e841bbdabfbb12786d04da2314..b3c75795bd1438ac130240a054cc9df5e885b055 100644 (file)
@@ -46,6 +46,7 @@ struct HashPos {
         * \brief Anonymous Hash Iterator Object. used for traversing the whole array from outside 
         */
        long Position;
+       int StepWidth;
 };
 
 
@@ -409,6 +410,20 @@ static long FindInHash(HashList *Hash, long HashBinKey)
        return SearchPos;
 }
 
+
+/**
+ * \brief another hashing algorithm; treat it as just a pointer to long.
+ * \param str Our pointer to the long value
+ * \param len the length of the data pointed to; needs to be sizeof int, else we won't use it!
+ * \returns the calculated hash value
+ */
+int Flathash(const char *str, long len)
+{
+       if (len != sizeof (int))
+               return 0;
+       else return *(int*)str;
+}
+
 /**
  * \brief private abstract wrapper around the hashing algorithm
  * \param HKey the hash string
@@ -544,17 +559,41 @@ int GetHashKeys(HashList *Hash, char ***List)
 
 /**
  * \brief creates a hash-linear iterator object
+ * \param Hash the list we reference
+ * \param in which step width should we iterate?
+ *  If negative, the last position matching the 
+ *  step-raster is provided.
  * \returns the hash iterator
  */
-HashPos *GetNewHashPos(void)
+HashPos *GetNewHashPos(HashList *Hash, int StepWidth)
 {
        HashPos *Ret;
        
        Ret = (HashPos*)malloc(sizeof(HashPos));
-       Ret->Position = 0;
+       if (StepWidth != 0)
+               Ret->StepWidth = StepWidth;
+       else
+               Ret->StepWidth = 1;
+       if (Ret->StepWidth <  0) {
+               Ret->Position = (Hash->nMembersUsed % (-Ret->StepWidth)) 
+                       * (-Ret->StepWidth);
+       }
+       else {
+               Ret->Position = 0;
+       }
        return Ret;
 }
 
+/**
+ * \brief retrieve the counter from the itteratoor
+ * \param the Iterator to analyze
+ * \returns the n'th hashposition we point at
+ */
+int GetHashPosCounter(HashPos *At)
+{
+       return At->Position;
+}
+
 /**
  * \brief frees a linear hash iterator
  */
@@ -580,13 +619,40 @@ int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, const char **HashKe
 {
        long PayloadPos;
 
-       if ((Hash == NULL) || (Hash->nMembersUsed <= At->Position))
+       if ((Hash == NULL) || (At->Position >= Hash->nMembersUsed))
                return 0;
        *HKLen = Hash->LookupTable[At->Position]->HKLen;
        *HashKey = Hash->LookupTable[At->Position]->HashKey;
        PayloadPos = Hash->LookupTable[At->Position]->Position;
        *Data = Hash->Members[PayloadPos]->Data;
-       At->Position++;
+
+       At->Position += At->StepWidth;
+       if (At->Position > Hash->nMembersUsed) {
+               At->Position = Hash->nMembersUsed;
+               return 0;
+       }
+       return 1;
+}
+
+/**
+ * \brief Get the data located where At points to
+ * note: you should prefer iterator operations instead of using me.
+ * \param Hash your Hashlist peek from
+ * \param HKLen returns Length of Hashkey Returned
+ * \param HashKey returns the Hashkey corrosponding to HashPos
+ * \param Data returns the Data found at HashPos
+ * \returns whether the item was found or not.
+ */
+int GetHashAt(HashList *Hash,long At, long *HKLen, const char **HashKey, void **Data)
+{
+       long PayloadPos;
+
+       if ((Hash == NULL) || (At >= Hash->nMembersUsed))
+               return 0;
+       *HKLen = Hash->LookupTable[At]->HKLen;
+       *HashKey = Hash->LookupTable[At]->HashKey;
+       PayloadPos = Hash->LookupTable[At]->Position;
+       *Data = Hash->Members[PayloadPos]->Data;
        return 1;
 }
 
@@ -712,5 +778,14 @@ void generic_free_handler(void *ptr) {
        free(ptr);
 }
 
+/*
+ * Generic function to free a reference.  
+ * since a reference actualy isn't needed to be freed, do nothing.
+ */
+void reference_free_handler(void *ptr) 
+{
+       return;
+}
+