mirror of
				https://github.com/go-gitea/gitea
				synced 2025-09-28 03:28:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			168 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| // 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"
 | |
| )
 | |
| 
 | |
| // A Builder allows constructing a Tag from individual components.
 | |
| // Its main user is Compose in the top-level language package.
 | |
| type Builder struct {
 | |
| 	Tag Tag
 | |
| 
 | |
| 	private    string // the x extension
 | |
| 	variants   []string
 | |
| 	extensions []string
 | |
| }
 | |
| 
 | |
| // Make returns a new Tag from the current settings.
 | |
| func (b *Builder) Make() Tag {
 | |
| 	t := b.Tag
 | |
| 
 | |
| 	if len(b.extensions) > 0 || len(b.variants) > 0 {
 | |
| 		sort.Sort(sortVariants(b.variants))
 | |
| 		sort.Strings(b.extensions)
 | |
| 
 | |
| 		if b.private != "" {
 | |
| 			b.extensions = append(b.extensions, b.private)
 | |
| 		}
 | |
| 		n := maxCoreSize + tokenLen(b.variants...) + tokenLen(b.extensions...)
 | |
| 		buf := make([]byte, n)
 | |
| 		p := t.genCoreBytes(buf)
 | |
| 		t.pVariant = byte(p)
 | |
| 		p += appendTokens(buf[p:], b.variants...)
 | |
| 		t.pExt = uint16(p)
 | |
| 		p += appendTokens(buf[p:], b.extensions...)
 | |
| 		t.str = string(buf[:p])
 | |
| 		// We may not always need to remake the string, but when or when not
 | |
| 		// to do so is rather tricky.
 | |
| 		scan := makeScanner(buf[:p])
 | |
| 		t, _ = parse(&scan, "")
 | |
| 		return t
 | |
| 
 | |
| 	} else if b.private != "" {
 | |
| 		t.str = b.private
 | |
| 		t.RemakeString()
 | |
| 	}
 | |
| 	return t
 | |
| }
 | |
| 
 | |
| // SetTag copies all the settings from a given Tag. Any previously set values
 | |
| // are discarded.
 | |
| func (b *Builder) SetTag(t Tag) {
 | |
| 	b.Tag.LangID = t.LangID
 | |
| 	b.Tag.RegionID = t.RegionID
 | |
| 	b.Tag.ScriptID = t.ScriptID
 | |
| 	// TODO: optimize
 | |
| 	b.variants = b.variants[:0]
 | |
| 	if variants := t.Variants(); variants != "" {
 | |
| 		for _, vr := range strings.Split(variants[1:], "-") {
 | |
| 			b.variants = append(b.variants, vr)
 | |
| 		}
 | |
| 	}
 | |
| 	b.extensions, b.private = b.extensions[:0], ""
 | |
| 	for _, e := range t.Extensions() {
 | |
| 		b.AddExt(e)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // AddExt adds extension e to the tag. e must be a valid extension as returned
 | |
| // by Tag.Extension. If the extension already exists, it will be discarded,
 | |
| // except for a -u extension, where non-existing key-type pairs will added.
 | |
| func (b *Builder) AddExt(e string) {
 | |
| 	if e[0] == 'x' {
 | |
| 		if b.private == "" {
 | |
| 			b.private = e
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 	for i, s := range b.extensions {
 | |
| 		if s[0] == e[0] {
 | |
| 			if e[0] == 'u' {
 | |
| 				b.extensions[i] += e[1:]
 | |
| 			}
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	b.extensions = append(b.extensions, e)
 | |
| }
 | |
| 
 | |
| // SetExt sets the extension e to the tag. e must be a valid extension as
 | |
| // returned by Tag.Extension. If the extension already exists, it will be
 | |
| // overwritten, except for a -u extension, where the individual key-type pairs
 | |
| // will be set.
 | |
| func (b *Builder) SetExt(e string) {
 | |
| 	if e[0] == 'x' {
 | |
| 		b.private = e
 | |
| 		return
 | |
| 	}
 | |
| 	for i, s := range b.extensions {
 | |
| 		if s[0] == e[0] {
 | |
| 			if e[0] == 'u' {
 | |
| 				b.extensions[i] = e + s[1:]
 | |
| 			} else {
 | |
| 				b.extensions[i] = e
 | |
| 			}
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	b.extensions = append(b.extensions, e)
 | |
| }
 | |
| 
 | |
| // AddVariant adds any number of variants.
 | |
| func (b *Builder) AddVariant(v ...string) {
 | |
| 	for _, v := range v {
 | |
| 		if v != "" {
 | |
| 			b.variants = append(b.variants, v)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ClearVariants removes any variants previously added, including those
 | |
| // copied from a Tag in SetTag.
 | |
| func (b *Builder) ClearVariants() {
 | |
| 	b.variants = b.variants[:0]
 | |
| }
 | |
| 
 | |
| // ClearExtensions removes any extensions previously added, including those
 | |
| // copied from a Tag in SetTag.
 | |
| func (b *Builder) ClearExtensions() {
 | |
| 	b.private = ""
 | |
| 	b.extensions = b.extensions[:0]
 | |
| }
 | |
| 
 | |
| 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]]
 | |
| }
 |