github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/code.google.com/p/leveldb-go/leveldb/db/comparer.go (about) 1 // Copyright 2011 The LevelDB-Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package db 6 7 import ( 8 "bytes" 9 ) 10 11 // Comparer defines a total ordering over the space of []byte keys: a 'less 12 // than' relationship. 13 type Comparer interface { 14 // Compare returns -1, 0, or +1 depending on whether a is 'less than', 15 // 'equal to' or 'greater than' b. The two arguments can only be 'equal' 16 // if their contents are exactly equal. Furthermore, the empty slice 17 // must be 'less than' any non-empty slice. 18 Compare(a, b []byte) int 19 20 // AppendSeparator appends a sequence of bytes x to dst such that 21 // a <= x && x < b, where 'less than' is consistent with Compare. 22 // It returns the enlarged slice, like the built-in append function. 23 // 24 // Precondition: either a is 'less than' b, or b is an empty slice. 25 // In the latter case, empty means 'positive infinity', and appending any 26 // x such that a <= x will be valid. 27 // 28 // An implementation may simply be "return append(dst, a...)" but appending 29 // fewer bytes will result in smaller tables. 30 // 31 // For example, if dst, a and b are the []byte equivalents of the strings 32 // "aqua", "black" and "blue", then the result may be "aquablb". 33 // Similarly, if the arguments were "aqua", "green" and "", then the result 34 // may be "aquah". 35 AppendSeparator(dst, a, b []byte) []byte 36 } 37 38 // DefaultComparer is the default implementation of the Comparer interface. 39 // It uses the natural ordering, consistent with bytes.Compare. 40 var DefaultComparer Comparer = defCmp{} 41 42 type defCmp struct{} 43 44 func (defCmp) Compare(a, b []byte) int { 45 return bytes.Compare(a, b) 46 } 47 48 func (defCmp) AppendSeparator(dst, a, b []byte) []byte { 49 i, n := SharedPrefixLen(a, b), len(dst) 50 dst = append(dst, a...) 51 if len(b) > 0 { 52 if i == len(a) { 53 return dst 54 } 55 if i == len(b) { 56 panic("a < b is a precondition, but b is a prefix of a") 57 } 58 if a[i] == 0xff || a[i]+1 >= b[i] { 59 // This isn't optimal, but it matches the C++ Level-DB implementation, and 60 // it's good enough. For example, if a is "1357" and b is "2", then the 61 // optimal (i.e. shortest) result is appending "14", but we append "1357". 62 return dst 63 } 64 } 65 i += n 66 for ; i < len(dst); i++ { 67 if dst[i] != 0xff { 68 dst[i]++ 69 return dst[:i+1] 70 } 71 } 72 return dst 73 } 74 75 // SharedPrefixLen returns the largest i such that a[:i] equals b[:i]. 76 // This function can be useful in implementing the Comparer interface. 77 func SharedPrefixLen(a, b []byte) int { 78 i, n := 0, len(a) 79 if n > len(b) { 80 n = len(b) 81 } 82 for i < n && a[i] == b[i] { 83 i++ 84 } 85 return i 86 }