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.
7 // makeisprint generates the tables for strconv's compact isPrint.
23 // bsearch16 returns the smallest i such that a[i] >= x.
24 // If there is no such i, bsearch16 returns len(a).
25 func bsearch16(a
[]uint16, x
uint16) int {
38 // bsearch32 returns the smallest i such that a[i] >= x.
39 // If there is no such i, bsearch32 returns len(a).
40 func bsearch32(a
[]uint32, x
uint32) int {
53 func isPrint(r rune
) bool {
54 // Same algorithm, either on uint16 or uint32 value.
55 // First, find first i such that rang[i] >= x.
56 // This is the index of either the start or end of a pair that might span x.
57 // The start is even (rang[i&^1]) and the end is odd (rang[i|1]).
58 // If we find x in a range, make sure x is not in exception list.
60 if 0 <= r
&& r
< 1<<16 {
61 rr
, rang
, except
:= uint16(r
), range16
, except16
62 i
:= bsearch16(rang
, rr
)
63 if i
>= len(rang
) || rr
< rang
[i
&^1] || rang
[i|
1] < rr
{
66 j
:= bsearch16(except
, rr
)
67 return j
>= len(except
) || except
[j
] != rr
70 rr
, rang
, except
:= uint32(r
), range32
, except32
71 i
:= bsearch32(rang
, rr
)
72 if i
>= len(rang
) || rr
< rang
[i
&^1] || rang
[i|
1] < rr
{
75 j
:= bsearch32(except
, rr
)
76 return j
>= len(except
) || except
[j
] != rr
79 func scan(min
, max rune
) (rang
, except
[]uint32) {
82 if (i
> max ||
!unicode
.IsPrint(i
)) && lo
>= 0 {
83 // End range, but avoid flip flop.
84 if i
+1 <= max
&& unicode
.IsPrint(i
+1) {
85 except
= append(except
, uint32(i
))
88 rang
= append(rang
, uint32(lo
), uint32(i
-1))
94 if lo
< 0 && unicode
.IsPrint(i
) {
101 func to16(x
[]uint32) []uint16 {
103 for _
, v
:= range x
{
104 if uint32(uint16(v
)) != v
{
105 panic("bad 32->16 conversion")
107 y
= append(y
, uint16(v
))
113 rang
, except
:= scan(0, 0xFFFF)
115 except16
= to16(except
)
116 range32
, except32
= scan(0x10000, unicode
.MaxRune
)
118 for i
:= rune(0); i
<= unicode
.MaxRune
; i
++ {
119 if isPrint(i
) != unicode
.IsPrint(i
) {
120 fmt
.Fprintf(os
.Stderr
, "%U: isPrint=%v, want %v\n", i
, isPrint(i
), unicode
.IsPrint(i
))
125 fmt
.Printf(`// Copyright 2013 The Go Authors. All rights reserved.
126 // Use of this source code is governed by a BSD-style
127 // license that can be found in the LICENSE file.` + "\n\n")
128 fmt
.Printf("// DO NOT EDIT. GENERATED BY\n")
129 fmt
.Printf("// go run makeisprint.go >x && mv x isprint.go\n\n")
130 fmt
.Printf("package strconv\n\n")
132 fmt
.Printf("// (%d+%d+%d)*2 + (%d)*4 = %d bytes\n\n",
133 len(range16
), len(except16
), len(except32
),
135 (len(range16
)+len(except16
)+len(except32
))*2+
138 fmt
.Printf("var isPrint16 = []uint16{\n")
139 for i
:= 0; i
< len(range16
); i
+= 2 {
140 fmt
.Printf("\t%#04x, %#04x,\n", range16
[i
], range16
[i
+1])
144 fmt
.Printf("var isNotPrint16 = []uint16{\n")
145 for _
, r
:= range except16
{
146 fmt
.Printf("\t%#04x,\n", r
)
150 fmt
.Printf("var isPrint32 = []uint32{\n")
151 for i
:= 0; i
< len(range32
); i
+= 2 {
152 fmt
.Printf("\t%#06x, %#06x,\n", range32
[i
], range32
[i
+1])
156 fmt
.Printf("var isNotPrint32 = []uint16{ // add 0x10000 to each entry\n")
157 for _
, r
:= range except32
{
159 fmt
.Fprintf(os
.Stderr
, "%U too big for isNotPrint32\n", r
)
162 fmt
.Printf("\t%#04x,\n", r
-0x10000)