trie.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright 2016 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 idna
  5. // appendMapping appends the mapping for the respective rune. isMapped must be
  6. // true. A mapping is a categorization of a rune as defined in UTS #46.
  7. func (c info) appendMapping(b []byte, s string) []byte {
  8. index := int(c >> indexShift)
  9. if c&xorBit == 0 {
  10. s := mappings[index:]
  11. return append(b, s[1:s[0]+1]...)
  12. }
  13. b = append(b, s...)
  14. if c&inlineXOR == inlineXOR {
  15. // TODO: support and handle two-byte inline masks
  16. b[len(b)-1] ^= byte(index)
  17. } else {
  18. for p := len(b) - int(xorData[index]); p < len(b); p++ {
  19. index++
  20. b[p] ^= xorData[index]
  21. }
  22. }
  23. return b
  24. }
  25. // Sparse block handling code.
  26. type valueRange struct {
  27. value uint16 // header: value:stride
  28. lo, hi byte // header: lo:n
  29. }
  30. type sparseBlocks struct {
  31. values []valueRange
  32. offset []uint16
  33. }
  34. var idnaSparse = sparseBlocks{
  35. values: idnaSparseValues[:],
  36. offset: idnaSparseOffset[:],
  37. }
  38. // Don't use newIdnaTrie to avoid unconditional linking in of the table.
  39. var trie = &idnaTrie{}
  40. // lookup determines the type of block n and looks up the value for b.
  41. // For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
  42. // is a list of ranges with an accompanying value. Given a matching range r,
  43. // the value for b is by r.value + (b - r.lo) * stride.
  44. func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
  45. offset := t.offset[n]
  46. header := t.values[offset]
  47. lo := offset + 1
  48. hi := lo + uint16(header.lo)
  49. for lo < hi {
  50. m := lo + (hi-lo)/2
  51. r := t.values[m]
  52. if r.lo <= b && b <= r.hi {
  53. return r.value + uint16(b-r.lo)*header.value
  54. }
  55. if b < r.lo {
  56. hi = m
  57. } else {
  58. lo = m + 1
  59. }
  60. }
  61. return 0
  62. }