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.
9 // For a description of ContractTrieSet, see text/collate/build/contract.go.
11 type ContractTrieSet []struct{ L, H, N, I uint8 }
13 // ctScanner is used to match a trie to an input sequence.
14 // A contraction may match a non-contiguous sequence of bytes in an input string.
15 // For example, if there is a contraction for <a, combining_ring>, it should match
16 // the sequence <a, combining_cedilla, combining_ring>, as combining_cedilla does
17 // not block combining_ring.
18 // ctScanner does not automatically skip over non-blocking non-starters, but rather
19 // retains the state of the last match and leaves it up to the user to continue
20 // the match at the appropriate points.
21 type ctScanner struct {
22 states ContractTrieSet
30 type ctScannerString struct {
31 states ContractTrieSet
39 func (t ContractTrieSet) scanner(index, n int, b []byte) ctScanner {
40 return ctScanner{s: b, states: t[index:], n: n}
43 func (t ContractTrieSet) scannerString(index, n int, str string) ctScannerString {
44 return ctScannerString{s: str, states: t[index:], n: n}
47 // result returns the offset i and bytes consumed p so far. If no suffix
48 // matched, i and p will be 0.
49 func (s *ctScanner) result() (i, p int) {
50 return s.index, s.pindex
53 func (s *ctScannerString) result() (i, p int) {
54 return s.index, s.pindex
62 // scan matches the longest suffix at the current location in the input
63 // and returns the number of bytes consumed.
64 func (s *ctScanner) scan(p int) int {
65 pr := p // the p at the rune start
67 states, n := s.states, s.n
68 for i := 0; i < n && p < len(str); {
71 // TODO: a significant number of contractions are of a form that
72 // cannot match discontiguous UTF-8 in a normalized string. We could let
73 // a negative value of e.n mean that we can set s.done = true and avoid
74 // the need for additional matches.
83 i, states, n = 0, states[int(e.H)+n:], int(e.N)
84 if p >= len(str) || utf8.RuneStart(str[p]) {
85 s.states, s.n, pr = states, n, p
92 } else if e.N == final && c <= e.H {
95 s.index = int(c-e.L) + int(e.I)
105 // scan is a verbatim copy of ctScanner.scan.
106 func (s *ctScannerString) scan(p int) int {
107 pr := p // the p at the rune start
109 states, n := s.states, s.n
110 for i := 0; i < n && p < len(str); {
113 // TODO: a significant number of contractions are of a form that
114 // cannot match discontiguous UTF-8 in a normalized string. We could let
115 // a negative value of e.n mean that we can set s.done = true and avoid
116 // the need for additional matches.
125 i, states, n = 0, states[int(e.H)+n:], int(e.N)
126 if p >= len(str) || utf8.RuneStart(str[p]) {
127 s.states, s.n, pr = states, n, p
134 } else if e.N == final && c <= e.H {
137 s.index = int(c-e.L) + int(e.I)