Import from old repository commit 61ef2b42a9c4ba8e1600f15bb0236765edc2ad45.
[sliver-openvswitch.git] / lib / hash.c
1 /*
2  * Copyright (c) 2008, 2009 Nicira Networks.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include <config.h>
17 #include "hash.h"
18 #include <string.h>
19
20 /* Returns the hash of the 'n' 32-bit words at 'p', starting from 'basis'.
21  * 'p' must be properly aligned. */
22 uint32_t
23 hash_words(const uint32_t *p, size_t n, uint32_t basis)
24 {
25     uint32_t a, b, c;
26
27     a = b = c = 0xdeadbeef + (((uint32_t) n) << 2) + basis;
28
29     while (n > 3) {
30         a += p[0];
31         b += p[1];
32         c += p[2];
33         HASH_MIX(a, b, c);
34         n -= 3;
35         p += 3;
36     }
37
38     switch (n) {
39     case 3:
40         c += p[2];
41         /* fall through */
42     case 2:
43         b += p[1];
44         /* fall through */
45     case 1:
46         a += p[0];
47         HASH_FINAL(a, b, c);
48         /* fall through */
49     case 0:
50         break;
51     }
52     return c;
53 }
54
55 /* Returns the hash of the 'n' bytes at 'p', starting from 'basis'. */
56 uint32_t
57 hash_bytes(const void *p_, size_t n, uint32_t basis)
58 {
59     const uint8_t *p = p_;
60     uint32_t a, b, c;
61     uint32_t tmp[3];
62
63     a = b = c = 0xdeadbeef + n + basis;
64
65     while (n >= sizeof tmp) {
66         memcpy(tmp, p, sizeof tmp);
67         a += tmp[0];
68         b += tmp[1];
69         c += tmp[2];
70         HASH_MIX(a, b, c);
71         n -= sizeof tmp;
72         p += sizeof tmp;
73     }
74
75     if (n) {
76         tmp[0] = tmp[1] = tmp[2] = 0;
77         memcpy(tmp, p, n);
78         a += tmp[0];
79         b += tmp[1];
80         c += tmp[2];
81         HASH_FINAL(a, b, c);
82     }
83
84     return c;
85 }