nss_hash.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /* Copyright (c) 1997-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #include <nss.h>
  15. /* This is from libc/db/hash/hash_func.c, hash3 is static there */
  16. /*
  17. * This is INCREDIBLY ugly, but fast. We break the string up into 4 byte
  18. * units. On the first time through the loop we get the "leftover bytes"
  19. * (len % 4). On every other iteration, we perform a 4x unrolled version
  20. * HASHC. Further unrolling does not appear to help.
  21. *
  22. * OZ's original sdbm hash
  23. */
  24. uint32_t
  25. __nss_hash (const void *keyarg, size_t len)
  26. {
  27. enum
  28. {
  29. HASH_CONST_P0 = 1, /* (uint32_t)(65599 ^ 0). */
  30. HASH_CONST_P1 = 65599, /* (uint32_t)(65599 ^ 1). */
  31. HASH_CONST_P2 = 8261505, /* (uint32_t)(65599 ^ 2). */
  32. HASH_CONST_P3 = 780587199, /* (uint32_t)(65599 ^ 3). */
  33. HASH_CONST_P4 = 1139564289 /* (uint32_t)(65599 ^ 4). */
  34. };
  35. const unsigned char *key;
  36. uint32_t h;
  37. #define HASHC h = *key++ + HASH_CONST_P1 * h
  38. h = 0;
  39. key = keyarg;
  40. if (len > 0)
  41. {
  42. switch ((len & (4 - 1)))
  43. {
  44. case 0:
  45. /* h starts out as zero so no need to include the multiply. */
  46. h = *key++;
  47. [[fallthrough]];
  48. case 3:
  49. HASHC;
  50. [[fallthrough]];
  51. case 2:
  52. HASHC;
  53. [[fallthrough]];
  54. case 1:
  55. HASHC;
  56. /* FALLTHROUGH */
  57. }
  58. uint32_t c0, c1, c2, c3;
  59. for (--len; len >= 4; len -= 4)
  60. {
  61. c0 = (unsigned char) *(key + 0);
  62. c1 = (unsigned char) *(key + 1);
  63. c2 = (unsigned char) *(key + 2);
  64. c3 = (unsigned char) *(key + 3);
  65. h = HASH_CONST_P4 * h + HASH_CONST_P3 * c0 + HASH_CONST_P2 * c1
  66. + HASH_CONST_P1 * c2 + HASH_CONST_P0 * c3;
  67. key += 4;
  68. }
  69. }
  70. return h;
  71. }
  72. libc_hidden_def (__nss_hash)