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.
10 // go run makeisprint.go -output isprint.go
25 var filename
= flag
.String("output", "isprint.go", "output file name")
34 // bsearch16 returns the smallest i such that a[i] >= x.
35 // If there is no such i, bsearch16 returns len(a).
36 func bsearch16(a
[]uint16, x
uint16) int {
49 // bsearch32 returns the smallest i such that a[i] >= x.
50 // If there is no such i, bsearch32 returns len(a).
51 func bsearch32(a
[]uint32, x
uint32) int {
64 func isPrint(r rune
) bool {
65 // Same algorithm, either on uint16 or uint32 value.
66 // First, find first i such that rang[i] >= x.
67 // This is the index of either the start or end of a pair that might span x.
68 // The start is even (rang[i&^1]) and the end is odd (rang[i|1]).
69 // If we find x in a range, make sure x is not in exception list.
71 if 0 <= r
&& r
< 1<<16 {
72 rr
, rang
, except
:= uint16(r
), range16
, except16
73 i
:= bsearch16(rang
, rr
)
74 if i
>= len(rang
) || rr
< rang
[i
&^1] || rang
[i|
1] < rr
{
77 j
:= bsearch16(except
, rr
)
78 return j
>= len(except
) || except
[j
] != rr
81 rr
, rang
, except
:= uint32(r
), range32
, except32
82 i
:= bsearch32(rang
, rr
)
83 if i
>= len(rang
) || rr
< rang
[i
&^1] || rang
[i|
1] < rr
{
86 j
:= bsearch32(except
, rr
)
87 return j
>= len(except
) || except
[j
] != rr
90 func scan(min
, max rune
) (rang
, except
[]uint32) {
93 if (i
> max ||
!unicode
.IsPrint(i
)) && lo
>= 0 {
94 // End range, but avoid flip flop.
95 if i
+1 <= max
&& unicode
.IsPrint(i
+1) {
96 except
= append(except
, uint32(i
))
99 rang
= append(rang
, uint32(lo
), uint32(i
-1))
105 if lo
< 0 && unicode
.IsPrint(i
) {
112 func to16(x
[]uint32) []uint16 {
114 for _
, v
:= range x
{
115 if uint32(uint16(v
)) != v
{
116 panic("bad 32->16 conversion")
118 y
= append(y
, uint16(v
))
126 rang
, except
:= scan(0, 0xFFFF)
128 except16
= to16(except
)
129 range32
, except32
= scan(0x10000, unicode
.MaxRune
)
131 for i
:= rune(0); i
<= unicode
.MaxRune
; i
++ {
132 if isPrint(i
) != unicode
.IsPrint(i
) {
133 log
.Fatalf("%U: isPrint=%v, want %v\n", i
, isPrint(i
), unicode
.IsPrint(i
))
139 fmt
.Fprintf(&buf
, `// Copyright 2013 The Go Authors. All rights reserved.
140 // Use of this source code is governed by a BSD-style
141 // license that can be found in the LICENSE file.`+"\n\n")
142 fmt
.Fprintf(&buf
, "// DO NOT EDIT. GENERATED BY\n")
143 fmt
.Fprintf(&buf
, "// go run makeisprint.go -output isprint.go\n\n")
144 fmt
.Fprintf(&buf
, "package strconv\n\n")
146 fmt
.Fprintf(&buf
, "// (%d+%d+%d)*2 + (%d)*4 = %d bytes\n\n",
147 len(range16
), len(except16
), len(except32
),
149 (len(range16
)+len(except16
)+len(except32
))*2+
152 fmt
.Fprintf(&buf
, "var isPrint16 = []uint16{\n")
153 for i
:= 0; i
< len(range16
); i
+= 2 {
154 fmt
.Fprintf(&buf
, "\t%#04x, %#04x,\n", range16
[i
], range16
[i
+1])
156 fmt
.Fprintf(&buf
, "}\n\n")
158 fmt
.Fprintf(&buf
, "var isNotPrint16 = []uint16{\n")
159 for _
, r
:= range except16
{
160 fmt
.Fprintf(&buf
, "\t%#04x,\n", r
)
162 fmt
.Fprintf(&buf
, "}\n\n")
164 fmt
.Fprintf(&buf
, "var isPrint32 = []uint32{\n")
165 for i
:= 0; i
< len(range32
); i
+= 2 {
166 fmt
.Fprintf(&buf
, "\t%#06x, %#06x,\n", range32
[i
], range32
[i
+1])
168 fmt
.Fprintf(&buf
, "}\n\n")
170 fmt
.Fprintf(&buf
, "var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n")
171 for _
, r
:= range except32
{
173 log
.Fatalf("%U too big for isNotPrint32\n", r
)
175 fmt
.Fprintf(&buf
, "\t%#04x,\n", r
-0x10000)
177 fmt
.Fprintf(&buf
, "}\n")
179 data
, err
:= format
.Source(buf
.Bytes())
183 err
= ioutil
.WriteFile(*filename
, data
, 0644)