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  }