// The MIT License (MIT)// Copyright (c) 2014 Andreas Briese, eduToolbox@Bri-C GmbH, Sarstedt// Permission is hereby granted, free of charge, to any person obtaining a copy of// this software and associated documentation files (the "Software"), to deal in// the Software without restriction, including without limitation the rights to// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of// the Software, and to permit persons to whom the Software is furnished to do so,// subject to the following conditions:// The above copyright notice and this permission notice shall be included in all// copies or substantial portions of the Software.// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.package zimport ()// helpervar mask = []uint8{1, 2, 4, 8, 16, 32, 64, 128}func getSize( uint64) ( uint64, uint64) {if < uint64(512) { = uint64(512) } = uint64(1)for < { <<= 1 ++ }return , }func calcSizeByWrongPositives(, float64) (uint64, uint64) { := -1 * * math.Log() / math.Pow(float64(0.69314718056), 2) := math.Ceil(float64(0.69314718056) * / )returnuint64(), uint64()}// NewBloomFilter returns a new bloomfilter.func ( ...float64) ( *Bloom) {var , uint64iflen() == 2 {if [1] < 1 { , = calcSizeByWrongPositives([0], [1]) } else { , = uint64([0]), uint64([1]) } } else {log.Fatal("usage: New(float64(number_of_entries), float64(number_of_hashlocations))" +" i.e. New(float64(1000), float64(3)) or New(float64(number_of_entries)," +" float64(number_of_hashlocations)) i.e. New(float64(1000), float64(0.03))") } , := getSize() = &Bloom{sizeExp: ,size: - 1,setLocs: ,shift: 64 - , } .Size()return}// Bloom filtertypeBloomstruct { bitset []uint64 ElemNum uint64 sizeExp uint64 size uint64 setLocs uint64 shift uint64}// <--- http://www.cse.yorku.ca/~oz/hash.html// modified Berkeley DB Hash (32bit)// hash is casted to l, h = 16bit fragments// func (bl Bloom) absdbm(b *[]byte) (l, h uint64) {// hash := uint64(len(*b))// for _, c := range *b {// hash = uint64(c) + (hash << 6) + (hash << bl.sizeExp) - hash// }// h = hash >> bl.shift// l = hash << bl.shift >> bl.shift// return l, h// }// Add adds hash of a key to the bloomfilter.func ( *Bloom) ( uint64) { := >> .shift := << .shift >> .shiftfor := uint64(0); < .setLocs; ++ { .Set(( + *) & .size) .ElemNum++ }}// Has checks if bit(s) for entry hash is/are set,// returns true if the hash was added to the Bloom Filter.func ( Bloom) ( uint64) bool { := >> .shift := << .shift >> .shiftfor := uint64(0); < .setLocs; ++ {if !.IsSet(( + *) & .size) {returnfalse } }returntrue}// AddIfNotHas only Adds hash, if it's not present in the bloomfilter.// Returns true if hash was added.// Returns false if hash was already registered in the bloomfilter.func ( *Bloom) ( uint64) bool {if .Has() {returnfalse } .Add()returntrue}// TotalSize returns the total size of the bloom filter.func ( *Bloom) () int {// The bl struct has 5 members and each one is 8 byte. The bitset is a // uint64 byte slice.returnlen(.bitset)*8 + 5*8}// Size makes Bloom filter with as bitset of size sz.func ( *Bloom) ( uint64) { .bitset = make([]uint64, >>6)}// Clear resets the Bloom filter.func ( *Bloom) () {for := range .bitset { .bitset[] = 0 }}// Set sets the bit[idx] of bitset.func ( *Bloom) ( uint64) { := unsafe.Pointer(uintptr(unsafe.Pointer(&.bitset[>>6])) + uintptr((%64)>>3)) *(*uint8)() |= mask[%8]}// IsSet checks if bit[idx] of bitset is set, returns true/false.func ( *Bloom) ( uint64) bool { := unsafe.Pointer(uintptr(unsafe.Pointer(&.bitset[>>6])) + uintptr((%64)>>3)) := ((*(*uint8)()) >> ( % 8)) & 1return == 1}// bloomJSONImExport// Im/Export structure used by JSONMarshal / JSONUnmarshaltype bloomJSONImExport struct { FilterSet []byte SetLocs uint64}// NewWithBoolset takes a []byte slice and number of locs per entry,// returns the bloomfilter with a bitset populated according to the input []byte.func newWithBoolset( *[]byte, uint64) *Bloom { := NewBloomFilter(float64(len(*)<<3), float64())for , := range * { *(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(&.bitset[0])) + uintptr())) = }return}// JSONUnmarshal takes JSON-Object (type bloomJSONImExport) as []bytes// returns bloom32 / bloom64 object.func ( []byte) (*Bloom, error) { := bloomJSONImExport{}if := json.Unmarshal(, &); != nil {returnnil, } := bytes.NewBuffer(.FilterSet) := .Bytes() := newWithBoolset(&, .SetLocs)return , nil}// JSONMarshal returns JSON-object (type bloomJSONImExport) as []byte.func ( Bloom) () []byte { := bloomJSONImExport{} .SetLocs = .setLocs .FilterSet = make([]byte, len(.bitset)<<3)for := range .FilterSet { .FilterSet[] = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&.bitset[0])) +uintptr())) } , := json.Marshal()if != nil {log.Fatal("json.Marshal failed: ", ) }return}
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.