github.com/go-xe2/third@v1.0.3/golang.org/x/text/unicode/runenames/gen.go (about)

     1  // Copyright 2016 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  // +build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"log"
    11  	"strings"
    12  	"unicode"
    13  
    14  	"github.com/go-xe2/third/golang.org/x/text/internal/gen"
    15  	"github.com/go-xe2/third/golang.org/x/text/internal/ucd"
    16  )
    17  
    18  // snippet is a slice of data; data is the concatenation of all of the names.
    19  type snippet struct {
    20  	offset int
    21  	length int
    22  	s      string
    23  }
    24  
    25  func makeTable0EntryDirect(rOffset, rLength, dOffset, dLength int) uint64 {
    26  	if rOffset >= 1<<bitsRuneOffset {
    27  		log.Fatalf("makeTable0EntryDirect: rOffset %d is too large", rOffset)
    28  	}
    29  	if rLength >= 1<<bitsRuneLength {
    30  		log.Fatalf("makeTable0EntryDirect: rLength %d is too large", rLength)
    31  	}
    32  	if dOffset >= 1<<bitsDataOffset {
    33  		log.Fatalf("makeTable0EntryDirect: dOffset %d is too large", dOffset)
    34  	}
    35  	if dLength >= 1<<bitsRuneLength {
    36  		log.Fatalf("makeTable0EntryDirect: dLength %d is too large", dLength)
    37  	}
    38  	return uint64(rOffset)<<shiftRuneOffset |
    39  		uint64(rLength)<<shiftRuneLength |
    40  		uint64(dOffset)<<shiftDataOffset |
    41  		uint64(dLength)<<shiftDataLength |
    42  		1 // Direct bit.
    43  }
    44  
    45  func makeTable0EntryIndirect(rOffset, rLength, dBase, t1Offset int) uint64 {
    46  	if rOffset >= 1<<bitsRuneOffset {
    47  		log.Fatalf("makeTable0EntryIndirect: rOffset %d is too large", rOffset)
    48  	}
    49  	if rLength >= 1<<bitsRuneLength {
    50  		log.Fatalf("makeTable0EntryIndirect: rLength %d is too large", rLength)
    51  	}
    52  	if dBase >= 1<<bitsDataBase {
    53  		log.Fatalf("makeTable0EntryIndirect: dBase %d is too large", dBase)
    54  	}
    55  	if t1Offset >= 1<<bitsTable1Offset {
    56  		log.Fatalf("makeTable0EntryIndirect: t1Offset %d is too large", t1Offset)
    57  	}
    58  	return uint64(rOffset)<<shiftRuneOffset |
    59  		uint64(rLength)<<shiftRuneLength |
    60  		uint64(dBase)<<shiftDataBase |
    61  		uint64(t1Offset)<<shiftTable1Offset |
    62  		0 // Direct bit.
    63  }
    64  
    65  func makeTable1Entry(x int) uint16 {
    66  	if x < 0 || 0xffff < x {
    67  		log.Fatalf("makeTable1Entry: entry %d is out of range", x)
    68  	}
    69  	return uint16(x)
    70  }
    71  
    72  var (
    73  	data     []byte
    74  	snippets = make([]snippet, 1+unicode.MaxRune)
    75  )
    76  
    77  func main() {
    78  	gen.Init()
    79  
    80  	names, counts := parse()
    81  	appendRepeatNames(names, counts)
    82  	appendUniqueNames(names, counts)
    83  
    84  	table0, table1 := makeTables()
    85  
    86  	gen.Repackage("gen_bits.go", "bits.go", "runenames")
    87  
    88  	w := gen.NewCodeWriter()
    89  	w.WriteVar("table0", table0)
    90  	w.WriteVar("table1", table1)
    91  	w.WriteConst("data", string(data))
    92  	w.WriteGoFile("tables.go", "runenames")
    93  }
    94  
    95  func parse() (names []string, counts map[string]int) {
    96  	names = make([]string, 1+unicode.MaxRune)
    97  	counts = map[string]int{}
    98  	ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
    99  		r, s := p.Rune(0), p.String(ucd.Name)
   100  		if s == "" {
   101  			return
   102  		}
   103  		if s[0] == '<' {
   104  			const first = ", First>"
   105  			if i := strings.Index(s, first); i >= 0 {
   106  				s = s[:i] + ">"
   107  			}
   108  		}
   109  		names[r] = s
   110  		counts[s]++
   111  	})
   112  	return names, counts
   113  }
   114  
   115  func appendRepeatNames(names []string, counts map[string]int) {
   116  	alreadySeen := map[string]snippet{}
   117  	for r, s := range names {
   118  		if s == "" || counts[s] == 1 {
   119  			continue
   120  		}
   121  		if s[0] != '<' {
   122  			log.Fatalf("Repeated name %q does not start with a '<'", s)
   123  		}
   124  
   125  		if z, ok := alreadySeen[s]; ok {
   126  			snippets[r] = z
   127  			continue
   128  		}
   129  
   130  		z := snippet{
   131  			offset: len(data),
   132  			length: len(s),
   133  			s:      s,
   134  		}
   135  		data = append(data, s...)
   136  		snippets[r] = z
   137  		alreadySeen[s] = z
   138  	}
   139  }
   140  
   141  func appendUniqueNames(names []string, counts map[string]int) {
   142  	for r, s := range names {
   143  		if s == "" || counts[s] != 1 {
   144  			continue
   145  		}
   146  		if s[0] == '<' {
   147  			log.Fatalf("Unique name %q starts with a '<'", s)
   148  		}
   149  
   150  		z := snippet{
   151  			offset: len(data),
   152  			length: len(s),
   153  			s:      s,
   154  		}
   155  		data = append(data, s...)
   156  		snippets[r] = z
   157  	}
   158  }
   159  
   160  func makeTables() (table0 []uint64, table1 []uint16) {
   161  	for i := 0; i < len(snippets); {
   162  		zi := snippets[i]
   163  		if zi == (snippet{}) {
   164  			i++
   165  			continue
   166  		}
   167  
   168  		// Look for repeat names. If we have one, we only need a table0 entry.
   169  		j := i + 1
   170  		for ; j < len(snippets) && zi == snippets[j]; j++ {
   171  		}
   172  		if j > i+1 {
   173  			table0 = append(table0, makeTable0EntryDirect(i, j-i, zi.offset, zi.length))
   174  			i = j
   175  			continue
   176  		}
   177  
   178  		// Otherwise, we have a run of unique names. We need one table0 entry
   179  		// and two or more table1 entries.
   180  		base := zi.offset &^ (1<<dataBaseUnit - 1)
   181  		t1Offset := len(table1) + 1
   182  		table1 = append(table1, makeTable1Entry(zi.offset-base))
   183  		table1 = append(table1, makeTable1Entry(zi.offset+zi.length-base))
   184  		for ; j < len(snippets) && snippets[j] != (snippet{}); j++ {
   185  			zj := snippets[j]
   186  			if data[zj.offset] == '<' {
   187  				break
   188  			}
   189  			table1 = append(table1, makeTable1Entry(zj.offset+zj.length-base))
   190  		}
   191  		table0 = append(table0, makeTable0EntryIndirect(i, j-i, base>>dataBaseUnit, t1Offset))
   192  		i = j
   193  	}
   194  	return table0, table1
   195  }