| // 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 implementation 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) | |
| } |