language/internal: include body of old compose This is like the old code but different. Prevents some internals from having to be exposed. Change-Id: Ibfd0c98e7ed276faab20789fd753f8ef5cf6bda5 Reviewed-on: https://go-review.googlesource.com/95820 Run-TryBot: Marcel van Lohuizen <mpvl@golang.org> Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/language/internal/compose.go b/language/internal/compose.go new file mode 100644 index 0000000..772c3d4 --- /dev/null +++ b/language/internal/compose.go
@@ -0,0 +1,101 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package language + +import ( + "sort" + "strings" +) + +type Builder struct { + Tag Tag + + Private string // the x extension + Ext []string + Variant []string + + Err error +} + +func (b *Builder) Make() Tag { + t := b.Tag + + if len(b.Ext) > 0 || len(b.Variant) > 0 { + sort.Sort(sortVariants(b.Variant)) + sort.Strings(b.Ext) + if b.Private != "" { + b.Ext = append(b.Ext, b.Private) + } + n := maxCoreSize + tokenLen(b.Variant...) + tokenLen(b.Ext...) + buf := make([]byte, n) + p := t.genCoreBytes(buf) + t.pVariant = byte(p) + p += appendTokens(buf[p:], b.Variant...) + t.pExt = uint16(p) + p += appendTokens(buf[p:], b.Ext...) + t.str = string(buf[:p]) + } else if b.Private != "" { + t.str = b.Private + t.RemakeString() + } + return t +} + +func (b *Builder) SetTag(t Tag) { + b.Tag.LangID = t.LangID + b.Tag.RegionID = t.RegionID + b.Tag.ScriptID = t.ScriptID + // TODO: optimize + b.Variant = b.Variant[:0] + if variants := t.Variants(); variants != "" { + for _, vr := range strings.Split(variants[1:], "-") { + b.Variant = append(b.Variant, vr) + } + } + b.Ext, b.Private = b.Ext[:0], "" + for _, e := range t.Extensions() { + b.AddExt(e) + } +} + +func (b *Builder) AddExt(e string) { + if e == "" { + } else if e[0] == 'x' { + b.Private = e + } else { + b.Ext = append(b.Ext, e) + } +} + +func tokenLen(token ...string) (n int) { + for _, t := range token { + n += len(t) + 1 + } + return +} + +func appendTokens(b []byte, token ...string) int { + p := 0 + for _, t := range token { + b[p] = '-' + copy(b[p+1:], t) + p += 1 + len(t) + } + return p +} + +type sortVariants []string + +func (s sortVariants) Len() int { + return len(s) +} + +func (s sortVariants) Swap(i, j int) { + s[j], s[i] = s[i], s[j] +} + +func (s sortVariants) Less(i, j int) bool { + return variantIndex[s[i]] < variantIndex[s[j]] +}