golang.org/x/text@v0.14.0/unicode/norm/example_iter_test.go (about) 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 5 package norm_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "unicode/utf8" 12 13 "golang.org/x/text/unicode/norm" 14 ) 15 16 // EqualSimple uses a norm.Iter to compare two non-normalized 17 // strings for equivalence. 18 func EqualSimple(a, b string) bool { 19 var ia, ib norm.Iter 20 ia.InitString(norm.NFKD, a) 21 ib.InitString(norm.NFKD, b) 22 for !ia.Done() && !ib.Done() { 23 if !bytes.Equal(ia.Next(), ib.Next()) { 24 return false 25 } 26 } 27 return ia.Done() && ib.Done() 28 } 29 30 // FindPrefix finds the longest common prefix of ASCII characters 31 // of a and b. 32 func FindPrefix(a, b string) int { 33 i := 0 34 for ; i < len(a) && i < len(b) && a[i] < utf8.RuneSelf && a[i] == b[i]; i++ { 35 } 36 return i 37 } 38 39 // EqualOpt is like EqualSimple, but optimizes the special 40 // case for ASCII characters. 41 func EqualOpt(a, b string) bool { 42 n := FindPrefix(a, b) 43 a, b = a[n:], b[n:] 44 var ia, ib norm.Iter 45 ia.InitString(norm.NFKD, a) 46 ib.InitString(norm.NFKD, b) 47 for !ia.Done() && !ib.Done() { 48 if !bytes.Equal(ia.Next(), ib.Next()) { 49 return false 50 } 51 if n := int64(FindPrefix(a[ia.Pos():], b[ib.Pos():])); n != 0 { 52 ia.Seek(n, io.SeekCurrent) 53 ib.Seek(n, io.SeekCurrent) 54 } 55 } 56 return ia.Done() && ib.Done() 57 } 58 59 var compareTests = []struct{ a, b string }{ 60 {"aaa", "aaa"}, 61 {"aaa", "aab"}, 62 {"a\u0300a", "\u00E0a"}, 63 {"a\u0300\u0320b", "a\u0320\u0300b"}, 64 {"\u1E0A\u0323", "\x44\u0323\u0307"}, 65 // A character that decomposes into multiple segments 66 // spans several iterations. 67 {"\u3304", "\u30A4\u30CB\u30F3\u30AF\u3099"}, 68 } 69 70 func ExampleIter() { 71 for i, t := range compareTests { 72 r0 := EqualSimple(t.a, t.b) 73 r1 := EqualOpt(t.a, t.b) 74 fmt.Printf("%d: %v %v\n", i, r0, r1) 75 } 76 // Output: 77 // 0: true true 78 // 1: false false 79 // 2: true true 80 // 3: true true 81 // 4: true true 82 // 5: true true 83 }