rangetable.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright 2015 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 rangetable provides utilities for creating and inspecting
  5. // unicode.RangeTables.
  6. package rangetable
  7. import (
  8. "sort"
  9. "unicode"
  10. )
  11. // New creates a RangeTable from the given runes, which may contain duplicates.
  12. func New(r ...rune) *unicode.RangeTable {
  13. if len(r) == 0 {
  14. return &unicode.RangeTable{}
  15. }
  16. sort.Sort(byRune(r))
  17. // Remove duplicates.
  18. k := 1
  19. for i := 1; i < len(r); i++ {
  20. if r[k-1] != r[i] {
  21. r[k] = r[i]
  22. k++
  23. }
  24. }
  25. var rt unicode.RangeTable
  26. for _, r := range r[:k] {
  27. if r <= 0xFFFF {
  28. rt.R16 = append(rt.R16, unicode.Range16{Lo: uint16(r), Hi: uint16(r), Stride: 1})
  29. } else {
  30. rt.R32 = append(rt.R32, unicode.Range32{Lo: uint32(r), Hi: uint32(r), Stride: 1})
  31. }
  32. }
  33. // Optimize RangeTable.
  34. return Merge(&rt)
  35. }
  36. type byRune []rune
  37. func (r byRune) Len() int { return len(r) }
  38. func (r byRune) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
  39. func (r byRune) Less(i, j int) bool { return r[i] < r[j] }
  40. // Visit visits all runes in the given RangeTable in order, calling fn for each.
  41. func Visit(rt *unicode.RangeTable, fn func(rune)) {
  42. for _, r16 := range rt.R16 {
  43. for r := rune(r16.Lo); r <= rune(r16.Hi); r += rune(r16.Stride) {
  44. fn(r)
  45. }
  46. }
  47. for _, r32 := range rt.R32 {
  48. for r := rune(r32.Lo); r <= rune(r32.Hi); r += rune(r32.Stride) {
  49. fn(r)
  50. }
  51. }
  52. }
  53. // Assigned returns a RangeTable with all assigned code points for a given
  54. // Unicode version. This includes graphic, format, control, and private-use
  55. // characters. It returns nil if the data for the given version is not
  56. // available.
  57. func Assigned(version string) *unicode.RangeTable {
  58. return assigned[version]
  59. }