1// Copyright 2015 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// +build ignore
7
8package main
9
10// This code is shared between the main code generator and the test code.
11
12import (
13	"flag"
14	"log"
15	"strconv"
16	"strings"
17
18	"golang.org/x/text/internal/gen"
19	"golang.org/x/text/internal/ucd"
20)
21
22var (
23	outputFile = flag.String("out", "tables.go", "output file")
24)
25
26var typeMap = map[string]elem{
27	"A":  tagAmbiguous,
28	"N":  tagNeutral,
29	"Na": tagNarrow,
30	"W":  tagWide,
31	"F":  tagFullwidth,
32	"H":  tagHalfwidth,
33}
34
35// getWidthData calls f for every entry for which it is defined.
36//
37// f may be called multiple times for the same rune. The last call to f is the
38// correct value. f is not called for all runes. The default tag type is
39// Neutral.
40func getWidthData(f func(r rune, tag elem, alt rune)) {
41	// Set the default values for Unified Ideographs. In line with Annex 11,
42	// we encode full ranges instead of the defined runes in Unified_Ideograph.
43	for _, b := range []struct{ lo, hi rune }{
44		{0x4E00, 0x9FFF},   // the CJK Unified Ideographs block,
45		{0x3400, 0x4DBF},   // the CJK Unified Ideographs Externsion A block,
46		{0xF900, 0xFAFF},   // the CJK Compatibility Ideographs block,
47		{0x20000, 0x2FFFF}, // the Supplementary Ideographic Plane,
48		{0x30000, 0x3FFFF}, // the Tertiary Ideographic Plane,
49	} {
50		for r := b.lo; r <= b.hi; r++ {
51			f(r, tagWide, 0)
52		}
53	}
54
55	inverse := map[rune]rune{}
56	maps := map[string]bool{
57		"<wide>":   true,
58		"<narrow>": true,
59	}
60
61	// We cannot reuse package norm's decomposition, as we need an unexpanded
62	// decomposition. We make use of the opportunity to verify that the
63	// decomposition type is as expected.
64	ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
65		r := p.Rune(0)
66		s := strings.SplitN(p.String(ucd.DecompMapping), " ", 2)
67		if !maps[s[0]] {
68			return
69		}
70		x, err := strconv.ParseUint(s[1], 16, 32)
71		if err != nil {
72			log.Fatalf("Error parsing rune %q", s[1])
73		}
74		if inverse[r] != 0 || inverse[rune(x)] != 0 {
75			log.Fatalf("Circular dependency in mapping between %U and %U", r, x)
76		}
77		inverse[r] = rune(x)
78		inverse[rune(x)] = r
79	})
80
81	// <rune range>;<type>
82	ucd.Parse(gen.OpenUCDFile("EastAsianWidth.txt"), func(p *ucd.Parser) {
83		tag, ok := typeMap[p.String(1)]
84		if !ok {
85			log.Fatalf("Unknown width type %q", p.String(1))
86		}
87		r := p.Rune(0)
88		alt, ok := inverse[r]
89		if tag == tagFullwidth || tag == tagHalfwidth && r != wonSign {
90			tag |= tagNeedsFold
91			if !ok {
92				log.Fatalf("Narrow or wide rune %U has no decomposition", r)
93			}
94		}
95		f(r, tag, alt)
96	})
97}
98