...

Source file src/golang.org/x/text/internal/cldrtree/type.go

Documentation: golang.org/x/text/internal/cldrtree

     1  // Copyright 2017 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  package cldrtree
     6  
     7  import (
     8  	"log"
     9  	"strconv"
    10  )
    11  
    12  // enumIndex is the numerical value of an enum value.
    13  type enumIndex int
    14  
    15  // An enum is a collection of enum values.
    16  type enum struct {
    17  	name   string // the Go type of the enum
    18  	rename func(string) string
    19  	keyMap map[string]enumIndex
    20  	keys   []string
    21  }
    22  
    23  // lookup returns the index for the enum corresponding to the string. If s
    24  // currently does not exist it will add the entry.
    25  func (e *enum) lookup(s string) enumIndex {
    26  	if e.rename != nil {
    27  		s = e.rename(s)
    28  	}
    29  	x, ok := e.keyMap[s]
    30  	if !ok {
    31  		if e.keyMap == nil {
    32  			e.keyMap = map[string]enumIndex{}
    33  		}
    34  		u, err := strconv.ParseUint(s, 10, 32)
    35  		if err == nil {
    36  			for len(e.keys) <= int(u) {
    37  				x := enumIndex(len(e.keys))
    38  				s := strconv.Itoa(int(x))
    39  				e.keyMap[s] = x
    40  				e.keys = append(e.keys, s)
    41  			}
    42  			if e.keyMap[s] != enumIndex(u) {
    43  				// TODO: handle more gracefully.
    44  				log.Fatalf("cldrtree: mix of integer and non-integer for %q %v", s, e.keys)
    45  			}
    46  			return enumIndex(u)
    47  		}
    48  		x = enumIndex(len(e.keys))
    49  		e.keyMap[s] = x
    50  		e.keys = append(e.keys, s)
    51  	}
    52  	return x
    53  }
    54  
    55  // A typeInfo indicates the set of possible enum values and a mapping from
    56  // these values to subtypes.
    57  type typeInfo struct {
    58  	enum        *enum
    59  	entries     map[enumIndex]*typeInfo
    60  	keyTypeInfo *typeInfo
    61  	shareKeys   bool
    62  }
    63  
    64  func (t *typeInfo) sharedKeys() bool {
    65  	return t.shareKeys
    66  }
    67  
    68  func (t *typeInfo) lookupSubtype(s string, opts *options) (x enumIndex, sub *typeInfo) {
    69  	if t.enum == nil {
    70  		if t.enum = opts.sharedEnums; t.enum == nil {
    71  			t.enum = &enum{}
    72  		}
    73  	}
    74  	if opts.sharedEnums != nil && t.enum != opts.sharedEnums {
    75  		panic("incompatible enums defined")
    76  	}
    77  	x = t.enum.lookup(s)
    78  	if t.entries == nil {
    79  		t.entries = map[enumIndex]*typeInfo{}
    80  	}
    81  	sub, ok := t.entries[x]
    82  	if !ok {
    83  		sub = opts.sharedType
    84  		if sub == nil {
    85  			sub = &typeInfo{}
    86  		}
    87  		t.entries[x] = sub
    88  	}
    89  	t.shareKeys = opts.sharedType != nil // For analysis purposes.
    90  	return x, sub
    91  }
    92  
    93  // metaData includes information about subtypes, possibly sharing commonality
    94  // with sibling branches, and information about inheritance, which may differ
    95  // per branch.
    96  type metaData struct {
    97  	b *Builder
    98  
    99  	parent *metaData
   100  
   101  	index    enumIndex // index into the parent's subtype index
   102  	key      string
   103  	elem     string // XML element corresponding to this type.
   104  	typeInfo *typeInfo
   105  
   106  	lookup map[enumIndex]*metaData
   107  	subs   []*metaData
   108  
   109  	inheritOffset int    // always negative when applicable
   110  	inheritIndex  string // new value for field indicated by inheritOffset
   111  	// inheritType   *metaData
   112  }
   113  
   114  func (m *metaData) sub(key string, opts *options) *metaData {
   115  	if m.lookup == nil {
   116  		m.lookup = map[enumIndex]*metaData{}
   117  	}
   118  	enum, info := m.typeInfo.lookupSubtype(key, opts)
   119  	sub := m.lookup[enum]
   120  	if sub == nil {
   121  		sub = &metaData{
   122  			b:      m.b,
   123  			parent: m,
   124  
   125  			index:    enum,
   126  			key:      key,
   127  			typeInfo: info,
   128  		}
   129  		m.lookup[enum] = sub
   130  		m.subs = append(m.subs, sub)
   131  	}
   132  	return sub
   133  }
   134  
   135  func (m *metaData) validate() {
   136  	for _, s := range m.subs {
   137  		s.validate()
   138  	}
   139  }
   140  

View as plain text