...

Source file src/golang.org/x/text/unicode/runenames/gen.go

Documentation: golang.org/x/text/unicode/runenames

     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  //go:build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"log"
    12  	"sort"
    13  	"strings"
    14  
    15  	"golang.org/x/text/internal/gen"
    16  	"golang.org/x/text/internal/gen/bitfield"
    17  	"golang.org/x/text/internal/ucd"
    18  )
    19  
    20  var (
    21  	// computed by computeDirectOffsets
    22  	directOffsets = map[string]int{}
    23  	directData    bytes.Buffer
    24  
    25  	// computed by computeEntries
    26  	entries    []entry
    27  	singleData bytes.Buffer
    28  	index      []uint16
    29  )
    30  
    31  type entry struct {
    32  	start    rune `bitfield:"21,startRune"`
    33  	numRunes int  `bitfield:"16"`
    34  	end      rune
    35  	index    int  `bitfield:"16"`
    36  	base     int  `bitfield:"6"`
    37  	direct   bool `bitfield:""`
    38  	name     string
    39  }
    40  
    41  func main() {
    42  	gen.Init()
    43  
    44  	w := gen.NewCodeWriter()
    45  	defer w.WriteVersionedGoFile("tables.go", "runenames")
    46  
    47  	gen.WriteUnicodeVersion(w)
    48  
    49  	computeDirectOffsets()
    50  	computeEntries()
    51  
    52  	if err := bitfield.Gen(w, entry{}, nil); err != nil {
    53  		log.Fatal(err)
    54  	}
    55  
    56  	type entry uint64 // trick the generation code to use the entry type
    57  	packed := []entry{}
    58  	for _, e := range entries {
    59  		e.numRunes = int(e.end - e.start + 1)
    60  		v, err := bitfield.Pack(e, nil)
    61  		if err != nil {
    62  			log.Fatal(err)
    63  		}
    64  		packed = append(packed, entry(v))
    65  	}
    66  
    67  	index = append(index, uint16(singleData.Len()))
    68  
    69  	w.WriteVar("entries", packed)
    70  	w.WriteVar("index", index)
    71  	w.WriteConst("directData", directData.String())
    72  	w.WriteConst("singleData", singleData.String())
    73  }
    74  
    75  func computeDirectOffsets() {
    76  	counts := map[string]int{}
    77  
    78  	p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
    79  	for p.Next() {
    80  		start, end := p.Range(0)
    81  		counts[getName(p)] += int(end-start) + 1
    82  	}
    83  
    84  	direct := []string{}
    85  	for k, v := range counts {
    86  		if v > 1 {
    87  			direct = append(direct, k)
    88  		}
    89  	}
    90  	sort.Strings(direct)
    91  
    92  	for _, s := range direct {
    93  		directOffsets[s] = directData.Len()
    94  		directData.WriteString(s)
    95  	}
    96  }
    97  
    98  func computeEntries() {
    99  	p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
   100  	for p.Next() {
   101  		start, end := p.Range(0)
   102  
   103  		last := entry{}
   104  		if len(entries) > 0 {
   105  			last = entries[len(entries)-1]
   106  		}
   107  
   108  		name := getName(p)
   109  		if index, ok := directOffsets[name]; ok {
   110  			if last.name == name && last.end+1 == start {
   111  				entries[len(entries)-1].end = end
   112  				continue
   113  			}
   114  			entries = append(entries, entry{
   115  				start:  start,
   116  				end:    end,
   117  				index:  index,
   118  				base:   len(name),
   119  				direct: true,
   120  				name:   name,
   121  			})
   122  			continue
   123  		}
   124  
   125  		if start != end {
   126  			log.Fatalf("Expected start == end, found %x != %x", start, end)
   127  		}
   128  
   129  		offset := singleData.Len()
   130  		base := offset >> 16
   131  		index = append(index, uint16(offset))
   132  		singleData.WriteString(name)
   133  
   134  		if last.base == base && last.end+1 == start {
   135  			entries[len(entries)-1].end = start
   136  			continue
   137  		}
   138  
   139  		entries = append(entries, entry{
   140  			start: start,
   141  			end:   end,
   142  			index: len(index) - 1,
   143  			base:  base,
   144  			name:  name,
   145  		})
   146  	}
   147  }
   148  
   149  func getName(p *ucd.Parser) string {
   150  	s := p.String(ucd.Name)
   151  	if s == "" {
   152  		return ""
   153  	}
   154  	if s[0] == '<' {
   155  		const first = ", First>"
   156  		if i := strings.Index(s, first); i >= 0 {
   157  			s = s[:i] + ">"
   158  		}
   159  
   160  	}
   161  	return s
   162  }
   163  

View as plain text