Copyright 2013 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.
go:generate go run gen.go gen_index.go -output tables.gogo:generate go run gen_parents.go

package compact
TODO: Remove above NOTE after: - verifying that tables are dropped correctly (most notably matcher tables).

import (
	

	
)
Tag represents a BCP 47 language tag. It is used to specify an instance of a specific language or locale. All language tag values are guaranteed to be well-formed.
NOTE: exported tags will become part of the public API.
	language ID
	locale   ID
	full     fullTag // always a language.Tag for now.
}

const _und = 0

type fullTag interface {
	IsRoot() bool
	Parent() language.Tag
}
Make a compact Tag from a fully specified internal language Tag.
func ( language.Tag) ( Tag) {
	if  := .TypeForKey("rg"); len() == 6 && [2:] == "zzzz" {
		if ,  := language.ParseRegion([:2]);  == nil {
			 := 
TODO: should we not consider "va" for the language tag?
			var ,  bool
			.language,  = FromTag()
			.RegionID = 
			.locale,  = FromTag()
			if ! || ! {
				.full = 
			}
			return 
		}
	}
	,  := FromTag()
	.language = 
	.locale = 
	if ! {
		.full = 
	}
	return 
}
Tag returns an internal language Tag version of this tag.
func ( Tag) () language.Tag {
	if .full != nil {
		return .full.(language.Tag)
	}
	 := .language.Tag()
	if .language != .locale {
		 := .locale.Tag()
		, _ = .SetTypeForKey("rg", strings.ToLower(.RegionID.String())+"zzzz")
	}
	return 
}
IsCompact reports whether this tag is fully defined in terms of ID.
func ( *Tag) () bool {
	return .full == nil
}
MayHaveVariants reports whether a tag may have variants. If it returns false it is guaranteed the tag does not have variants.
func ( Tag) () bool {
	return .full != nil || int(.language) >= len(coreTags)
}
MayHaveExtensions reports whether a tag may have extensions. If it returns false it is guaranteed the tag does not have them.
func ( Tag) () bool {
	return .full != nil ||
		int(.language) >= len(coreTags) ||
		.language != .locale
}
IsRoot returns true if t is equal to language "und".
func ( Tag) () bool {
	if .full != nil {
		return .full.IsRoot()
	}
	return .language == _und
}
Parent returns the CLDR parent of t. In CLDR, missing fields in data for a specific language are substituted with fields from the parent language. The parent for a language may change for newer versions of CLDR.
func ( Tag) () Tag {
	if .full != nil {
		return Make(.full.Parent())
	}
Simulate stripping -u-rg-xxxxxx
TODO: use parent lookup table once cycle from internal package is removed. Probably by internalizing the table and declaring this fast enough. lang := compactID(internal.Parent(uint16(t.language)))
	,  := FromTag(.language.Tag().Parent())
	return Tag{language: , locale: }
}
returns token t and the rest of the string.
func ( string) (,  string) {
	 := strings.Index([1:], "-")
	if  == -1 {
		return [1:], ""
	}
	++
	return [1:], [:]
}
LanguageID returns an index, where 0 <= index < NumCompactTags, for tags for which data exists in the text repository.The index will change over time and should not be stored in persistent storage. If t does not match a compact index, exact will be false and the compact index will be returned for the first match after repeatedly taking the Parent of t.
func ( Tag) ( ID,  bool) {
	return .language, .full == nil
}
RegionalID returns the ID for the regional variant of this tag. This index is used to indicate region-specific overrides, such as default currency, default calendar and week data, default time cycle, and default measurement system and unit preferences. For instance, the tag en-GB-u-rg-uszzzz specifies British English with US settings for currency, number formatting, etc. The CompactIndex for this tag will be that for en-GB, while the RegionalID will be the one corresponding to en-US.
func ( Tag) ( ID,  bool) {
	return .locale, .full == nil
}
LanguageTag returns t stripped of regional variant indicators. At the moment this means it is stripped of a regional and variant subtag "rg" and "va" in the "u" extension.
func ( Tag) () Tag {
	if .full == nil {
		return Tag{language: .language, locale: .language}
	}
	 := .Tag()
	.SetTypeForKey("rg", "")
	.SetTypeForKey("va", "")
	return Make()
}
RegionalTag returns the regional variant of the tag. At the moment this means that the region is set from the regional subtag "rg" in the "u" extension.
func ( Tag) () Tag {
	 := Tag{language: .locale, locale: .locale}
	if .full == nil {
		return 
	}
	 := language.Builder{}
tag, _ = tag.SetTypeForKey("rg", "")
	.SetTag(.locale.Tag())
	if  := .Variants();  != "" {
		for ,  := range strings.Split(, "-") {
			.AddVariant()
		}
	}
	for ,  := range .Extensions() {
		.AddExt()
	}
	return 
}
FromTag reports closest matching ID for an internal language Tag.
TODO: perhaps give more frequent tags a lower index. TODO: we could make the indexes stable. This will excluded some possibilities for optimization, so don't do this quite yet.
	 = true

	, ,  := .Raw()
	if .HasString() {
We have no entries for user-defined tags.
			return 0, false
		}
		 := false
		if .HasVariants() {
			if .HasExtensions() {
				 := language.Builder{}
				.SetTag(language.Tag{LangID: , ScriptID: , RegionID: })
				.AddVariant(.Variants())
				 = false
				 = .Make()
			}
			 = true
TODO: va may mean something else. Consider not considering it. Strip all but the 'va' entry.
			 := 
			 := .TypeForKey("va")
			 = language.Tag{LangID: , ScriptID: , RegionID: }
			if  != "" {
				, _ = .SetTypeForKey("va", )
				 = true
			}
			 =  == 
		} else {
			 = false
		}
We have some variants.
			for ,  := range specialTags {
				if  ==  {
					return ID( + len(coreTags)), 
				}
			}
			 = false
		}
	}
	if ,  := getCoreIndex();  {
		return , 
	}
	 = false
Deal with cases where an extra script is inserted for the region.
		,  := .Maximize()
		if ,  := getCoreIndex();  {
			return , 
		}
	}
No variants specified: just compare core components. The key has the form lllssrrr, where l, s, and r are nibbles for respectively the langID, scriptID, and regionID.
		if ,  := getCoreIndex();  {
			return , 
		}
	}
	return 0, 
}