| // Copyright 2012 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 main |
| |
| import ( |
| "log" |
| "unicode/utf16" |
| |
| "golang.org/x/text/collate" |
| "golang.org/x/text/language" |
| ) |
| |
| // Input holds an input string in both UTF-8 and UTF-16 format. |
| type Input struct { |
| index int // used for restoring to original random order |
| UTF8 []byte |
| UTF16 []uint16 |
| key []byte // used for sorting |
| } |
| |
| func (i Input) String() string { |
| return string(i.UTF8) |
| } |
| |
| func makeInput(s8 []byte, s16 []uint16) Input { |
| return Input{UTF8: s8, UTF16: s16} |
| } |
| |
| func makeInputString(s string) Input { |
| return Input{ |
| UTF8: []byte(s), |
| UTF16: utf16.Encode([]rune(s)), |
| } |
| } |
| |
| // Collator is an interface for architecture-specific implementations of collation. |
| type Collator interface { |
| // Key generates a sort key for the given input. Implemenations |
| // may return nil if a collator does not support sort keys. |
| Key(s Input) []byte |
| |
| // Compare returns -1 if a < b, 1 if a > b and 0 if a == b. |
| Compare(a, b Input) int |
| } |
| |
| // CollatorFactory creates a Collator for a given language tag. |
| type CollatorFactory struct { |
| name string |
| makeFn func(tag string) (Collator, error) |
| description string |
| } |
| |
| var collators = []CollatorFactory{} |
| |
| // AddFactory registers f as a factory for an implementation of Collator. |
| func AddFactory(f CollatorFactory) { |
| collators = append(collators, f) |
| } |
| |
| func getCollator(name, locale string) Collator { |
| for _, f := range collators { |
| if f.name == name { |
| col, err := f.makeFn(locale) |
| if err != nil { |
| log.Fatal(err) |
| } |
| return col |
| } |
| } |
| log.Fatalf("collator of type %q not found", name) |
| return nil |
| } |
| |
| // goCollator is an implemention of Collator using go's own collator. |
| type goCollator struct { |
| c *collate.Collator |
| buf collate.Buffer |
| } |
| |
| func init() { |
| AddFactory(CollatorFactory{"go", newGoCollator, "Go's native collator implementation."}) |
| } |
| |
| func newGoCollator(loc string) (Collator, error) { |
| c := &goCollator{c: collate.New(language.Make(loc))} |
| return c, nil |
| } |
| |
| func (c *goCollator) Key(b Input) []byte { |
| return c.c.Key(&c.buf, b.UTF8) |
| } |
| |
| func (c *goCollator) Compare(a, b Input) int { |
| return c.c.Compare(a.UTF8, b.UTF8) |
| } |