Hasher.pm 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. # Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
  2. # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
  3. # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
  4. # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
  5. # Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
  6. # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
  7. # Copyright (C) Research In Motion Limited 2010. All rights reserved.
  8. # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
  9. # Copyright (C) 2011 Patrick Gansterer <paroga@webkit.org>
  10. # Copyright (C) 2012 Ericsson AB. All rights reserved.
  11. #
  12. # This library is free software; you can redistribute it and/or
  13. # modify it under the terms of the GNU Library General Public
  14. # License as published by the Free Software Foundation; either
  15. # version 2 of the License, or (at your option) any later version.
  16. #
  17. # This library is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. # Library General Public License for more details.
  21. #
  22. # You should have received a copy of the GNU Library General Public License
  23. # along with this library; see the file COPYING.LIB. If not, write to
  24. # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  25. # Boston, MA 02110-1301, USA.
  26. package Hasher;
  27. use strict;
  28. sub leftShift($$) {
  29. my ($value, $distance) = @_;
  30. return (($value << $distance) & 0xFFFFFFFF);
  31. }
  32. # Paul Hsieh's SuperFastHash
  33. # http://www.azillionmonkeys.com/qed/hash.html
  34. sub GenerateHashValue
  35. {
  36. my @chars = split(/ */, $_[0]);
  37. # This hash is designed to work on 16-bit chunks at a time. But since the normal case
  38. # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
  39. # were 16-bit chunks, which should give matching results
  40. my $EXP2_32 = 4294967296;
  41. my $hash = 0x9e3779b9;
  42. my $l = scalar @chars; #I wish this was in Ruby --- Maks
  43. my $rem = $l & 1;
  44. $l = $l >> 1;
  45. my $s = 0;
  46. # Main loop
  47. for (; $l > 0; $l--) {
  48. $hash += ord($chars[$s]);
  49. my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
  50. $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
  51. $s += 2;
  52. $hash += $hash >> 11;
  53. $hash %= $EXP2_32;
  54. }
  55. # Handle end case
  56. if ($rem != 0) {
  57. $hash += ord($chars[$s]);
  58. $hash ^= (leftShift($hash, 11)% $EXP2_32);
  59. $hash += $hash >> 17;
  60. }
  61. # Force "avalanching" of final 127 bits
  62. $hash ^= leftShift($hash, 3);
  63. $hash += ($hash >> 5);
  64. $hash = ($hash% $EXP2_32);
  65. $hash ^= (leftShift($hash, 2)% $EXP2_32);
  66. $hash += ($hash >> 15);
  67. $hash = $hash% $EXP2_32;
  68. $hash ^= (leftShift($hash, 10)% $EXP2_32);
  69. # Save 8 bits for StringImpl to use as flags.
  70. $hash &= 0xffffff;
  71. # This avoids ever returning a hash code of 0, since that is used to
  72. # signal "hash not computed yet". Setting the high bit maintains
  73. # reasonable fidelity to a hash code of 0 because it is likely to yield
  74. # exactly 0 when hash lookup masks out the high bits.
  75. $hash = (0x80000000 >> 8) if ($hash == 0);
  76. return $hash;
  77. }
  78. 1;