github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/strconv/makeisprint.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 //go:build ignore 6 7 // 8 // usage: 9 // 10 // go run makeisprint.go -output isprint.go 11 // 12 13 package main 14 15 import ( 16 "bytes" 17 "flag" 18 "fmt" 19 "go/format" 20 "log" 21 "os" 22 "slices" 23 "unicode" 24 ) 25 26 var filename = flag.String("output", "isprint.go", "output file name") 27 28 var ( 29 range16 []uint16 30 except16 []uint16 31 range32 []uint32 32 except32 []uint32 33 ) 34 35 func isPrint(r rune) bool { 36 // Same algorithm, either on uint16 or uint32 value. 37 // First, find first i such that rang[i] >= x. 38 // This is the index of either the start or end of a pair that might span x. 39 // The start is even (rang[i&^1]) and the end is odd (rang[i|1]). 40 // If we find x in a range, make sure x is not in exception list. 41 42 if 0 <= r && r < 1<<16 { 43 rr, rang, except := uint16(r), range16, except16 44 i, _ := slices.BinarySearch(rang, rr) 45 if i >= len(rang) || rr < rang[i&^1] || rang[i|1] < rr { 46 return false 47 } 48 _, found := slices.BinarySearch(except, rr) 49 return !found 50 } 51 52 rr, rang, except := uint32(r), range32, except32 53 i, _ := slices.BinarySearch(rang, rr) 54 if i >= len(rang) || rr < rang[i&^1] || rang[i|1] < rr { 55 return false 56 } 57 _, found := slices.BinarySearch(except, rr) 58 return !found 59 } 60 61 func scan(min, max rune) (rang, except []uint32) { 62 lo := rune(-1) 63 for i := min; ; i++ { 64 if (i > max || !unicode.IsPrint(i)) && lo >= 0 { 65 // End range, but avoid flip flop. 66 if i+1 <= max && unicode.IsPrint(i+1) { 67 except = append(except, uint32(i)) 68 continue 69 } 70 rang = append(rang, uint32(lo), uint32(i-1)) 71 lo = -1 72 } 73 if i > max { 74 break 75 } 76 if lo < 0 && unicode.IsPrint(i) { 77 lo = i 78 } 79 } 80 return 81 } 82 83 func to16(x []uint32) []uint16 { 84 var y []uint16 85 for _, v := range x { 86 if uint32(uint16(v)) != v { 87 panic("bad 32->16 conversion") 88 } 89 y = append(y, uint16(v)) 90 } 91 return y 92 } 93 94 func main() { 95 flag.Parse() 96 97 rang, except := scan(0, 0xFFFF) 98 range16 = to16(rang) 99 except16 = to16(except) 100 range32, except32 = scan(0x10000, unicode.MaxRune) 101 102 for i := rune(0); i <= unicode.MaxRune; i++ { 103 if isPrint(i) != unicode.IsPrint(i) { 104 log.Fatalf("%U: isPrint=%v, want %v\n", i, isPrint(i), unicode.IsPrint(i)) 105 } 106 } 107 108 var buf bytes.Buffer 109 110 fmt.Fprintf(&buf, `// Copyright 2013 The Go Authors. All rights reserved. 111 // Use of this source code is governed by a BSD-style 112 // license that can be found in the LICENSE file.`+"\n\n") 113 fmt.Fprintf(&buf, "// Code generated by go run makeisprint.go -output isprint.go; DO NOT EDIT.\n\n") 114 fmt.Fprintf(&buf, "package strconv\n\n") 115 116 fmt.Fprintf(&buf, "// (%d+%d+%d)*2 + (%d)*4 = %d bytes\n\n", 117 len(range16), len(except16), len(except32), 118 len(range32), 119 (len(range16)+len(except16)+len(except32))*2+ 120 (len(range32))*4) 121 122 fmt.Fprintf(&buf, "var isPrint16 = []uint16{\n") 123 for i := 0; i < len(range16); i += 2 { 124 fmt.Fprintf(&buf, "\t%#04x, %#04x,\n", range16[i], range16[i+1]) 125 } 126 fmt.Fprintf(&buf, "}\n\n") 127 128 fmt.Fprintf(&buf, "var isNotPrint16 = []uint16{\n") 129 for _, r := range except16 { 130 fmt.Fprintf(&buf, "\t%#04x,\n", r) 131 } 132 fmt.Fprintf(&buf, "}\n\n") 133 134 fmt.Fprintf(&buf, "var isPrint32 = []uint32{\n") 135 for i := 0; i < len(range32); i += 2 { 136 fmt.Fprintf(&buf, "\t%#06x, %#06x,\n", range32[i], range32[i+1]) 137 } 138 fmt.Fprintf(&buf, "}\n\n") 139 140 fmt.Fprintf(&buf, "var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n") 141 for _, r := range except32 { 142 if r >= 0x20000 { 143 log.Fatalf("%U too big for isNotPrint32\n", r) 144 } 145 fmt.Fprintf(&buf, "\t%#04x,\n", r-0x10000) 146 } 147 fmt.Fprintf(&buf, "}\n\n") 148 149 // The list of graphic but not "printable" runes is short. Just make one easy table. 150 fmt.Fprintf(&buf, "// isGraphic lists the graphic runes not matched by IsPrint.\n") 151 fmt.Fprintf(&buf, "var isGraphic = []uint16{\n") 152 for r := rune(0); r <= unicode.MaxRune; r++ { 153 if unicode.IsPrint(r) != unicode.IsGraphic(r) { 154 // Sanity check. 155 if !unicode.IsGraphic(r) { 156 log.Fatalf("%U is printable but not graphic\n", r) 157 } 158 if r > 0xFFFF { // We expect only 16-bit values. 159 log.Fatalf("%U too big for isGraphic\n", r) 160 } 161 fmt.Fprintf(&buf, "\t%#04x,\n", r) 162 } 163 } 164 fmt.Fprintf(&buf, "}\n") 165 166 data, err := format.Source(buf.Bytes()) 167 if err != nil { 168 log.Fatal(err) 169 } 170 err = os.WriteFile(*filename, data, 0644) 171 if err != nil { 172 log.Fatal(err) 173 } 174 }