1
2
3
4
5
6
7 package json
8
9 import (
10 "encoding/binary"
11 "math/bits"
12 )
13
14
15 type stringCache = [256]string
16
17
18
19
20 func makeString(c *stringCache, b []byte) string {
21 const (
22 minCachedLen = 2
23 maxCachedLen = 256
24 )
25 if c == nil || len(b) < minCachedLen || len(b) > maxCachedLen {
26 return string(b)
27 }
28
29
30
31 var h uint32
32 switch {
33 case len(b) >= 8:
34 lo := binary.LittleEndian.Uint64(b[:8])
35 hi := binary.LittleEndian.Uint64(b[len(b)-8:])
36 h = hash64(uint32(lo), uint32(lo>>32)) ^ hash64(uint32(hi), uint32(hi>>32))
37 case len(b) >= 4:
38 lo := binary.LittleEndian.Uint32(b[:4])
39 hi := binary.LittleEndian.Uint32(b[len(b)-4:])
40 h = hash64(lo, hi)
41 case len(b) >= 2:
42 lo := binary.LittleEndian.Uint16(b[:2])
43 hi := binary.LittleEndian.Uint16(b[len(b)-2:])
44 h = hash64(uint32(lo), uint32(hi))
45 }
46
47
48 i := h % uint32(len(*c))
49 if s := (*c)[i]; s == string(b) {
50 return s
51 }
52 s := string(b)
53 (*c)[i] = s
54 return s
55 }
56
57
58 func hash64(lo, hi uint32) uint32 {
59
60
61
62
63
64 const (
65 prime1 = 0x9e3779b1
66 prime2 = 0x85ebca77
67 prime3 = 0xc2b2ae3d
68 prime4 = 0x27d4eb2f
69 prime5 = 0x165667b1
70 )
71 h := prime5 + uint32(8)
72 h += lo * prime3
73 h = bits.RotateLeft32(h, 17) * prime4
74 h += hi * prime3
75 h = bits.RotateLeft32(h, 17) * prime4
76
77
78
79 const avalanche = false
80 if avalanche {
81 h ^= h >> 15
82 h *= prime2
83 h ^= h >> 13
84 h *= prime3
85 h ^= h >> 16
86 }
87 return h
88 }
89
View as plain text