• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

SuperFastHash.cpp

Go to the documentation of this file.
00001 #include "SuperFastHash.h"
00002 #include "NativeTypes.h"
00003 #include <stdlib.h>
00004 
00005 #if !defined(_WIN32)
00006 #include <stdint.h>
00007 #endif
00008 
00009 #undef get16bits
00010 #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
00011   || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
00012 #define get16bits(d) (*((const uint16_t *) (d)))
00013 #endif
00014 
00015 #if !defined (get16bits)
00016 #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
00017                        +(uint32_t)(((const uint8_t *)(d))[0]) )
00018 #endif
00019 
00020 static const int INCREMENTAL_READ_BLOCK=65536;
00021 
00022 unsigned int SuperFastHash (const char * data, int length)
00023 {
00024         // All this is necessary or the hash does not match SuperFastHashIncremental
00025         int bytesRemaining=length;
00026         unsigned int lastHash = length;
00027         int offset=0;
00028         while (bytesRemaining>=INCREMENTAL_READ_BLOCK)
00029         {
00030                 lastHash=SuperFastHashIncremental (data+offset, INCREMENTAL_READ_BLOCK, lastHash );
00031                 bytesRemaining-=INCREMENTAL_READ_BLOCK;
00032                 offset+=INCREMENTAL_READ_BLOCK;
00033         }
00034         if (bytesRemaining>0)
00035         {
00036                 lastHash=SuperFastHashIncremental (data+offset, bytesRemaining, lastHash );
00037         }
00038         return lastHash;
00039 
00040 //      return SuperFastHashIncremental(data,len,len);
00041 }
00042 unsigned int SuperFastHashIncremental (const char * data, int len, unsigned int lastHash )
00043 {
00044         uint32_t hash = (uint32_t) lastHash;
00045         uint32_t tmp;
00046         int rem;
00047 
00048         if (len <= 0 || data == NULL) return 0;
00049 
00050         rem = len & 3;
00051         len >>= 2;
00052 
00053         /* Main loop */
00054         for (;len > 0; len--) {
00055                 hash  += get16bits (data);
00056                 tmp    = (get16bits (data+2) << 11) ^ hash;
00057                 hash   = (hash << 16) ^ tmp;
00058                 data  += 2*sizeof (uint16_t);
00059                 hash  += hash >> 11;
00060         }
00061 
00062         /* Handle end cases */
00063         switch (rem) {
00064                 case 3: hash += get16bits (data);
00065                         hash ^= hash << 16;
00066                         hash ^= data[sizeof (uint16_t)] << 18;
00067                         hash += hash >> 11;
00068                         break;
00069                 case 2: hash += get16bits (data);
00070                         hash ^= hash << 11;
00071                         hash += hash >> 17;
00072                         break;
00073                 case 1: hash += *data;
00074                         hash ^= hash << 10;
00075                         hash += hash >> 1;
00076         }
00077 
00078         /* Force "avalanching" of final 127 bits */
00079         hash ^= hash << 3;
00080         hash += hash >> 5;
00081         hash ^= hash << 4;
00082         hash += hash >> 17;
00083         hash ^= hash << 25;
00084         hash += hash >> 6;
00085 
00086         return (unsigned int) hash;
00087 
00088 }
00089 
00090 unsigned int SuperFastHashFile (const char * filename)
00091 {
00092         FILE *fp = fopen(filename, "rb");
00093         if (fp==0)
00094                 return 0;
00095         unsigned int hash = SuperFastHashFilePtr(fp);
00096         fclose(fp);
00097         return hash;
00098 }
00099 
00100 unsigned int SuperFastHashFilePtr (FILE *fp)
00101 {
00102         fseek(fp, 0, SEEK_END);
00103         int length = ftell(fp);
00104         fseek(fp, 0, SEEK_SET);
00105         int bytesRemaining=length;
00106         unsigned int lastHash = length;
00107         char readBlock[INCREMENTAL_READ_BLOCK];
00108         while (bytesRemaining>=(int) sizeof(readBlock))
00109         {
00110                 fread(readBlock, sizeof(readBlock), 1, fp);
00111                 lastHash=SuperFastHashIncremental (readBlock, (int) sizeof(readBlock), lastHash );
00112                 bytesRemaining-=(int) sizeof(readBlock);
00113         }
00114         if (bytesRemaining>0)
00115         {
00116                 fread(readBlock, bytesRemaining, 1, fp);
00117                 lastHash=SuperFastHashIncremental (readBlock, bytesRemaining, lastHash );
00118         }
00119         return lastHash;
00120 }

Generated on Thu Sep 30 2010 01:27:28 for RakNet by  doxygen 1.7.1