github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/util/string.go (about)

     1  package util
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strconv"
     7  	"time"
     8  )
     9  
    10  const primeRK = 16777619
    11  
    12  /* simple string hash used by Go strings package */
    13  func Hashstr(sep string) int {
    14  	hash := uint32(0)
    15  	for i := 0; i < len(sep); i++ {
    16  		hash = hash*primeRK + uint32(sep[i])
    17  	}
    18  	return int(hash)
    19  }
    20  
    21  // util/StringHelper.java
    22  
    23  /*
    24  Poached from Guava: set a different salt/seed for each VM instance,
    25  to frustrate hash key collision denial of service attacks, and to
    26  catch any places that somehow rely on hash function/order across VM
    27  instances:
    28  */
    29  var GOOD_FAST_HASH_SEED = func() uint32 {
    30  	if prop := os.Getenv("tests_seed"); prop != "" {
    31  		// so if there is a test failure that relied on hash order, we
    32  		// remain reproducible based on the test seed:
    33  		if len(prop) > 8 {
    34  			prop = prop[len(prop)-8:]
    35  		}
    36  		n, err := strconv.ParseInt(prop, 16, 64)
    37  		if err != nil {
    38  			panic(err)
    39  		}
    40  		fmt.Printf("tests_seed=%v\n", uint32(n))
    41  		return uint32(n)
    42  	} else {
    43  		return uint32(time.Now().Nanosecond())
    44  	}
    45  }()
    46  
    47  /* Returns true iff the ref starts with the given prefix. Otherwise false. */
    48  func StartsWith(ref, prefix []byte) bool {
    49  	return sliceEquals(ref, prefix, 0)
    50  }
    51  
    52  func sliceEquals(sliceToTest, other []byte, pos int) bool {
    53  	panic("niy")
    54  }
    55  
    56  /*
    57  Returns the MurmurHash3_x86_32 hash.
    58  Original source/tests at https://github.com/yonik/java_util/
    59  */
    60  func MurmurHash3_x86_32(data []byte, seed uint32) uint32 {
    61  	c1, c2 := uint32(0xcc9e2d51), uint32(0x1b873593)
    62  
    63  	h1 := seed
    64  	roundedEnd := (len(data) & 0xfffffffc) // round down to 4 byte block
    65  
    66  	for i := 0; i < roundedEnd; i += 4 {
    67  		// little endian load order
    68  		k1 := uint32(data[i]) | (uint32(data[i+1]) << 8) |
    69  			(uint32(data[i+2]) << 16) | (uint32(data[i+3]) << 24)
    70  		k1 *= c1
    71  		k1 = rotateLeft(k1, 15)
    72  		k1 *= c2
    73  
    74  		h1 ^= k1
    75  		h1 = rotateLeft(h1, 13)
    76  		h1 = h1*5 + 0xe6546b64
    77  	}
    78  
    79  	// tail
    80  	k1 := uint32(0)
    81  
    82  	left := len(data) & 0x03
    83  	if left == 3 {
    84  		k1 = uint32(data[roundedEnd+2]) << 16
    85  	}
    86  	if left >= 2 {
    87  		k1 |= uint32(data[roundedEnd+1]) << 8
    88  	}
    89  	if left >= 1 {
    90  		k1 |= uint32(data[roundedEnd])
    91  		k1 *= c1
    92  		k1 = rotateLeft(k1, 15)
    93  		k1 *= c2
    94  		h1 ^= k1
    95  	}
    96  
    97  	// finalization
    98  	h1 ^= uint32(len(data))
    99  
   100  	// fmix(h1);
   101  	h1 ^= h1 >> 16
   102  	h1 *= 0x85ebca6b
   103  	h1 ^= h1 >> 13
   104  	h1 *= 0xc2b2ae35
   105  	h1 ^= h1 >> 16
   106  
   107  	return h1
   108  }
   109  
   110  func rotateLeft(n uint32, offset uint) uint32 {
   111  	mask := uint32(1<<(32-offset)) - 1
   112  	hi := (n & mask) << offset
   113  	low := (n - (n & mask)) >> (32 - offset)
   114  	return hi | low
   115  }