col.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2012 The 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. package main
  5. import (
  6. "log"
  7. "unicode/utf16"
  8. "golang.org/x/text/collate"
  9. "golang.org/x/text/language"
  10. )
  11. // Input holds an input string in both UTF-8 and UTF-16 format.
  12. type Input struct {
  13. index int // used for restoring to original random order
  14. UTF8 []byte
  15. UTF16 []uint16
  16. key []byte // used for sorting
  17. }
  18. func (i Input) String() string {
  19. return string(i.UTF8)
  20. }
  21. func makeInput(s8 []byte, s16 []uint16) Input {
  22. return Input{UTF8: s8, UTF16: s16}
  23. }
  24. func makeInputString(s string) Input {
  25. return Input{
  26. UTF8: []byte(s),
  27. UTF16: utf16.Encode([]rune(s)),
  28. }
  29. }
  30. // Collator is an interface for architecture-specific implementations of collation.
  31. type Collator interface {
  32. // Key generates a sort key for the given input. Implemenations
  33. // may return nil if a collator does not support sort keys.
  34. Key(s Input) []byte
  35. // Compare returns -1 if a < b, 1 if a > b and 0 if a == b.
  36. Compare(a, b Input) int
  37. }
  38. // CollatorFactory creates a Collator for a given language tag.
  39. type CollatorFactory struct {
  40. name string
  41. makeFn func(tag string) (Collator, error)
  42. description string
  43. }
  44. var collators = []CollatorFactory{}
  45. // AddFactory registers f as a factory for an implementation of Collator.
  46. func AddFactory(f CollatorFactory) {
  47. collators = append(collators, f)
  48. }
  49. func getCollator(name, locale string) Collator {
  50. for _, f := range collators {
  51. if f.name == name {
  52. col, err := f.makeFn(locale)
  53. if err != nil {
  54. log.Fatal(err)
  55. }
  56. return col
  57. }
  58. }
  59. log.Fatalf("collator of type %q not found", name)
  60. return nil
  61. }
  62. // goCollator is an implemention of Collator using go's own collator.
  63. type goCollator struct {
  64. c *collate.Collator
  65. buf collate.Buffer
  66. }
  67. func init() {
  68. AddFactory(CollatorFactory{"go", newGoCollator, "Go's native collator implementation."})
  69. }
  70. func newGoCollator(loc string) (Collator, error) {
  71. c := &goCollator{c: collate.New(language.Make(loc))}
  72. return c, nil
  73. }
  74. func (c *goCollator) Key(b Input) []byte {
  75. return c.c.Key(&c.buf, b.UTF8)
  76. }
  77. func (c *goCollator) Compare(a, b Input) int {
  78. return c.c.Compare(a.UTF8, b.UTF8)
  79. }