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