github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/base/comparer.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package base 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "fmt" 21 "strconv" 22 "unicode/utf8" 23 ) 24 25 type Compare func(a, b []byte) int 26 27 type Equal func(a, b []byte) bool 28 29 type AbbreviatedKey func(key []byte) uint64 30 31 type FormatKey func(key []byte) fmt.Formatter 32 33 type FormatValue func(key, value []byte) fmt.Formatter 34 35 type Separator func(dst, a, b []byte) []byte 36 37 type Successor func(dst, a []byte) []byte 38 39 type Split func(a []byte) int 40 41 type Comparer struct { 42 Compare Compare 43 Equal Equal 44 AbbreviatedKey AbbreviatedKey 45 FormatKey FormatKey 46 FormatValue FormatValue 47 Separator Separator 48 Split Split 49 Successor Successor 50 Name string 51 } 52 53 var DefaultFormatter = func(key []byte) fmt.Formatter { 54 return FormatBytes(key) 55 } 56 57 var DefaultComparer = &Comparer{ 58 Compare: bytes.Compare, 59 Equal: bytes.Equal, 60 61 AbbreviatedKey: func(key []byte) uint64 { 62 if len(key) >= 8 { 63 return binary.BigEndian.Uint64(key) 64 } 65 var v uint64 66 for _, b := range key { 67 v <<= 8 68 v |= uint64(b) 69 } 70 return v << uint(8*(8-len(key))) 71 }, 72 73 FormatKey: DefaultFormatter, 74 75 Separator: func(dst, a, b []byte) []byte { 76 i, n := SharedPrefixLen(a, b), len(dst) 77 dst = append(dst, a...) 78 79 min := len(a) 80 if min > len(b) { 81 min = len(b) 82 } 83 if i >= min { 84 return dst 85 } 86 87 if a[i] >= b[i] { 88 return dst 89 } 90 91 if i < len(b)-1 || a[i]+1 < b[i] { 92 i += n 93 dst[i]++ 94 return dst[:i+1] 95 } 96 97 i += n + 1 98 for ; i < len(dst); i++ { 99 if dst[i] != 0xff { 100 dst[i]++ 101 return dst[:i+1] 102 } 103 } 104 return dst 105 }, 106 107 Successor: func(dst, a []byte) (ret []byte) { 108 for i := 0; i < len(a); i++ { 109 if a[i] != 0xff { 110 dst = append(dst, a[:i+1]...) 111 dst[len(dst)-1]++ 112 return dst 113 } 114 } 115 return append(dst, a...) 116 }, 117 118 Name: "bitalosdb.BytewiseComparator", 119 } 120 121 func SharedPrefixLen(a, b []byte) int { 122 i, n := 0, len(a) 123 if n > len(b) { 124 n = len(b) 125 } 126 asUint64 := func(c []byte, i int) uint64 { 127 return binary.LittleEndian.Uint64(c[i:]) 128 } 129 for i < n-7 && asUint64(a, i) == asUint64(b, i) { 130 i += 8 131 } 132 for i < n && a[i] == b[i] { 133 i++ 134 } 135 return i 136 } 137 138 type FormatBytes []byte 139 140 const lowerhex = "0123456789abcdef" 141 142 func (p FormatBytes) Format(s fmt.State, c rune) { 143 buf := make([]byte, 0, len(p)) 144 for _, b := range p { 145 if b < utf8.RuneSelf && strconv.IsPrint(rune(b)) { 146 buf = append(buf, b) 147 continue 148 } 149 buf = append(buf, `\x`...) 150 buf = append(buf, lowerhex[b>>4]) 151 buf = append(buf, lowerhex[b&0xF]) 152 } 153 s.Write(buf) 154 }