SuperFastHash.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "SuperFastHash.h"
  11. #include "NativeTypes.h"
  12. #include <stdlib.h>
  13. #if !defined(_WIN32)
  14. #include <stdint.h>
  15. #endif
  16. #undef get16bits
  17. #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
  18. || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
  19. #define get16bits(d) (*((const uint16_t *) (d)))
  20. #else
  21. #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
  22. +(uint32_t)(((const uint8_t *)(d))[0]) )
  23. #endif
  24. static const int INCREMENTAL_READ_BLOCK=65536;
  25. uint32_t SuperFastHash (const char * data, int length)
  26. {
  27. // All this is necessary or the hash does not match SuperFastHashIncremental
  28. int bytesRemaining=length;
  29. unsigned int lastHash = length;
  30. int offset=0;
  31. while (bytesRemaining>=INCREMENTAL_READ_BLOCK)
  32. {
  33. lastHash=SuperFastHashIncremental (data+offset, INCREMENTAL_READ_BLOCK, lastHash );
  34. bytesRemaining-=INCREMENTAL_READ_BLOCK;
  35. offset+=INCREMENTAL_READ_BLOCK;
  36. }
  37. if (bytesRemaining>0)
  38. {
  39. lastHash=SuperFastHashIncremental (data+offset, bytesRemaining, lastHash );
  40. }
  41. return lastHash;
  42. // return SuperFastHashIncremental(data,len,len);
  43. }
  44. uint32_t SuperFastHashIncremental (const char * data, int len, unsigned int lastHash )
  45. {
  46. uint32_t hash = (uint32_t) lastHash;
  47. uint32_t tmp;
  48. int rem;
  49. if (len <= 0 || data == NULL) return 0;
  50. rem = len & 3;
  51. len >>= 2;
  52. /* Main loop */
  53. for (;len > 0; len--) {
  54. hash += get16bits (data);
  55. tmp = (get16bits (data+2) << 11) ^ hash;
  56. hash = (hash << 16) ^ tmp;
  57. data += 2*sizeof (uint16_t);
  58. hash += hash >> 11;
  59. }
  60. /* Handle end cases */
  61. switch (rem) {
  62. case 3: hash += get16bits (data);
  63. hash ^= hash << 16;
  64. hash ^= data[sizeof (uint16_t)] << 18;
  65. hash += hash >> 11;
  66. break;
  67. case 2: hash += get16bits (data);
  68. hash ^= hash << 11;
  69. hash += hash >> 17;
  70. break;
  71. case 1: hash += *data;
  72. hash ^= hash << 10;
  73. hash += hash >> 1;
  74. }
  75. /* Force "avalanching" of final 127 bits */
  76. hash ^= hash << 3;
  77. hash += hash >> 5;
  78. hash ^= hash << 4;
  79. hash += hash >> 17;
  80. hash ^= hash << 25;
  81. hash += hash >> 6;
  82. return (uint32_t) hash;
  83. }
  84. uint32_t SuperFastHashFile (const char * filename)
  85. {
  86. FILE *fp = fopen(filename, "rb");
  87. if (fp==0)
  88. return 0;
  89. uint32_t hash = SuperFastHashFilePtr(fp);
  90. fclose(fp);
  91. return hash;
  92. }
  93. uint32_t SuperFastHashFilePtr (FILE *fp)
  94. {
  95. fseek(fp, 0, SEEK_END);
  96. int length = ftell(fp);
  97. fseek(fp, 0, SEEK_SET);
  98. int bytesRemaining=length;
  99. unsigned int lastHash = length;
  100. char readBlock[INCREMENTAL_READ_BLOCK];
  101. while (bytesRemaining>=(int) sizeof(readBlock))
  102. {
  103. fread(readBlock, sizeof(readBlock), 1, fp);
  104. lastHash=SuperFastHashIncremental (readBlock, (int) sizeof(readBlock), lastHash );
  105. bytesRemaining-=(int) sizeof(readBlock);
  106. }
  107. if (bytesRemaining>0)
  108. {
  109. fread(readBlock, bytesRemaining, 1, fp);
  110. lastHash=SuperFastHashIncremental (readBlock, bytesRemaining, lastHash );
  111. }
  112. return lastHash;
  113. }
粤ICP备19079148号