]> Cypherpunks repositories - gostls13.git/commitdiff
exp/locale/collate: added functionality for sorting.
authorMarcel van Lohuizen <mpvl@golang.org>
Wed, 23 Jan 2013 13:16:22 +0000 (14:16 +0100)
committerMarcel van Lohuizen <mpvl@golang.org>
Wed, 23 Jan 2013 13:16:22 +0000 (14:16 +0100)
Eliminates the need for the user to fiddle with keys.

R=rsc
CC=golang-dev
https://golang.org/cl/7060051

src/pkg/exp/locale/collate/sort.go [new file with mode: 0644]
src/pkg/exp/locale/collate/sort_test.go [new file with mode: 0644]

diff --git a/src/pkg/exp/locale/collate/sort.go b/src/pkg/exp/locale/collate/sort.go
new file mode 100644 (file)
index 0000000..57b2efd
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate
+
+import (
+       "bytes"
+       "sort"
+)
+
+const (
+       maxSortBuffer  = 40960
+       maxSortEntries = 4096
+)
+
+type swapper interface {
+       Swap(i, j int)
+}
+
+type sorter struct {
+       buf  *Buffer
+       keys [][]byte
+       src  swapper
+}
+
+func (s *sorter) init(n int) {
+       if s.buf == nil {
+               s.buf = &Buffer{}
+               s.buf.init()
+       }
+       if cap(s.keys) < n {
+               s.keys = make([][]byte, n)
+       }
+       s.keys = s.keys[0:n]
+}
+
+func (s *sorter) clean() {
+       if len(s.buf.key) > maxSortBuffer {
+               s.buf.key = s.buf.buf[:0]
+       }
+       if len(s.keys) > maxSortEntries {
+               s.keys = nil
+       }
+}
+
+func (s *sorter) sort(src swapper) {
+       s.src = src
+       sort.Sort(s)
+}
+
+func (s sorter) Len() int {
+       return len(s.keys)
+}
+
+func (s sorter) Less(i, j int) bool {
+       return bytes.Compare(s.keys[i], s.keys[j]) == -1
+}
+
+func (s sorter) Swap(i, j int) {
+       s.keys[i], s.keys[j] = s.keys[j], s.keys[i]
+       s.src.Swap(i, j)
+}
+
+// A Lister can be sorted by Collator's Sort method.
+type Lister interface {
+       Len() int
+       Swap(i, j int)
+       // Bytes returns the bytes of the text at index i.
+       Bytes(i int) []byte
+}
+
+// Sort uses sort.Sort to sort the strings represented by x using the rules of c.
+func (c *Collator) Sort(x Lister) {
+       n := x.Len()
+       c.sorter.init(n)
+       for i := 0; i < n; i++ {
+               c.sorter.keys[i] = c.Key(c.sorter.buf, x.Bytes(i))
+       }
+       c.sorter.sort(x)
+}
+
+// Strings sorts x using the rules of c.
+func (c *Collator) Strings(x []string) {
+       c.sorter.init(len(x))
+       for i, s := range x {
+               c.sorter.keys[i] = c.KeyFromString(c.sorter.buf, s)
+       }
+       c.sorter.sort(sort.StringSlice(x))
+}
diff --git a/src/pkg/exp/locale/collate/sort_test.go b/src/pkg/exp/locale/collate/sort_test.go
new file mode 100644 (file)
index 0000000..d0682f4
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package collate_test
+
+import (
+       "exp/locale/collate"
+       "fmt"
+       "testing"
+)
+
+func ExampleCollator_Strings() {
+       c := collate.New("root")
+       strings := []string{
+               "ad",
+               "äb",
+               "ac",
+       }
+       c.Strings(strings)
+       fmt.Println(strings)
+       // Output: [äb ac ad]
+}
+
+type sorter []string
+
+func (s sorter) Len() int {
+       return len(s)
+}
+
+func (s sorter) Swap(i, j int) {
+       s[j], s[i] = s[i], s[j]
+}
+
+func (s sorter) Bytes(i int) []byte {
+       return []byte(s[i])
+}
+
+func TestSort(t *testing.T) {
+       c := collate.New("en")
+       strings := []string{
+               "bcd",
+               "abc",
+               "ddd",
+       }
+       c.Sort(sorter(strings))
+       res := fmt.Sprint(strings)
+       want := "[abc bcd ddd]"
+       if res != want {
+               t.Errorf("found %s; want %s", res, want)
+       }
+}