example_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2014 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 triegen_test
  5. import (
  6. "fmt"
  7. "io/ioutil"
  8. "math/rand"
  9. "unicode"
  10. "golang.org/x/text/internal/triegen"
  11. )
  12. const seed = 0x12345
  13. var genWriter = ioutil.Discard
  14. func randomRunes() map[rune]uint8 {
  15. rnd := rand.New(rand.NewSource(seed))
  16. m := map[rune]uint8{}
  17. for len(m) < 100 {
  18. // Only set our random rune if it is a valid Unicode code point.
  19. if r := rune(rnd.Int31n(unicode.MaxRune + 1)); []rune(string(r))[0] == r {
  20. m[r] = 1
  21. }
  22. }
  23. return m
  24. }
  25. // Example_build shows how to build a simple trie. It assigns the value 1 to
  26. // 100 random runes generated by randomRunes.
  27. func Example_build() {
  28. t := triegen.NewTrie("rand")
  29. for r, _ := range randomRunes() {
  30. t.Insert(r, 1)
  31. }
  32. sz, err := t.Gen(genWriter)
  33. fmt.Printf("Trie size: %d bytes\n", sz)
  34. fmt.Printf("Error: %v\n", err)
  35. // Output:
  36. // Trie size: 9280 bytes
  37. // Error: <nil>
  38. }
  39. // Example_lookup demonstrates how to use the trie generated by Example_build.
  40. func Example_lookup() {
  41. trie := newRandTrie(0)
  42. // The same set of runes used by Example_build.
  43. runes := randomRunes()
  44. // Verify the right value is returned for all runes.
  45. for r := rune(0); r <= unicode.MaxRune; r++ {
  46. // Note that the return type of lookup is uint8.
  47. if v, _ := trie.lookupString(string(r)); v != runes[r] {
  48. fmt.Println("FAILURE")
  49. return
  50. }
  51. }
  52. fmt.Println("SUCCESS")
  53. // Output:
  54. // SUCCESS
  55. }
  56. // runeValues generates some random values for a set of interesting runes.
  57. func runeValues() map[rune]uint64 {
  58. rnd := rand.New(rand.NewSource(seed))
  59. m := map[rune]uint64{}
  60. for p := 4; p <= unicode.MaxRune; p <<= 1 {
  61. for d := -1; d <= 1; d++ {
  62. m[rune(p+d)] = uint64(rnd.Int63())
  63. }
  64. }
  65. return m
  66. }
  67. // ExampleGen_build demonstrates the creation of multiple tries sharing common
  68. // blocks. ExampleGen_lookup demonstrates how to use the generated tries.
  69. func ExampleGen_build() {
  70. var tries []*triegen.Trie
  71. rv := runeValues()
  72. for _, c := range []struct {
  73. include func(rune) bool
  74. name string
  75. }{
  76. {func(r rune) bool { return true }, "all"},
  77. {func(r rune) bool { return r < 0x80 }, "ASCII only"},
  78. {func(r rune) bool { return r < 0x80 }, "ASCII only 2"},
  79. {func(r rune) bool { return r <= 0xFFFF }, "BMP only"},
  80. {func(r rune) bool { return r > 0xFFFF }, "No BMP"},
  81. } {
  82. t := triegen.NewTrie(c.name)
  83. tries = append(tries, t)
  84. for r, v := range rv {
  85. if c.include(r) {
  86. t.Insert(r, v)
  87. }
  88. }
  89. }
  90. sz, err := triegen.Gen(genWriter, "multi", tries)
  91. fmt.Printf("Trie size: %d bytes\n", sz)
  92. fmt.Printf("Error: %v\n", err)
  93. // Output:
  94. // Trie size: 18250 bytes
  95. // Error: <nil>
  96. }
  97. // ExampleGen_lookup shows how to look up values in the trie generated by
  98. // ExampleGen_build.
  99. func ExampleGen_lookup() {
  100. rv := runeValues()
  101. for i, include := range []func(rune) bool{
  102. func(r rune) bool { return true }, // all
  103. func(r rune) bool { return r < 0x80 }, // ASCII only
  104. func(r rune) bool { return r < 0x80 }, // ASCII only 2
  105. func(r rune) bool { return r <= 0xFFFF }, // BMP only
  106. func(r rune) bool { return r > 0xFFFF }, // No BMP
  107. } {
  108. t := newMultiTrie(i)
  109. for r := rune(0); r <= unicode.MaxRune; r++ {
  110. x := uint64(0)
  111. if include(r) {
  112. x = rv[r]
  113. }
  114. // As we convert from a valid rune, we know it is safe to use
  115. // lookupStringUnsafe.
  116. if v := t.lookupStringUnsafe(string(r)); x != v {
  117. fmt.Println("FAILURE")
  118. return
  119. }
  120. }
  121. }
  122. fmt.Println("SUCCESS")
  123. // Output:
  124. // SUCCESS
  125. }