Skip to content

Commit

Permalink
Merge pull request #37 from markus-oberhumer/minor-cleanups
Browse files Browse the repository at this point in the history
Minor cleanups
  • Loading branch information
mattn committed Jan 10, 2020
2 parents 18c3d09 + 4bd49ad commit f9aa72c
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 44 deletions.
1 change: 0 additions & 1 deletion runewidth.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ func inTables(r rune, ts ...table) bool {
}

func inTable(r rune, t table) bool {
// func (t table) IncludesRune(r rune) bool {
if r < t[0].first {
return false
}
Expand Down
2 changes: 2 additions & 0 deletions runewidth_table.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 46 additions & 36 deletions runewidth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"unicode/utf8"
)

var _ sort.Interface = (*table)(nil)
var _ sort.Interface = (*table)(nil) // ensure that type "table" does implement sort.Interface

func init() {
os.Setenv("RUNEWIDTH_EASTASIAN", "")
Expand All @@ -30,51 +30,57 @@ func (t *table) Swap(i, j int) {
(*t)[i], (*t)[j] = (*t)[j], (*t)[i]
}

var tables = []table{
private,
nonprint,
combining,
doublewidth,
ambiguous,
emoji,
notassigned,
neutral,
type tableInfo struct {
tbl table
name string
wantN int
wantSHA string
}

var tables = []tableInfo{
{private, "private", 137468, "a4a641206dc8c5de80bd9f03515a54a706a5a4904c7684dc6a33d65c967a51b2"},
{nonprint, "nonprint", 2143, "288904683eb225e7c4c0bd3ee481b53e8dace404ec31d443afdbc4d13729fe95"},
{combining, "combining", 461, "ef1839ee99b2707da7d5592949bd9b40d434fa6462c6da61477bae923389e263"},
{doublewidth, "doublewidth", 181887, "de2d7a29c94fb2fe471b5fd0c003043845ce59d1823170606b95f9fc8988067a"},
{ambiguous, "ambiguous", 138739, "d05e339a10f296de6547ff3d6c5aee32f627f6555477afebd4a3b7e3cf74c9e3"},
{emoji, "emoji", 3791, "bf02b49f5cbee8df150053574d20125164e7f16b5f62aa5971abca3b2f39a8e6"},
{notassigned, "notassigned", 10, "68441e98eca1450efbe857ac051fcc872eed347054dfd0bc662d1c4ee021d69f"},
{neutral, "neutral", 26925, "d79d8558f3cc35c633e5025c9b29c005b853589c8f71b4a72507b5c31d8a6829"},
}

func TestTableChecksums(t *testing.T) {
check := func(name string, tbl table, wantN int, wantSHA string) {
for _, ti := range tables {
gotN := 0
buf := make([]byte, utf8.MaxRune+1)
for r := rune(0); r <= utf8.MaxRune; r++ {
if inTable(r, tbl) {
if inTable(r, ti.tbl) {
gotN++
buf[r] = 1
}
}
gotSHA := fmt.Sprintf("%x", sha256.Sum256(buf))
if gotN != wantN || gotSHA != wantSHA {
t.Errorf("table = %s,\n\tn = %d want %d,\n\tsha256 = %s want %s", name, gotN, wantN, gotSHA, wantSHA)
if gotN != ti.wantN || gotSHA != ti.wantSHA {
t.Errorf("table = %s,\n\tn = %d want %d,\n\tsha256 = %s want %s", ti.name, gotN, ti.wantN, gotSHA, ti.wantSHA)
}
}
}

check("private", private, 137468, "a4a641206dc8c5de80bd9f03515a54a706a5a4904c7684dc6a33d65c967a51b2")
check("notprint", nonprint, 2143, "288904683eb225e7c4c0bd3ee481b53e8dace404ec31d443afdbc4d13729fe95")
check("combining", combining, 461, "ef1839ee99b2707da7d5592949bd9b40d434fa6462c6da61477bae923389e263")
check("doublewidth", doublewidth, 181887, "de2d7a29c94fb2fe471b5fd0c003043845ce59d1823170606b95f9fc8988067a")
check("ambiguous", ambiguous, 138739, "d05e339a10f296de6547ff3d6c5aee32f627f6555477afebd4a3b7e3cf74c9e3")
check("emoji", emoji, 3791, "bf02b49f5cbee8df150053574d20125164e7f16b5f62aa5971abca3b2f39a8e6")
check("notassigned", notassigned, 10, "68441e98eca1450efbe857ac051fcc872eed347054dfd0bc662d1c4ee021d69f")
check("neutral", neutral, 26925, "d79d8558f3cc35c633e5025c9b29c005b853589c8f71b4a72507b5c31d8a6829")
func checkInterval(first, last rune) bool {
return first >= 0 && first <= utf8.MaxRune &&
last >= 0 && last <= utf8.MaxRune &&
first <= last
}

func isCompact(t *testing.T, tbl table) bool {
func isCompact(t *testing.T, ti *tableInfo) bool {
tbl := ti.tbl
for i := range tbl {
if tbl[i].last < tbl[i].first { // sanity check
t.Errorf("table invalid: %v", tbl[i])
e := tbl[i]
if !checkInterval(e.first, e.last) { // sanity check
t.Errorf("table invalid: table = %s index = %d %v", ti.name, i, e)
return false
}
if i+1 < len(tbl) && tbl[i].last+1 >= tbl[i+1].first { // can be combined into one entry
t.Errorf("table not compact: %v %v", tbl[i-1], tbl[i])
if i+1 < len(tbl) && e.last+1 >= tbl[i+1].first { // can be combined into one entry
t.Errorf("table not compact: table = %s index = %d %v %v", ti.name, i, e, tbl[i+1])
return false
}
}
Expand All @@ -100,26 +106,30 @@ func printCompactTable(tbl table) {
sort.Sort(&tbl) // just in case
first := rune(-1)
for i := range tbl {
e := tbl[i]
if !checkInterval(e.first, e.last) { // sanity check
panic("invalid table")
}
if first < 0 {
first = tbl[i].first
first = e.first
}
if i+1 < len(tbl) && tbl[i].last+1 >= tbl[i+1].first { // can be combined into one entry
if i+1 < len(tbl) && e.last+1 >= tbl[i+1].first { // can be combined into one entry
continue
}
printEntry(first, tbl[i].last)
printEntry(first, e.last)
first = -1
}
fmt.Printf("\n\n")
}

func TestSorted(t *testing.T) {
for _, tbl := range tables {
if !sort.IsSorted(&tbl) {
t.Errorf("table not sorted")
for _, ti := range tables {
if !sort.IsSorted(&ti.tbl) {
t.Errorf("table not sorted: %s", ti.name)
}
if !isCompact(t, tbl) {
t.Errorf("table not compact")
// printCompactTable(tbl)
if !isCompact(t, &ti) {
t.Errorf("table not compact: %s", ti.name)
//printCompactTable(ti.tbl)
}
}
}
Expand Down
27 changes: 20 additions & 7 deletions script/generate.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
// +build ignore

// Generate runewidth_table.go from data at https://unicode.org/

package main

import (
"bufio"
"bytes"
"fmt"
"go/format"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
)

Expand Down Expand Up @@ -75,7 +81,7 @@ func eastasian(out io.Writer, in io.Reader) error {
}

switch ss {
case "W","F":
case "W", "F":
dbl = append(dbl, rrange{
lo: r1,
hi: r2,
Expand Down Expand Up @@ -169,11 +175,9 @@ func emoji(out io.Writer, in io.Reader) error {
}

func main() {
f, err := os.Create("runewidth_table.go")
if err != nil {
log.Fatal(err)
}
defer f.Close()
var buf bytes.Buffer
f := &buf
fmt.Fprint(f, "// Code generated by script/generate.go. DO NOT EDIT.\n\n")

fmt.Fprint(f, "package runewidth\n\n")

Expand All @@ -192,4 +196,13 @@ func main() {
defer resp.Body.Close()

emoji(f, resp.Body)

out, err := format.Source(f.Bytes())
if err != nil {
log.Fatal(err)
}
err = ioutil.WriteFile("runewidth_table.go", out, 0666)
if err != nil {
log.Fatal(err)
}
}

0 comments on commit f9aa72c

Please sign in to comment.